History

TimeSeriesPlatformLibrary: Added temporal support options to DataPublisher interfaces.

J. Ritchie Carroll committed 7 years ago

Commit 5c5b4061 parent 04505f228 files · +603 −300Browse files

Showing the changes to Source/Libraries/TimeSeriesPlatformLibrary/Transport (11 of 28 files). Show all

Unified · Split

11 files
  1. Source/Libraries/TimeSeriesPlatformLibrary/Transport/DataPublisher.cpp +94 −34
  2. Source/Libraries/TimeSeriesPlatformLibrary/Transport/DataPublisher.h +34 −13
  3. Source/Libraries/TimeSeriesPlatformLibrary/Transport/DataSubscriber.h +10 −9
  4. Source/Libraries/TimeSeriesPlatformLibrary/Transport/PublisherInstance.cpp +32 −8
  5. Source/Libraries/TimeSeriesPlatformLibrary/Transport/PublisherInstance.h +8 −4
  6. Source/Libraries/TimeSeriesPlatformLibrary/Transport/SubscriberConnection.cpp +114 −58
  7. Source/Libraries/TimeSeriesPlatformLibrary/Transport/SubscriberConnection.h +48 −5
  8. Source/Libraries/TimeSeriesPlatformLibrary/Transport/SubscriberInstance.cpp +4 −4
  9. Source/Libraries/TimeSeriesPlatformLibrary/Transport/SubscriberInstance.h +1 −1
  10. Source/Libraries/TimeSeriesPlatformLibrary/Transport/TransportTypes.cpp +18 −1
  11. Source/Libraries/TimeSeriesPlatformLibrary/Transport/TransportTypes.h +5 −4
Source/Libraries/TimeSeriesPlatformLibrary/Transport/DataPublisher.cpp+94−34
@@ -36,24 +36,13 @@ using namespace GSF::FilterExpressions; · 35 unmodified lines
36using namespace GSF::TimeSeries;36using namespace GSF::TimeSeries;
37using namespace GSF::TimeSeries::Transport;37using namespace GSF::TimeSeries::Transport;
38 38
39struct SubscriberConnectionInfo
40{
41 const GSF::Guid SubscriberID;
42 const string ConnectionID;
43
44 SubscriberConnectionInfo(const GSF::Guid& subscriberID, string connectionID) :
45 SubscriberID(subscriberID),
46 ConnectionID(std::move(connectionID))
47 {
48 }
49};
50
51DataPublisher::DataPublisher(const TcpEndPoint& endpoint) :39DataPublisher::DataPublisher(const TcpEndPoint& endpoint) :
52 m_nodeID(NewGuid()),40 m_nodeID(NewGuid()),
53 m_securityMode(SecurityMode::None),41 m_securityMode(SecurityMode::None),
54 m_allowMetadataRefresh(true),42 m_allowMetadataRefresh(true),
55 m_allowNaNValueFilter(true),43 m_allowNaNValueFilter(true),
56 m_forceNaNValueFilter(false),44 m_forceNaNValueFilter(false),
45 m_supportsTemporalSubscriptions(false),
57 m_cipherKeyRotationPeriod(60000),46 m_cipherKeyRotationPeriod(60000),
58 m_userData(nullptr),47 m_userData(nullptr),
59 m_disposing(false),48 m_disposing(false),
@@ -116,19 +105,21 @@ void DataPublisher::AcceptConnection(const SubscriberConnectionPtr& connection, · 56 unmodified lines
116 m_subscriberConnectionsLock.unlock();105 m_subscriberConnectionsLock.unlock();
117 106
118 connection->Start();107 connection->Start();
119 DispatchClientConnected(connection->GetSubscriberID(), connection->GetConnectionID());108 DispatchClientConnected(connection);
120 }109 }
121 110
122 StartAccept();111 StartAccept();
123}112}
124 113
114void DataPublisher::ConnectionTerminated(const SubscriberConnectionPtr& connection)
115{
116 DispatchClientDisconnected(connection);
117}
118
125void DataPublisher::RemoveConnection(const SubscriberConnectionPtr& connection)119void DataPublisher::RemoveConnection(const SubscriberConnectionPtr& connection)
126{120{
127 m_subscriberConnectionsLock.lock();121 m_subscriberConnectionsLock.lock();
128 122 m_subscriberConnections.erase(connection);
129 if (m_subscriberConnections.erase(connection))
130 DispatchClientDisconnected(connection->GetSubscriberID(), connection->GetConnectionID());
131
132 m_subscriberConnectionsLock.unlock();123 m_subscriberConnectionsLock.unlock();
133}124}
134 125
@@ -169,16 +160,28 @@ void DataPublisher::DispatchErrorMessage(const string& message) · 34 unmodified lines
169 Dispatch(&ErrorMessageDispatcher, reinterpret_cast<const uint8_t*>(message.c_str()), 0, messageSize);160 Dispatch(&ErrorMessageDispatcher, reinterpret_cast<const uint8_t*>(message.c_str()), 0, messageSize);
170}161}
171 162
172void DataPublisher::DispatchClientConnected(const GSF::Guid& subscriberID, const string& connectionID)163void DataPublisher::DispatchClientConnected(const SubscriberConnectionPtr& connection)
164{
165 SubscriberConnection* connectionReference = &*connection;
166 Dispatch(&ClientConnectedDispatcher, reinterpret_cast<uint8_t*>(&connectionReference), 0, sizeof(SubscriberConnection**));
167}
168
169void DataPublisher::DispatchClientDisconnected(const SubscriberConnectionPtr& connection)
170{
171 SubscriberConnection* connectionReference = &*connection;
172 Dispatch(&ClientDisconnectedDispatcher, reinterpret_cast<uint8_t*>(&connectionReference), 0, sizeof(SubscriberConnection**));
173}
174
175void DataPublisher::DispatchTemporalSubscriptionRequested(const SubscriberConnectionPtr& connection)
173{176{
174 SubscriberConnectionInfo* data = new SubscriberConnectionInfo(subscriberID, connectionID);177 SubscriberConnection* connectionReference = &*connection;
175 Dispatch(&ClientConnectedDispatcher, reinterpret_cast<uint8_t*>(&data), 0, sizeof(SubscriberConnectionInfo**));178 Dispatch(&TemporalSubscriptionRequestedDispatcher, reinterpret_cast<uint8_t*>(&connectionReference), 0, sizeof(SubscriberConnection**));
176}179}
177 180
178void DataPublisher::DispatchClientDisconnected(const GSF::Guid& subscriberID, const std::string& connectionID)181void DataPublisher::DispatchTemporalProcessingIntervalChangeRequested(const SubscriberConnectionPtr& connection)
179{182{
180 SubscriberConnectionInfo* data = new SubscriberConnectionInfo(subscriberID, connectionID);183 SubscriberConnection* connectionReference = &*connection;
181 Dispatch(&ClientDisconnectedDispatcher, reinterpret_cast<uint8_t*>(&data), 0, sizeof(SubscriberConnectionInfo**));184 Dispatch(&TemporalProcessingIntervalChangeRequestedDispatcher, reinterpret_cast<uint8_t*>(&connectionReference), 0, sizeof(SubscriberConnection**));
182}185}
183 186
184// Dispatcher function for status messages. Decodes the message and provides it to the user via the status message callback.187// Dispatcher function for status messages. Decodes the message and provides it to the user via the status message callback.
@@ -207,32 +210,56 @@ void DataPublisher::ErrorMessageDispatcher(DataPublisher* source, const vector<u · 22 unmodified lines
207 210
208void DataPublisher::ClientConnectedDispatcher(DataPublisher* source, const vector<uint8_t>& buffer)211void DataPublisher::ClientConnectedDispatcher(DataPublisher* source, const vector<uint8_t>& buffer)
209{212{
210 SubscriberConnectionInfo* data = *reinterpret_cast<SubscriberConnectionInfo**>(const_cast<uint8_t*>(&buffer[0]));213 SubscriberConnection* connection = *reinterpret_cast<SubscriberConnection**>(const_cast<uint8_t*>(&buffer[0]));
211 214
212 if (source != nullptr)215 if (source != nullptr)
213 {216 {
214 const SubscriberConnectionCallback clientConnectedCallback = source->m_clientConnectedCallback;217 const SubscriberConnectionCallback clientConnectedCallback = source->m_clientConnectedCallback;
215 218
216 if (clientConnectedCallback != nullptr)219 if (clientConnectedCallback != nullptr)
217 clientConnectedCallback(source, data->SubscriberID, data->ConnectionID);220 clientConnectedCallback(source, connection->GetReference());
218 }221 }
219
220 delete data;
221}222}
222 223
223void DataPublisher::ClientDisconnectedDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer)224void DataPublisher::ClientDisconnectedDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer)
224{225{
225 SubscriberConnectionInfo* data = *reinterpret_cast<SubscriberConnectionInfo**>(const_cast<uint8_t*>(&buffer[0]));226 SubscriberConnection* connection = *reinterpret_cast<SubscriberConnection**>(const_cast<uint8_t*>(&buffer[0]));
226 227
227 if (source != nullptr)228 if (source != nullptr)
228 {229 {
229 const SubscriberConnectionCallback clientDisconnectedCallback = source->m_clientDisconnectedCallback;230 const SubscriberConnectionCallback clientDisconnectedCallback = source->m_clientDisconnectedCallback;
230 231
231 if (clientDisconnectedCallback != nullptr)232 if (clientDisconnectedCallback != nullptr)
232 clientDisconnectedCallback(source, data->SubscriberID, data->ConnectionID);233 clientDisconnectedCallback(source, connection->GetReference());
234
235 source->RemoveConnection(connection->GetReference());
236 }
237}
238
239void DataPublisher::TemporalSubscriptionRequestedDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer)
240{
241 SubscriberConnection* connection = *reinterpret_cast<SubscriberConnection**>(const_cast<uint8_t*>(&buffer[0]));
242
243 if (source != nullptr)
244 {
245 const SubscriberConnectionCallback temporalSubscriptionRequestedCallback = source->m_temporalSubscriptionRequestedCallback;
246
247 if (temporalSubscriptionRequestedCallback != nullptr)
248 temporalSubscriptionRequestedCallback(source, connection->GetReference());
233 }249 }
250}
251
252void DataPublisher::TemporalProcessingIntervalChangeRequestedDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer)
253{
254 SubscriberConnection* connection = *reinterpret_cast<SubscriberConnection**>(const_cast<uint8_t*>(&buffer[0]));
255
256 if (source != nullptr)
257 {
258 const SubscriberConnectionCallback temporalProcessingIntervalChangeRequestedCallback = source->m_temporalProcessingIntervalChangeRequestedCallback;
234 259
235 delete data;260 if (temporalProcessingIntervalChangeRequestedCallback != nullptr)
261 temporalProcessingIntervalChangeRequestedCallback(source, connection->GetReference());
262 }
236}263}
237 264
238int32_t DataPublisher::GetColumnIndex(const GSF::Data::DataTablePtr& table, const std::string& columnName)265int32_t DataPublisher::GetColumnIndex(const GSF::Data::DataTablePtr& table, const std::string& columnName)
@@ -683,14 +710,27 @@ vector<MeasurementMetadataPtr> DataPublisher::FilterMetadata(const string& filte · 444 unmodified lines
683 710
684void DataPublisher::PublishMeasurements(const vector<Measurement>& measurements)711void DataPublisher::PublishMeasurements(const vector<Measurement>& measurements)
685{712{
686 for (const auto& connection : m_subscriberConnections)713 vector<MeasurementPtr> measurementPtrs;
687 connection->PublishMeasurements(measurements);714
715 measurementPtrs.reserve(measurements.size());
716
717 for (const auto& measurement : measurements)
718 measurementPtrs.push_back(ToPtr(measurement));
719
720 PublishMeasurements(measurementPtrs);
688}721}
689 722
690void DataPublisher::PublishMeasurements(const vector<MeasurementPtr>& measurements)723void DataPublisher::PublishMeasurements(const vector<MeasurementPtr>& measurements)
691{724{
725 m_subscriberConnectionsLock.lock();
726
692 for (const auto& connection : m_subscriberConnections)727 for (const auto& connection : m_subscriberConnections)
693 connection->PublishMeasurements(measurements);728 {
729 if (connection->GetIsSubscribed() && !connection->GetIsTemporalSubscription())
730 connection->PublishMeasurements(measurements);
731 }
732
733 m_subscriberConnectionsLock.unlock();
694}734}
695 735
696const GSF::Guid& DataPublisher::GetNodeID() const736const GSF::Guid& DataPublisher::GetNodeID() const
@@ -743,6 +783,16 @@ void DataPublisher::SetNaNValueFilterForced(bool forced) · 46 unmodified lines
743 m_forceNaNValueFilter = forced;783 m_forceNaNValueFilter = forced;
744}784}
745 785
786bool DataPublisher::GetSupportsTemporalSubscriptions() const
787{
788 return m_supportsTemporalSubscriptions;
789}
790
791void DataPublisher::SetSupportsTemporalSubscriptions(bool value)
792{
793 m_supportsTemporalSubscriptions = value;
794}
795
746uint32_t DataPublisher::GetCipherKeyRotationPeriod() const796uint32_t DataPublisher::GetCipherKeyRotationPeriod() const
747{797{
748 return m_cipherKeyRotationPeriod;798 return m_cipherKeyRotationPeriod;
@@ -823,4 +873,14 @@ void DataPublisher::RegisterClientConnectedCallback(const SubscriberConnectionCa · 74 unmodified lines
823void DataPublisher::RegisterClientDisconnectedCallback(const SubscriberConnectionCallback& clientDisconnectedCallback)873void DataPublisher::RegisterClientDisconnectedCallback(const SubscriberConnectionCallback& clientDisconnectedCallback)
824{874{
825 m_clientDisconnectedCallback = clientDisconnectedCallback;875 m_clientDisconnectedCallback = clientDisconnectedCallback;
826}876}
877
878void DataPublisher::RegisterTemporalSubscriptionRequestedCallback(const SubscriberConnectionCallback& temporalSubscriptionRequestedCallback)
879{
880 m_temporalSubscriptionRequestedCallback = temporalSubscriptionRequestedCallback;
881}
882
883void DataPublisher::RegisterTemporalProcessingIntervalChangeRequestedCallback(const SubscriberConnectionCallback& temporalProcessingIntervalChangeRequestedCallback)
884{
885 m_temporalProcessingIntervalChangeRequestedCallback = temporalProcessingIntervalChangeRequestedCallback;
886}
Source/Libraries/TimeSeriesPlatformLibrary/Transport/DataPublisher.h+34−13
@@ -44,12 +44,13 @@ namespace Transport · 43 unmodified lines
44{44{
45 class DataPublisher : public EnableSharedThisPtr<DataPublisher> // NOLINT45 class DataPublisher : public EnableSharedThisPtr<DataPublisher> // NOLINT
46 {46 {
47 private:47 public:
48 // Function pointer types48 // Function pointer types
49 typedef std::function<void(DataPublisher*, const std::vector<uint8_t>&)> DispatcherFunction;49 typedef std::function<void(DataPublisher*, const std::vector<uint8_t>&)> DispatcherFunction;
50 typedef std::function<void(DataPublisher*, const std::string&)> MessageCallback;50 typedef std::function<void(DataPublisher*, const std::string&)> MessageCallback;
51 typedef std::function<void(DataPublisher*, const GSF::Guid&, const std::string&)> SubscriberConnectionCallback;51 typedef std::function<void(DataPublisher*, const SubscriberConnectionPtr&)> SubscriberConnectionCallback;
52 52
53 private:
53 // Structure used to dispatch54 // Structure used to dispatch
54 // callbacks on the callback thread.55 // callbacks on the callback thread.
55 struct CallbackDispatcher56 struct CallbackDispatcher
@@ -70,6 +71,7 @@ namespace Transport · 14 unmodified lines
70 bool m_allowMetadataRefresh;71 bool m_allowMetadataRefresh;
71 bool m_allowNaNValueFilter;72 bool m_allowNaNValueFilter;
72 bool m_forceNaNValueFilter;73 bool m_forceNaNValueFilter;
74 bool m_supportsTemporalSubscriptions;
73 uint32_t m_cipherKeyRotationPeriod;75 uint32_t m_cipherKeyRotationPeriod;
74 void* m_userData;76 void* m_userData;
75 bool m_disposing;77 bool m_disposing;
@@ -93,6 +95,7 @@ namespace Transport · 17 unmodified lines
93 // Command channel handlers95 // Command channel handlers
94 void StartAccept();96 void StartAccept();
95 void AcceptConnection(const SubscriberConnectionPtr& connection, const ErrorCode& error);97 void AcceptConnection(const SubscriberConnectionPtr& connection, const ErrorCode& error);
98 void ConnectionTerminated(const SubscriberConnectionPtr& connection);
96 void RemoveConnection(const SubscriberConnectionPtr& connection);99 void RemoveConnection(const SubscriberConnectionPtr& connection);
97 100
98 // Callbacks101 // Callbacks
@@ -100,19 +103,25 @@ namespace Transport · 1 unmodified line
100 MessageCallback m_errorMessageCallback;103 MessageCallback m_errorMessageCallback;
101 SubscriberConnectionCallback m_clientConnectedCallback;104 SubscriberConnectionCallback m_clientConnectedCallback;
102 SubscriberConnectionCallback m_clientDisconnectedCallback;105 SubscriberConnectionCallback m_clientDisconnectedCallback;
106 SubscriberConnectionCallback m_temporalSubscriptionRequestedCallback;
107 SubscriberConnectionCallback m_temporalProcessingIntervalChangeRequestedCallback;
103 108
104 // Dispatchers109 // Dispatchers
105 void Dispatch(const DispatcherFunction& function);110 void Dispatch(const DispatcherFunction& function);
106 void Dispatch(const DispatcherFunction& function, const uint8_t* data, uint32_t offset, uint32_t length);111 void Dispatch(const DispatcherFunction& function, const uint8_t* data, uint32_t offset, uint32_t length);
107 void DispatchStatusMessage(const std::string& message);112 void DispatchStatusMessage(const std::string& message);
108 void DispatchErrorMessage(const std::string& message);113 void DispatchErrorMessage(const std::string& message);
109 void DispatchClientConnected(const GSF::Guid& subscriberID, const std::string& connectionID);114 void DispatchClientConnected(const SubscriberConnectionPtr& connection);
110 void DispatchClientDisconnected(const GSF::Guid& subscriberID, const std::string& connectionID);115 void DispatchClientDisconnected(const SubscriberConnectionPtr& connection);
116 void DispatchTemporalSubscriptionRequested(const SubscriberConnectionPtr& connection);
117 void DispatchTemporalProcessingIntervalChangeRequested(const SubscriberConnectionPtr& connection);
111 118
112 static void StatusMessageDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer);119 static void StatusMessageDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer);
113 static void ErrorMessageDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer);120 static void ErrorMessageDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer);
114 static void ClientConnectedDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer);121 static void ClientConnectedDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer);
115 static void ClientDisconnectedDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer);122 static void ClientDisconnectedDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer);
123 static void TemporalSubscriptionRequestedDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer);
124 static void TemporalProcessingIntervalChangeRequestedDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer);
116 static int32_t GetColumnIndex(const GSF::Data::DataTablePtr& table, const std::string& columnName);125 static int32_t GetColumnIndex(const GSF::Data::DataTablePtr& table, const std::string& columnName);
117 public:126 public:
118 // Creates a new instance of the data publisher.127 // Creates a new instance of the data publisher.
@@ -123,14 +132,22 @@ namespace Transport · 4 unmodified lines
123 // tied up by the publisher.132 // tied up by the publisher.
124 ~DataPublisher();133 ~DataPublisher();
125 134
126 // Define metadata from existing metadata tables135 // Defines metadata from existing metadata records
127 void DefineMetadata(const std::vector<DeviceMetadataPtr>& deviceMetadata, const std::vector<MeasurementMetadataPtr>& measurementMetadata, const std::vector<PhasorMetadataPtr>& phasorMetadata, int32_t versionNumber = 0);136 void DefineMetadata(const std::vector<DeviceMetadataPtr>& deviceMetadata, const std::vector<MeasurementMetadataPtr>& measurementMetadata, const std::vector<PhasorMetadataPtr>& phasorMetadata, int32_t versionNumber = 0);
128 137
129 // Define metadata from an existing dataset138 // Defines metadata from an existing dataset
130 void DefineMetadata(const GSF::Data::DataSetPtr& metadata);139 void DefineMetadata(const GSF::Data::DataSetPtr& metadata);
131 140
141 // Gets primary metadata. This dataset contains all the normalized metadata tables that define
142 // the available detail about the data points that can be subscribed to by clients.
132 const GSF::Data::DataSetPtr& GetMetadata() const;143 const GSF::Data::DataSetPtr& GetMetadata() const;
144
145 // Gets filtering metadata. This dataset, derived from primary metadata, contains a flattened
146 // table used to subscribe to a filtered set of points with an expression, e.g.:
147 // FILTER ActiveMeasurements WHERE SignalType LIKE '%PHA'
133 const GSF::Data::DataSetPtr& GetFilteringMetadata() const;148 const GSF::Data::DataSetPtr& GetFilteringMetadata() const;
149
150 // Filters primary MeasurementDetail metadata returning values as measurement metadata records
134 std::vector<MeasurementMetadataPtr> FilterMetadata(const std::string& filterExpression) const;151 std::vector<MeasurementMetadataPtr> FilterMetadata(const std::string& filterExpression) const;
135 152
136 void PublishMeasurements(const std::vector<Measurement>& measurements);153 void PublishMeasurements(const std::vector<Measurement>& measurements);
@@ -154,6 +171,9 @@ namespace Transport · 17 unmodified lines
154 bool IsNaNValueFilterForced() const;171 bool IsNaNValueFilterForced() const;
155 void SetNaNValueFilterForced(bool forced);172 void SetNaNValueFilterForced(bool forced);
156 173
174 bool GetSupportsTemporalSubscriptions() const;
175 void SetSupportsTemporalSubscriptions(bool value);
176
157 uint32_t GetCipherKeyRotationPeriod() const;177 uint32_t GetCipherKeyRotationPeriod() const;
158 void SetCipherKeyRotationPeriod(uint32_t period);178 void SetCipherKeyRotationPeriod(uint32_t period);
159 179
@@ -169,17 +189,18 @@ namespace Transport · 9 unmodified lines
169 // Callback registration189 // Callback registration
170 //190 //
171 // Callback functions are defined with the following signatures:191 // Callback functions are defined with the following signatures:
172 // void ProcessStatusMessage(DataPublisher*, const string& message)192 // void ProcessStatusMessage(DataPublisher* source, const string& message)
173 // void ProcessErrorMessage(DataPublisher*, const string& message)193 // void ProcessErrorMessage(DataPublisher* source, const string& message)
174 // void ProcessClientConnected(DataPublisher*, const GSF::Guid& subscriberID, const string& connectionID);194 // void ProcessClientConnected(DataPublisher* source, const SubscriberConnectionPtr& connection);
175 // void ProcessClientDisconnected(DataPublisher*, const GSF::Guid& subscriberID, const string& connectionID);195 // void ProcessClientDisconnected(DataPublisher* source, const SubscriberConnectionPtr& connection);
196 // void ProcessTemporalSubscriptionRequested(DataPublisher* source, const SubscriberConnectionPtr& connection);
197 // void ProcessTemporalProcessingIntervalChangeRequested(DataPublisher* source, const SubscriberConnectionPtr& connection);
176 void RegisterStatusMessageCallback(const MessageCallback& statusMessageCallback);198 void RegisterStatusMessageCallback(const MessageCallback& statusMessageCallback);
177 void RegisterErrorMessageCallback(const MessageCallback& errorMessageCallback);199 void RegisterErrorMessageCallback(const MessageCallback& errorMessageCallback);
178 void RegisterClientConnectedCallback(const SubscriberConnectionCallback& clientConnectedCallback);200 void RegisterClientConnectedCallback(const SubscriberConnectionCallback& clientConnectedCallback);
179 void RegisterClientDisconnectedCallback(const SubscriberConnectionCallback& clientDisconnectedCallback);201 void RegisterClientDisconnectedCallback(const SubscriberConnectionCallback& clientDisconnectedCallback);
180 202 void RegisterTemporalSubscriptionRequestedCallback(const SubscriberConnectionCallback& temporalSubscriptionRequestedCallback);
181 //static std::string DecodeClientString(const SubscriberConnectionPtr& connection, const uint8_t* data, uint32_t offset, uint32_t length);203 void RegisterTemporalProcessingIntervalChangeRequestedCallback(const SubscriberConnectionCallback& temporalProcessingIntervalChangeRequestedCallback);
182 //static std::vector<uint8_t> EncodeClientString(const SubscriberConnectionPtr& connection, const std::string& value);
183 204
184 friend class SubscriberConnection;205 friend class SubscriberConnection;
185 };206 };
Source/Libraries/TimeSeriesPlatformLibrary/Transport/DataSubscriber.h+10−9
@@ -134,7 +134,7 @@ namespace Transport · 133 unmodified lines
134 134
135 class DataSubscriber // NOLINT135 class DataSubscriber // NOLINT
136 {136 {
137 private:137 public:
138 // Function pointer types138 // Function pointer types
139 typedef std::function<void(DataSubscriber*, const std::vector<uint8_t>&)> DispatcherFunction;139 typedef std::function<void(DataSubscriber*, const std::vector<uint8_t>&)> DispatcherFunction;
140 typedef std::function<void(DataSubscriber*, const std::string&)> MessageCallback;140 typedef std::function<void(DataSubscriber*, const std::string&)> MessageCallback;
@@ -144,6 +144,7 @@ namespace Transport · 3 unmodified lines
144 typedef std::function<void(DataSubscriber*)> ConfigurationChangedCallback;144 typedef std::function<void(DataSubscriber*)> ConfigurationChangedCallback;
145 typedef std::function<void(DataSubscriber*)> ConnectionTerminatedCallback;145 typedef std::function<void(DataSubscriber*)> ConnectionTerminatedCallback;
146 146
147 private:
147 // Structure used to dispatch148 // Structure used to dispatch
148 // callbacks on the callback thread.149 // callbacks on the callback thread.
149 struct CallbackDispatcher150 struct CallbackDispatcher
@@ -263,14 +264,14 @@ namespace Transport · 113 unmodified lines
263 // Callback registration264 // Callback registration
264 //265 //
265 // Callback functions are defined with the following signatures:266 // Callback functions are defined with the following signatures:
266 // void ProcessStatusMessage(DataSubscriber*, const string& message)267 // void ProcessStatusMessage(DataSubscriber* source, const string& message)
267 // void ProcessErrorMessage(DataSubscriber*, const string& message)268 // void ProcessErrorMessage(DataSubscriber* source, const string& message)
268 // void ProcessDataStartTime(DataSubscriber*, int64_t startTime)269 // void ProcessDataStartTime(DataSubscriber* source, int64_t startTime)
269 // void ProcessMetadata(DataSubscriber*, const vector<uint8_t>& metadata)270 // void ProcessMetadata(DataSubscriber* source, const vector<uint8_t>& metadata)
270 // void ProcessNewMeasurements(DataSubscriber*, const vector<MeasurementPtr>& newMeasurements)271 // void ProcessNewMeasurements(DataSubscriber* source, const vector<MeasurementPtr>& newMeasurements)
271 // void ProcessProcessingComplete(DataSubscriber*, const string& message)272 // void ProcessProcessingComplete(DataSubscriber* source, const string& message)
272 // void ProcessConfigurationChanged(DataSubscriber*)273 // void ProcessConfigurationChanged(DataSubscriber* source)
273 // void ProcessConnectionTerminated(DataSubscriber*)274 // void ProcessConnectionTerminated(DataSubscriber* source)
274 //275 //
275 // Metadata is provided to the user as zlib-compressed XML,276 // Metadata is provided to the user as zlib-compressed XML,
276 // and must be decompressed and interpreted before it can be used.277 // and must be decompressed and interpreted before it can be used.
Source/Libraries/TimeSeriesPlatformLibrary/Transport/PublisherInstance.cpp+32−8
@@ -57,16 +57,28 @@ void PublisherInstance::HandleErrorMessage(DataPublisher* source, const string& · 56 unmodified lines
57 instance->ErrorMessage(message);57 instance->ErrorMessage(message);
58}58}
59 59
60void PublisherInstance::HandleClientConnected(DataPublisher* source, const GSF::Guid& subscriberID, const std::string& connectionID)60void PublisherInstance::HandleClientConnected(DataPublisher* source, const SubscriberConnectionPtr& connection)
61{61{
62 PublisherInstance* instance = static_cast<PublisherInstance*>(source->GetUserData());62 PublisherInstance* instance = static_cast<PublisherInstance*>(source->GetUserData());
63 instance->ClientConnected(subscriberID, connectionID);63 instance->ClientConnected(connection);
64}64}
65 65
66void PublisherInstance::HandleClientDisconnected(DataPublisher* source, const GSF::Guid& subscriberID, const std::string& connectionID)66void PublisherInstance::HandleClientDisconnected(DataPublisher* source, const SubscriberConnectionPtr& connection)
67{67{
68 PublisherInstance* instance = static_cast<PublisherInstance*>(source->GetUserData());68 PublisherInstance* instance = static_cast<PublisherInstance*>(source->GetUserData());
69 instance->ClientDisconnected(subscriberID, connectionID);69 instance->ClientDisconnected(connection);
70}
71
72void PublisherInstance::HandleTemporalSubscriptionRequested(DataPublisher* source, const SubscriberConnectionPtr& connection)
73{
74 PublisherInstance* instance = static_cast<PublisherInstance*>(source->GetUserData());
75 instance->TemporalSubscriptionRequested(connection);
76}
77
78void PublisherInstance::HandleTemporalProcessingIntervalChangeRequested(DataPublisher* source, const SubscriberConnectionPtr& connection)
79{
80 PublisherInstance* instance = static_cast<PublisherInstance*>(source->GetUserData());
81 instance->TemporalProcessingIntervalChangeRequested(connection);
70}82}
71 83
72void PublisherInstance::StatusMessage(const string& message)84void PublisherInstance::StatusMessage(const string& message)
@@ -79,14 +91,24 @@ void PublisherInstance::ErrorMessage(const string& message) · 6 unmodified lines
79 cerr << message << endl << endl;91 cerr << message << endl << endl;
80}92}
81 93
82void PublisherInstance::ClientConnected(const GSF::Guid& subscriberID, const string& connectionID)94void PublisherInstance::ClientConnected(const SubscriberConnectionPtr& connection)
95{
96 cout << "Client \"" << connection->GetConnectionID() << "\" with subscriber ID " << ToString(connection->GetSubscriberID()) << " connected..." << endl << endl;
97}
98
99void PublisherInstance::ClientDisconnected(const SubscriberConnectionPtr& connection)
100{
101 cout << "Client \"" << connection->GetConnectionID() << "\" with subscriber ID " << ToString(connection->GetSubscriberID()) << " disconnected..." << endl << endl;
102}
103
104void PublisherInstance::TemporalSubscriptionRequested(const SubscriberConnectionPtr& connection)
83{105{
84 cout << "Client \"" << connectionID << "\" with subscriber ID " << ToString(subscriberID) << " connected..." << endl << endl;106 cout << "Client \"" << connection->GetConnectionID() << "\" with subscriber ID " << ToString(connection->GetSubscriberID()) << " has requested a temporal subscription starting at " << ToString(connection->GetStartTimeConstraint()) << endl << endl;
85}107}
86 108
87void PublisherInstance::ClientDisconnected(const GSF::Guid& subscriberID, const std::string& connectionID)109void PublisherInstance::TemporalProcessingIntervalChangeRequested(const SubscriberConnectionPtr& connection)
88{110{
89 cout << "Client \"" << connectionID << "\" with subscriber ID " << ToString(subscriberID) << " disconnected..." << endl << endl;111 cout << "Client \"" << connection->GetConnectionID() << "\" with subscriber ID " << ToString(connection->GetSubscriberID()) << " has requested to change its temporal processing interval to " << ToString(connection->GetProcessingInterval()) << "ms" << endl << endl;
90}112}
91 113
92void PublisherInstance::Initialize()114void PublisherInstance::Initialize()
@@ -96,6 +118,8 @@ void PublisherInstance::Initialize() · 3 unmodified lines
96 m_publisher.RegisterErrorMessageCallback(&HandleErrorMessage);118 m_publisher.RegisterErrorMessageCallback(&HandleErrorMessage);
97 m_publisher.RegisterClientConnectedCallback(&HandleClientConnected);119 m_publisher.RegisterClientConnectedCallback(&HandleClientConnected);
98 m_publisher.RegisterClientDisconnectedCallback(&HandleClientDisconnected);120 m_publisher.RegisterClientDisconnectedCallback(&HandleClientDisconnected);
121 m_publisher.RegisterTemporalSubscriptionRequestedCallback(&HandleTemporalSubscriptionRequested);
122 m_publisher.RegisterTemporalProcessingIntervalChangeRequestedCallback(&HandleTemporalProcessingIntervalChangeRequested);
99 123
100 m_initialized = true;124 m_initialized = true;
101}125}
Source/Libraries/TimeSeriesPlatformLibrary/Transport/PublisherInstance.h+8−4
@@ -43,14 +43,18 @@ namespace Transport · 42 unmodified lines
43 // Internal subscription event handlers43 // Internal subscription event handlers
44 static void HandleStatusMessage(DataPublisher* source, const std::string& message);44 static void HandleStatusMessage(DataPublisher* source, const std::string& message);
45 static void HandleErrorMessage(DataPublisher* source, const std::string& message);45 static void HandleErrorMessage(DataPublisher* source, const std::string& message);
46 static void HandleClientConnected(DataPublisher* source, const Guid& subscriberID, const std::string& connectionID);46 static void HandleClientConnected(DataPublisher* source, const SubscriberConnectionPtr& connection);
47 static void HandleClientDisconnected(DataPublisher* source, const Guid& subscriberID, const std::string& connectionID);47 static void HandleClientDisconnected(DataPublisher* source, const SubscriberConnectionPtr& connection);
48 static void HandleTemporalSubscriptionRequested(DataPublisher* source, const SubscriberConnectionPtr& connection);
49 static void HandleTemporalProcessingIntervalChangeRequested(DataPublisher* source, const SubscriberConnectionPtr& connection);
48 50
49 protected:51 protected:
50 virtual void StatusMessage(const std::string& message); // Defaults output to cout52 virtual void StatusMessage(const std::string& message); // Defaults output to cout
51 virtual void ErrorMessage(const std::string& message); // Defaults output to cerr53 virtual void ErrorMessage(const std::string& message); // Defaults output to cerr
52 virtual void ClientConnected(const Guid& subscriberID, const std::string& connectionID);54 virtual void ClientConnected(const SubscriberConnectionPtr& connection);
53 virtual void ClientDisconnected(const Guid& subscriberID, const std::string& connectionID);55 virtual void ClientDisconnected(const SubscriberConnectionPtr& connection);
56 virtual void TemporalSubscriptionRequested(const SubscriberConnectionPtr& connection);
57 virtual void TemporalProcessingIntervalChangeRequested(const SubscriberConnectionPtr& connection);
54 58
55 public:59 public:
56 PublisherInstance(uint16_t port, bool ipV6);60 PublisherInstance(uint16_t port, bool ipV6);
Source/Libraries/TimeSeriesPlatformLibrary/Transport/SubscriberConnection.cpp+114−58
@@ -48,6 +48,9 @@ SubscriberConnection::SubscriberConnection(DataPublisherPtr parent, IOContext& c · 47 unmodified lines
48 m_subscriberID(NewGuid()),48 m_subscriberID(NewGuid()),
49 m_operationalModes(OperationalModes::NoFlags),49 m_operationalModes(OperationalModes::NoFlags),
50 m_encoding(OperationalEncoding::UTF8),50 m_encoding(OperationalEncoding::UTF8),
51 m_startTimeConstraint(DateTime::MaxValue),
52 m_stopTimeConstraint(DateTime::MaxValue),
53 m_processingInterval(-1),
51 m_usePayloadCompression(false),54 m_usePayloadCompression(false),
52 m_useCompactMeasurementFormat(true),55 m_useCompactMeasurementFormat(true),
53 m_includeTime(true),56 m_includeTime(true),
@@ -80,6 +83,11 @@ const DataPublisherPtr& SubscriberConnection::GetParent() const · 26 unmodified lines
80 return m_parent;83 return m_parent;
81}84}
82 85
86SubscriberConnectionPtr SubscriberConnection::GetReference()
87{
88 return shared_from_this();
89}
90
83TcpSocket& SubscriberConnection::CommandChannelSocket()91TcpSocket& SubscriberConnection::CommandChannelSocket()
84{92{
85 return m_commandChannelSocket;93 return m_commandChannelSocket;
@@ -126,6 +134,43 @@ uint32_t SubscriberConnection::GetEncoding() const · 40 unmodified lines
126 return m_encoding;134 return m_encoding;
127}135}
128 136
137bool SubscriberConnection::GetIsTemporalSubscription() const
138{
139 return m_startTimeConstraint < DateTime::MaxValue;
140}
141
142const GSF::datetime_t& SubscriberConnection::GetStartTimeConstraint() const
143{
144 return m_startTimeConstraint;
145}
146
147void SubscriberConnection::SetStartTimeConstraint(const GSF::datetime_t& value)
148{
149 m_startTimeConstraint = value;
150}
151
152const GSF::datetime_t& SubscriberConnection::GetStopTimeConstraint() const
153{
154 return m_stopTimeConstraint;
155}
156
157void SubscriberConnection::SetStopTimeConstraint(const GSF::datetime_t& value)
158{
159 m_stopTimeConstraint = value;
160}
161
162int32_t SubscriberConnection::GetProcessingInterval() const
163{
164 return m_processingInterval;
165}
166
167void SubscriberConnection::SetProcessingInterval(int32_t value)
168{
169 m_processingInterval = value;
170 m_parent->DispatchTemporalProcessingIntervalChangeRequested(shared_from_this());
171 m_parent->DispatchStatusMessage(m_connectionID + " was assigned a new processing interval of " + ToString(value) + ".");
172}
173
129bool SubscriberConnection::GetUsePayloadCompression() const174bool SubscriberConnection::GetUsePayloadCompression() const
130{175{
131 return m_usePayloadCompression;176 return m_usePayloadCompression;
@@ -313,50 +358,7 @@ void SubscriberConnection::Stop() · 181 unmodified lines
313 m_pingTimer.Stop();358 m_pingTimer.Stop();
314 m_commandChannelSocket.shutdown(socket_base::shutdown_both);359 m_commandChannelSocket.shutdown(socket_base::shutdown_both);
315 m_commandChannelSocket.cancel();360 m_commandChannelSocket.cancel();
316 m_parent->RemoveConnection(shared_from_this());361 m_parent->ConnectionTerminated(shared_from_this());
317}
318
319void SubscriberConnection::PublishMeasurements(const vector<Measurement>& measurements)
320{
321 if (measurements.empty() || !m_isSubscribed)
322 return;
323
324 if (!m_startTimeSent)
325 m_startTimeSent = SendDataStartTime(measurements[0].Timestamp);
326
327 // TODO: Consider queuing measurements for processing
328
329 CompactMeasurement serializer(m_signalIndexCache, m_baseTimeOffsets, m_includeTime, m_useCompactMeasurementFormat);
330 vector<uint8_t> packet, buffer;
331 int32_t count = 0;
332
333 packet.reserve(MaxPacketSize);
334 buffer.reserve(16);
335
336 for (size_t i = 0; i < measurements.size(); i++)
337 {
338 const Measurement& measurement = measurements[i];
339 const uint16_t runtimeID = m_signalIndexCache->GetSignalIndex(measurement.SignalID);
340
341 if (runtimeID == UInt16::MaxValue)
342 continue;
343
344 const uint32_t length = serializer.SerializeMeasurement(measurement, buffer, runtimeID);
345
346 if (packet.size() + length > MaxPacketSize)
347 {
348 PublishDataPacket(packet, count);
349 packet.clear();
350 count = 0;
351 }
352
353 WriteBytes(packet, buffer);
354 buffer.clear();
355 count++;
356 }
357
358 if (count > 0)
359 PublishDataPacket(packet, count);
360}362}
361 363
362void SubscriberConnection::PublishMeasurements(const vector<MeasurementPtr>& measurements)364void SubscriberConnection::PublishMeasurements(const vector<MeasurementPtr>& measurements)
@@ -402,6 +404,11 @@ void SubscriberConnection::PublishMeasurements(const vector<MeasurementPtr>& mea · 39 unmodified lines
402 PublishDataPacket(packet, count);404 PublishDataPacket(packet, count);
403}405}
404 406
407void SubscriberConnection::CompleteTemporalSubscription()
408{
409 SendResponse(ServerResponse::ProcessingComplete, ServerCommand::Subscribe, ToString(m_parent->GetNodeID()));
410}
411
405void SubscriberConnection::HandleSubscribe(uint8_t* data, uint32_t length)412void SubscriberConnection::HandleSubscribe(uint8_t* data, uint32_t length)
406{413{
407 try414 try
@@ -441,6 +448,24 @@ void SubscriberConnection::HandleSubscribe(uint8_t* data, uint32_t length) · 33 unmodified lines
441 if (TryGetValue(settings, "requestNaNValueFilter", setting))448 if (TryGetValue(settings, "requestNaNValueFilter", setting))
442 SetIsNaNFiltered(ParseBoolean(setting));449 SetIsNaNFiltered(ParseBoolean(setting));
443 450
451 if (TryGetValue(settings, "startTimeConstraint", setting))
452 TryParseTimestamp(setting.c_str(), m_startTimeConstraint, DateTime::MaxValue);
453
454 if (TryGetValue(settings, "startTimeConstraint", setting))
455 TryParseTimestamp(setting.c_str(), m_startTimeConstraint, DateTime::MaxValue);
456
457 if (TryGetValue(settings, "processingInterval", setting) && !setting.empty())
458 TryParseInt32(setting, m_processingInterval, -1);
459
460 if (GetIsTemporalSubscription())
461 {
462 if (!m_parent->GetSupportsTemporalSubscriptions())
463 throw PublisherException("Publisher does not temporal subscriptions");
464
465 if (m_startTimeConstraint > m_stopTimeConstraint)
466 throw PublisherException("Specified stop time of requested temporal subscription precedes start time");
467 }
468
444 SetUsePayloadCompression(usePayloadCompression);469 SetUsePayloadCompression(usePayloadCompression);
445 SetUseCompactMeasurementFormat(useCompactMeasurementFormat);470 SetUseCompactMeasurementFormat(useCompactMeasurementFormat);
446 471
@@ -518,36 +543,48 @@ void SubscriberConnection::HandleSubscribe(uint8_t* data, uint32_t length) · 71 unmodified lines
518 SetIsSubscribed(true);543 SetIsSubscribed(true);
519 SendResponse(ServerResponse::Succeeded, ServerCommand::Subscribe, message);544 SendResponse(ServerResponse::Succeeded, ServerCommand::Subscribe, message);
520 m_parent->DispatchStatusMessage(message);545 m_parent->DispatchStatusMessage(message);
546
547 if (GetIsTemporalSubscription())
548 m_parent->DispatchTemporalSubscriptionRequested(shared_from_this());
521 }549 }
522 else550 else
523 {551 {
524 const string message = byteLength > 0 ?552 HandleSubscribeFailure(byteLength > 0 ?
525 "Not enough buffer was provided to parse client data subscription." :553 "Not enough buffer was provided to parse client data subscription." :
526 "Cannot initialize client data subscription without a connection string.";554 "Cannot initialize client data subscription without a connection string.");
527
528 SendResponse(ServerResponse::Failed, ServerCommand::Subscribe, message);
529 m_parent->DispatchErrorMessage(message);
530 } 555 }
531 } 556 }
532 }557 }
533 else558 else
534 {559 {
535 const string message = "Not enough buffer was provided to parse client data subscription.";560 HandleSubscribeFailure("Not enough buffer was provided to parse client data subscription.");
536 SendResponse(ServerResponse::Failed, ServerCommand::Subscribe, message);
537 m_parent->DispatchErrorMessage(message);
538 }561 }
539 }562 }
540 catch (const std::exception& ex)563 catch (const PublisherException& ex)
541 {564 {
542 const string message = "Failed to process client data subscription due to exception: " + string(ex.what());565 HandleSubscribeFailure("Failed to process client data subscription due to exception: " + string(ex.what()));
543 SendResponse(ServerResponse::Failed, ServerCommand::Subscribe, message);566 }
544 m_parent->DispatchErrorMessage(message);567 catch (...)
568 {
569 HandleSubscribeFailure("Failed to process client data subscription due to exception: " + boost::current_exception_diagnostic_information(true));
545 }570 }
546}571}
547 572
573void SubscriberConnection::HandleSubscribeFailure(const std::string& message)
574{
575 SendResponse(ServerResponse::Failed, ServerCommand::Subscribe, message);
576 m_parent->DispatchErrorMessage(message);
577
578 if (GetIsTemporalSubscription())
579 CompleteTemporalSubscription();
580}
581
548void SubscriberConnection::HandleUnsubscribe()582void SubscriberConnection::HandleUnsubscribe()
549{583{
550 SetIsSubscribed(false);584 SetIsSubscribed(false);
585
586 if (GetIsTemporalSubscription())
587 CompleteTemporalSubscription();
551}588}
552 589
553void SubscriberConnection::HandleMetadataRefresh(uint8_t* data, uint32_t length)590void SubscriberConnection::HandleMetadataRefresh(uint8_t* data, uint32_t length)
@@ -559,7 +596,7 @@ void SubscriberConnection::HandleMetadataRefresh(uint8_t* data, uint32_t length) · 5 unmodified lines
559 m_parent->DispatchStatusMessage("Received meta-data refresh request from " + GetConnectionID() + ", preparing response...");596 m_parent->DispatchStatusMessage("Received meta-data refresh request from " + GetConnectionID() + ", preparing response...");
560 597
561 StringMap<ExpressionTreePtr> filterExpressions;598 StringMap<ExpressionTreePtr> filterExpressions;
562 const DateTime startTime = UtcNow(); //-V821599 const datetime_t startTime = UtcNow(); //-V821
563 600
564 try601 try
565 {602 {
@@ -622,8 +659,22 @@ void SubscriberConnection::HandleRotateCipherKeys() · 56 unmodified lines
622{659{
623}660}
624 661
625void SubscriberConnection::HandleUpdateProcessingInterval(uint8_t* data, uint32_t length)662void SubscriberConnection::HandleUpdateProcessingInterval(const uint8_t* data, uint32_t length)
626{663{
664 // Make sure there is enough buffer for new processing interval value
665 if (length >= 4)
666 {
667 // Next 4 bytes are an integer representing the new processing interval
668 const int32_t processingInterval = EndianConverter::Default.ConvertBigEndian(*reinterpret_cast<const int32_t*>(data));
669 SetProcessingInterval(processingInterval);
670 SendResponse(ServerResponse::Succeeded, ServerCommand::UpdateProcessingInterval, "New processing interval of " + ToString(processingInterval) + " assigned.");
671 }
672 else
673 {
674 const string message = "Not enough buffer was provided to update client processing interval.";
675 SendResponse(ServerResponse::Failed, ServerCommand::UpdateProcessingInterval, message);
676 m_parent->DispatchErrorMessage(message);
677 }
627}678}
628 679
629void SubscriberConnection::HandleDefineOperationalModes(uint8_t* data, uint32_t length)680void SubscriberConnection::HandleDefineOperationalModes(uint8_t* data, uint32_t length)
@@ -1056,6 +1107,11 @@ void SubscriberConnection::WriteHandler(const ErrorCode& error, uint32_t bytesTr · 426 unmodified lines
1056 }1107 }
1057}1108}
1058 1109
1110bool SubscriberConnection::SendResponse(uint8_t responseCode, uint8_t commandCode)
1111{
1112 return SendResponse(responseCode, commandCode, vector<uint8_t>(0));
1113}
1114
1059bool SubscriberConnection::SendResponse(uint8_t responseCode, uint8_t commandCode, const string& message)1115bool SubscriberConnection::SendResponse(uint8_t responseCode, uint8_t commandCode, const string& message)
1060{1116{
1061 return SendResponse(responseCode, commandCode, EncodeString(message));1117 return SendResponse(responseCode, commandCode, EncodeString(message));
Source/Libraries/TimeSeriesPlatformLibrary/Transport/SubscriberConnection.h+48−5
@@ -37,6 +37,9 @@ namespace Transport · 36 unmodified lines
37 class DataPublisher;37 class DataPublisher;
38 typedef GSF::SharedPtr<DataPublisher> DataPublisherPtr;38 typedef GSF::SharedPtr<DataPublisher> DataPublisherPtr;
39 39
40 class SubscriberConnection;
41 typedef GSF::SharedPtr<SubscriberConnection> SubscriberConnectionPtr;
42
40 // Represents a subscriber connection to a data publisher43 // Represents a subscriber connection to a data publisher
41 class SubscriberConnection : public GSF::EnableSharedThisPtr<SubscriberConnection> // NOLINT44 class SubscriberConnection : public GSF::EnableSharedThisPtr<SubscriberConnection> // NOLINT
42 {45 {
@@ -49,6 +52,9 @@ namespace Transport · 6 unmodified lines
49 std::string m_subscriptionInfo;52 std::string m_subscriptionInfo;
50 uint32_t m_operationalModes;53 uint32_t m_operationalModes;
51 uint32_t m_encoding;54 uint32_t m_encoding;
55 GSF::datetime_t m_startTimeConstraint;
56 GSF::datetime_t m_stopTimeConstraint;
57 int32_t m_processingInterval;
52 bool m_usePayloadCompression;58 bool m_usePayloadCompression;
53 bool m_useCompactMeasurementFormat;59 bool m_useCompactMeasurementFormat;
54 bool m_includeTime;60 bool m_includeTime;
@@ -79,17 +85,18 @@ namespace Transport · 24 unmodified lines
79 SignalIndexCachePtr m_signalIndexCache;85 SignalIndexCachePtr m_signalIndexCache;
80 int32_t m_timeIndex;86 int32_t m_timeIndex;
81 int64_t m_baseTimeOffsets[2];87 int64_t m_baseTimeOffsets[2];
82 DateTime m_lastPublishTime;88 datetime_t m_lastPublishTime;
83 //TSSCMeasurementParser m_tsscMeasurementParser;89 //TSSCMeasurementParser m_tsscMeasurementParser;
84 //bool m_tsscResetRequested;90 //bool m_tsscResetRequested;
85 //uint16_t m_tsscSequenceNumber;91 //uint16_t m_tsscSequenceNumber;
86 92
87 // Server request handlers93 // Server request handlers
88 void HandleSubscribe(uint8_t* data, uint32_t length);94 void HandleSubscribe(uint8_t* data, uint32_t length);
95 void HandleSubscribeFailure(const std::string& message);
89 void HandleUnsubscribe();96 void HandleUnsubscribe();
90 void HandleMetadataRefresh(uint8_t* data, uint32_t length);97 void HandleMetadataRefresh(uint8_t* data, uint32_t length);
91 void HandleRotateCipherKeys();98 void HandleRotateCipherKeys();
92 void HandleUpdateProcessingInterval(uint8_t* data, uint32_t length);99 void HandleUpdateProcessingInterval(const uint8_t* data, uint32_t length);
93 void HandleDefineOperationalModes(uint8_t* data, uint32_t length);100 void HandleDefineOperationalModes(uint8_t* data, uint32_t length);
94 void HandleConfirmNotification(uint8_t* data, uint32_t length);101 void HandleConfirmNotification(uint8_t* data, uint32_t length);
95 void HandleConfirmBufferBlock(uint8_t* data, uint32_t length);102 void HandleConfirmBufferBlock(uint8_t* data, uint32_t length);
@@ -112,43 +119,78 @@ namespace Transport · 16 unmodified lines
112 ~SubscriberConnection();119 ~SubscriberConnection();
113 120
114 const DataPublisherPtr& GetParent() const;121 const DataPublisherPtr& GetParent() const;
122 SubscriberConnectionPtr GetReference();
115 123
116 GSF::TcpSocket& CommandChannelSocket();124 GSF::TcpSocket& CommandChannelSocket();
117 125
118 // Gets or sets subscriber identification used when subscriber is known and pre-established126 // Gets or sets subscriber UUID used when subscriber is known and pre-established
119 const GSF::Guid& GetSubscriberID() const;127 const GSF::Guid& GetSubscriberID() const;
120 void SetSubscriberID(const GSF::Guid& id);128 void SetSubscriberID(const GSF::Guid& id);
121 129
130 // Gets subscriber connection identification, e.g., remote IP/port, for display and logging references
122 const std::string& GetConnectionID() const;131 const std::string& GetConnectionID() const;
132
133 // Gets subscriber remote IP address
123 const GSF::IPAddress& GetIPAddress() const;134 const GSF::IPAddress& GetIPAddress() const;
135
136 // Gets subscriber communications port
124 const std::string& GetHostName() const;137 const std::string& GetHostName() const;
125 138
139 // Gets or sets established subscriber operational modes
126 uint32_t GetOperationalModes() const;140 uint32_t GetOperationalModes() const;
127 void SetOperationalModes(uint32_t value);141 void SetOperationalModes(uint32_t value);
128 142
143 // Gets established subscriber string encoding
129 uint32_t GetEncoding() const;144 uint32_t GetEncoding() const;
130 145
146 // Gets flags that determines if this subscription is temporal based
147 bool GetIsTemporalSubscription() const;
148
149 // Gets or sets the start time temporal processing constraint
150 const GSF::datetime_t& GetStartTimeConstraint() const;
151 void SetStartTimeConstraint(const GSF::datetime_t& value);
152
153 // Gets or sets the stop time temporal processing constraint
154 const GSF::datetime_t& GetStopTimeConstraint() const;
155 void SetStopTimeConstraint(const GSF::datetime_t& value);
156
157 // Gets or sets the desired temporal processing interval, in milliseconds
158 // With the exception of the values of -1 and 0, this value specifies the desired processing interval for data, i.e.,
159 // basically a delay, or timer interval, over which to process data. A value of -1 means to use the default processing
160 // interval while a value of 0 means to process data as fast as possible.
161 int32_t GetProcessingInterval() const;
162 void SetProcessingInterval(int32_t value);
163
164 // Gets or sets flag that determines if payload compression should be enabled in data packets
131 bool GetUsePayloadCompression() const;165 bool GetUsePayloadCompression() const;
132 void SetUsePayloadCompression(bool value);166 void SetUsePayloadCompression(bool value);
133 167
168 // Gets or sets flag that determines if the compact measurement format should be used in data packets
134 bool GetUseCompactMeasurementFormat() const;169 bool GetUseCompactMeasurementFormat() const;
135 void SetUseCompactMeasurementFormat(bool value);170 void SetUseCompactMeasurementFormat(bool value);
136 171
172 // Gets or sets flag that determines if time should be included in data packets when the compact measurement format used
137 bool GetIncludeTime() const;173 bool GetIncludeTime() const;
138 void SetIncludeTime(bool value);174 void SetIncludeTime(bool value);
139 175
176 // Gets or sets flag that determines if time should be restricted to millisecond resolution in data packets when the
177 // compact measurement format used; otherwise, full resolution time will be used
140 bool GetUseMillisecondResolution() const;178 bool GetUseMillisecondResolution() const;
141 void SetUseMillisecondResolution(bool value);179 void SetUseMillisecondResolution(bool value);
142 180
181 // Gets or sets flag that determines if NaN values should be excluded from data packets
143 bool GetIsNaNFiltered() const;182 bool GetIsNaNFiltered() const;
144 void SetIsNaNFiltered(bool value);183 void SetIsNaNFiltered(bool value);
145 184
185 // Gets or sets flag that determines if subscriber connection is currently subscribed
146 bool GetIsSubscribed() const;186 bool GetIsSubscribed() const;
147 void SetIsSubscribed(bool value);187 void SetIsSubscribed(bool value);
148 188
189 // Gets or sets subscription details about subscriber
149 const std::string& GetSubscriptionInfo() const;190 const std::string& GetSubscriptionInfo() const;
150 void SetSubscriptionInfo(const std::string& value);191 void SetSubscriptionInfo(const std::string& value);
151 192
193 // Gets or sets signal index cache for subscriber representing run-time mappings for subscribed points
152 const SignalIndexCachePtr& GetSignalIndexCache() const;194 const SignalIndexCachePtr& GetSignalIndexCache() const;
153 void SetSignalIndexCache(SignalIndexCachePtr signalIndexCache);195 void SetSignalIndexCache(SignalIndexCachePtr signalIndexCache);
154 196
@@ -164,15 +206,16 @@ namespace Transport · 9 unmodified lines
164 void Start();206 void Start();
165 void Stop();207 void Stop();
166 208
167 void PublishMeasurements(const std::vector<Measurement>& measurements);
168 void PublishMeasurements(const std::vector<MeasurementPtr>& measurements);209 void PublishMeasurements(const std::vector<MeasurementPtr>& measurements);
210 void CompleteTemporalSubscription();
169 211
170 void CommandChannelSendAsync(uint8_t* data, uint32_t offset, uint32_t length);212 void CommandChannelSendAsync(uint8_t* data, uint32_t offset, uint32_t length);
171 void DataChannelSendAsync(uint8_t* data, uint32_t offset, uint32_t length);213 void DataChannelSendAsync(uint8_t* data, uint32_t offset, uint32_t length);
172 void WriteHandler(const ErrorCode& error, uint32_t bytesTransferred);214 void WriteHandler(const ErrorCode& error, uint32_t bytesTransferred);
173 215
216 bool SendResponse(uint8_t responseCode, uint8_t commandCode);
174 bool SendResponse(uint8_t responseCode, uint8_t commandCode, const std::string& message);217 bool SendResponse(uint8_t responseCode, uint8_t commandCode, const std::string& message);
175 bool SendResponse(uint8_t responseCode, uint8_t commandCode, const std::vector<uint8_t>& data = {});218 bool SendResponse(uint8_t responseCode, uint8_t commandCode, const std::vector<uint8_t>& data);
176 219
177 std::string DecodeString(const uint8_t* data, uint32_t offset, uint32_t length) const;220 std::string DecodeString(const uint8_t* data, uint32_t offset, uint32_t length) const;
178 std::vector<uint8_t> EncodeString(const std::string& value) const;221 std::vector<uint8_t> EncodeString(const std::string& value) const;
Source/Libraries/TimeSeriesPlatformLibrary/Transport/SubscriberInstance.cpp+4−4
@@ -562,7 +562,7 @@ void SubscriberInstance::DataStartTime(time_t unixSOC, uint16_t milliseconds) · 561 unmodified lines
562{562{
563}563}
564 564
565void SubscriberInstance::DataStartTime(DateTime startTime)565void SubscriberInstance::DataStartTime(datetime_t startTime)
566{566{
567}567}
568 568
@@ -876,7 +876,7 @@ void SubscriberInstance::ConstructConfigurationFrames(const StringMap<DeviceMeta · 307 unmodified lines
876 phasorReference->Phasor->Type = "?";876 phasorReference->Phasor->Type = "?";
877 phasorReference->Phasor->Phase = "+";877 phasorReference->Phasor->Phase = "+";
878 phasorReference->Phasor->SourceIndex = i;878 phasorReference->Phasor->SourceIndex = i;
879 phasorReference->Phasor->UpdatedOn = DateTime();879 phasorReference->Phasor->UpdatedOn = datetime_t();
880 880
881 phasorReference->Angle = nullptr;881 phasorReference->Angle = nullptr;
882 phasorReference->Magnitude = nullptr;882 phasorReference->Magnitude = nullptr;
@@ -912,7 +912,7 @@ void SubscriberInstance::ConstructConfigurationFrames(const StringMap<DeviceMeta · 29 unmodified lines
912 measurement->Reference.Kind = SignalKind::Analog;912 measurement->Reference.Kind = SignalKind::Analog;
913 measurement->PhasorSourceIndex = 0U;913 measurement->PhasorSourceIndex = 0U;
914 measurement->Description = "";914 measurement->Description = "";
915 measurement->UpdatedOn = DateTime();915 measurement->UpdatedOn = datetime_t();
916 916
917 configurationFrame->Analogs.push_back(measurement);917 configurationFrame->Analogs.push_back(measurement);
918 }918 }
@@ -946,7 +946,7 @@ void SubscriberInstance::ConstructConfigurationFrames(const StringMap<DeviceMeta · 27 unmodified lines
946 measurement->Reference.Kind = SignalKind::Digital;946 measurement->Reference.Kind = SignalKind::Digital;
947 measurement->PhasorSourceIndex = 0U;947 measurement->PhasorSourceIndex = 0U;
948 measurement->Description = "";948 measurement->Description = "";
949 measurement->UpdatedOn = DateTime();949 measurement->UpdatedOn = datetime_t();
950 950
951 configurationFrame->Digitals.push_back(measurement);951 configurationFrame->Digitals.push_back(measurement);
952 }952 }
Source/Libraries/TimeSeriesPlatformLibrary/Transport/SubscriberInstance.h+1−1
@@ -79,7 +79,7 @@ namespace Transport · 78 unmodified lines
79 virtual void StatusMessage(const std::string& message); // Defaults output to cout79 virtual void StatusMessage(const std::string& message); // Defaults output to cout
80 virtual void ErrorMessage(const std::string& message); // Defaults output to cerr80 virtual void ErrorMessage(const std::string& message); // Defaults output to cerr
81 virtual void DataStartTime(time_t unixSOC, uint16_t milliseconds);81 virtual void DataStartTime(time_t unixSOC, uint16_t milliseconds);
82 virtual void DataStartTime(DateTime startTime);82 virtual void DataStartTime(datetime_t startTime);
83 virtual void ReceivedMetadata(const std::vector<uint8_t>& payload);83 virtual void ReceivedMetadata(const std::vector<uint8_t>& payload);
84 virtual void ParsedMetadata();84 virtual void ParsedMetadata();
85 virtual void ReceivedNewMeasurements(const std::vector<MeasurementPtr>& measurements);85 virtual void ReceivedNewMeasurements(const std::vector<MeasurementPtr>& measurements);
Source/Libraries/TimeSeriesPlatformLibrary/Transport/TransportTypes.cpp+18−1
@@ -64,7 +64,7 @@ float64_t Measurement::AdjustedValue() const · 63 unmodified lines
64 return Value * Multiplier + Adder;64 return Value * Multiplier + Adder;
65}65}
66 66
67DateTime Measurement::GetDateTime() const67datetime_t Measurement::GetDateTime() const
68{68{
69 return FromTicks(Timestamp);69 return FromTicks(Timestamp);
70}70}
@@ -74,6 +74,23 @@ void Measurement::GetUnixTime(time_t& unixSOC, uint16_t& milliseconds) const · 3 unmodified lines
74 ToUnixTime(Timestamp, unixSOC, milliseconds);74 ToUnixTime(Timestamp, unixSOC, milliseconds);
75}75}
76 76
77MeasurementPtr TimeSeries::ToPtr(const Measurement& source)
78{
79 MeasurementPtr destination = NewSharedPtr<Measurement>();
80
81 destination->ID = source.ID;
82 destination->Source = source.Source;
83 destination->SignalID = source.SignalID;
84 destination->Tag = source.Tag;
85 destination->Value = source.Value;
86 destination->Adder = source.Adder;
87 destination->Multiplier = source.Multiplier;
88 destination->Timestamp = source.Timestamp;
89 destination->Flags = source.Flags;
90
91 return destination;
92}
93
77SignalReference::SignalReference() :94SignalReference::SignalReference() :
78 SignalID(Empty::Guid),95 SignalID(Empty::Guid),
79 Index(0),96 Index(0),
Source/Libraries/TimeSeriesPlatformLibrary/Transport/TransportTypes.h+5−4
@@ -97,13 +97,14 @@ namespace TimeSeries · 96 unmodified lines
97 float64_t AdjustedValue() const;97 float64_t AdjustedValue() const;
98 98
99 // Gets Timestamp as DateTime99 // Gets Timestamp as DateTime
100 DateTime GetDateTime() const;100 datetime_t GetDateTime() const;
101 101
102 // Gets Timestamp in Unix second of century and milliseconds102 // Gets Timestamp in Unix second of century and milliseconds
103 void GetUnixTime(time_t& unixSOC, uint16_t& milliseconds) const;103 void GetUnixTime(time_t& unixSOC, uint16_t& milliseconds) const;
104 };104 };
105 105
106 typedef SharedPtr<Measurement> MeasurementPtr;106 typedef SharedPtr<Measurement> MeasurementPtr;
107 MeasurementPtr ToPtr(const Measurement& source);
107 108
108 enum SignalKind : int16_t109 enum SignalKind : int16_t
109 {110 {
@@ -162,7 +163,7 @@ namespace TimeSeries · 52 unmodified lines
162 SignalReference Reference; // Parsed signal reference structure163 SignalReference Reference; // Parsed signal reference structure
163 uint16_t PhasorSourceIndex; // Measurement phasor index, if measurement represents a "Phasor"164 uint16_t PhasorSourceIndex; // Measurement phasor index, if measurement represents a "Phasor"
164 std::string Description; // Detailed measurement description (free-form)165 std::string Description; // Detailed measurement description (free-form)
165 DateTime UpdatedOn; // Time of last meta-data update166 datetime_t UpdatedOn; // Time of last meta-data update
166 };167 };
167 168
168 typedef SharedPtr<MeasurementMetadata> MeasurementMetadataPtr;169 typedef SharedPtr<MeasurementMetadata> MeasurementMetadataPtr;
@@ -174,7 +175,7 @@ namespace TimeSeries · 5 unmodified lines
174 std::string Type; // Phasor type, i.e., "V" for voltage or "I" for current175 std::string Type; // Phasor type, i.e., "V" for voltage or "I" for current
175 std::string Phase; // Phasor phase, one of, "+", "-", "0", "A", "B" or "C"176 std::string Phase; // Phasor phase, one of, "+", "-", "0", "A", "B" or "C"
176 uint16_t SourceIndex; // Phasor ordered index, uses 1-based indexing (key to MeasurementMetadata.PhasorSourceIndex)177 uint16_t SourceIndex; // Phasor ordered index, uses 1-based indexing (key to MeasurementMetadata.PhasorSourceIndex)
177 DateTime UpdatedOn; // Time of last meta-data update178 datetime_t UpdatedOn; // Time of last meta-data update
178 };179 };
179 180
180 typedef SharedPtr<PhasorMetadata> PhasorMetadataPtr;181 typedef SharedPtr<PhasorMetadata> PhasorMetadataPtr;
@@ -202,7 +203,7 @@ namespace TimeSeries · 21 unmodified lines
202 std::string VendorDeviceName; // Original vendor device name, e.g., PMU brand (if useful / provided)203 std::string VendorDeviceName; // Original vendor device name, e.g., PMU brand (if useful / provided)
203 float64_t Longitude; // Device longitude (if reported)204 float64_t Longitude; // Device longitude (if reported)
204 float64_t Latitude; // Device latitude (if reported)205 float64_t Latitude; // Device latitude (if reported)
205 DateTime UpdatedOn; // Time of last meta-data update206 datetime_t UpdatedOn; // Time of last meta-data update
206 207
207 // Associated measurement and phasor meta-data208 // Associated measurement and phasor meta-data
208 std::vector<MeasurementMetadataPtr> Measurements; // DataPublisher does not need to assign209 std::vector<MeasurementMetadataPtr> Measurements; // DataPublisher does not need to assign

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t