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
3636 using namespace GSF::TimeSeries;
3737 using namespace GSF::TimeSeries::Transport;
3838
39−struct 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−
5139 DataPublisher::DataPublisher(const TcpEndPoint& endpoint) :
5240 m_nodeID(NewGuid()),
5341 m_securityMode(SecurityMode::None),
5442 m_allowMetadataRefresh(true),
5543 m_allowNaNValueFilter(true),
5644 m_forceNaNValueFilter(false),
45+ m_supportsTemporalSubscriptions(false),
5746 m_cipherKeyRotationPeriod(60000),
5847 m_userData(nullptr),
5948 m_disposing(false),
@@ -116,19 +105,21 @@ void DataPublisher::AcceptConnection(const SubscriberConnectionPtr& connection, · 56 unmodified lines
116105 m_subscriberConnectionsLock.unlock();
117106
118107 connection->Start();
119− DispatchClientConnected(connection->GetSubscriberID(), connection->GetConnectionID());
108+ DispatchClientConnected(connection);
120109 }
121110
122111 StartAccept();
123112 }
124113
114+void DataPublisher::ConnectionTerminated(const SubscriberConnectionPtr& connection)
115+{
116+ DispatchClientDisconnected(connection);
117+}
118+
125119 void DataPublisher::RemoveConnection(const SubscriberConnectionPtr& connection)
126120 {
127121 m_subscriberConnectionsLock.lock();
128−
129− if (m_subscriberConnections.erase(connection))
130− DispatchClientDisconnected(connection->GetSubscriberID(), connection->GetConnectionID());
131−
122+ m_subscriberConnections.erase(connection);
132123 m_subscriberConnectionsLock.unlock();
133124 }
134125
@@ -169,16 +160,28 @@ void DataPublisher::DispatchErrorMessage(const string& message) · 34 unmodified lines
169160 Dispatch(&ErrorMessageDispatcher, reinterpret_cast<const uint8_t*>(message.c_str()), 0, messageSize);
170161 }
171162
172−void DataPublisher::DispatchClientConnected(const GSF::Guid& subscriberID, const string& connectionID)
163+void DataPublisher::DispatchClientConnected(const SubscriberConnectionPtr& connection)
164+{
165+ SubscriberConnection* connectionReference = &*connection;
166+ Dispatch(&ClientConnectedDispatcher, reinterpret_cast<uint8_t*>(&connectionReference), 0, sizeof(SubscriberConnection**));
167+}
168+
169+void DataPublisher::DispatchClientDisconnected(const SubscriberConnectionPtr& connection)
170+{
171+ SubscriberConnection* connectionReference = &*connection;
172+ Dispatch(&ClientDisconnectedDispatcher, reinterpret_cast<uint8_t*>(&connectionReference), 0, sizeof(SubscriberConnection**));
173+}
174+
175+void DataPublisher::DispatchTemporalSubscriptionRequested(const SubscriberConnectionPtr& connection)
173176 {
174− SubscriberConnectionInfo* data = new SubscriberConnectionInfo(subscriberID, connectionID);
175− Dispatch(&ClientConnectedDispatcher, reinterpret_cast<uint8_t*>(&data), 0, sizeof(SubscriberConnectionInfo**));
177+ SubscriberConnection* connectionReference = &*connection;
178+ Dispatch(&TemporalSubscriptionRequestedDispatcher, reinterpret_cast<uint8_t*>(&connectionReference), 0, sizeof(SubscriberConnection**));
176179 }
177180
178−void DataPublisher::DispatchClientDisconnected(const GSF::Guid& subscriberID, const std::string& connectionID)
181+void DataPublisher::DispatchTemporalProcessingIntervalChangeRequested(const SubscriberConnectionPtr& connection)
179182 {
180− SubscriberConnectionInfo* data = new SubscriberConnectionInfo(subscriberID, connectionID);
181− Dispatch(&ClientDisconnectedDispatcher, reinterpret_cast<uint8_t*>(&data), 0, sizeof(SubscriberConnectionInfo**));
183+ SubscriberConnection* connectionReference = &*connection;
184+ Dispatch(&TemporalProcessingIntervalChangeRequestedDispatcher, reinterpret_cast<uint8_t*>(&connectionReference), 0, sizeof(SubscriberConnection**));
182185 }
183186
184187 // 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
207210
208211 void DataPublisher::ClientConnectedDispatcher(DataPublisher* source, const vector<uint8_t>& buffer)
209212 {
210− SubscriberConnectionInfo* data = *reinterpret_cast<SubscriberConnectionInfo**>(const_cast<uint8_t*>(&buffer[0]));
213+ SubscriberConnection* connection = *reinterpret_cast<SubscriberConnection**>(const_cast<uint8_t*>(&buffer[0]));
211214
212215 if (source != nullptr)
213216 {
214217 const SubscriberConnectionCallback clientConnectedCallback = source->m_clientConnectedCallback;
215218
216219 if (clientConnectedCallback != nullptr)
217− clientConnectedCallback(source, data->SubscriberID, data->ConnectionID);
220+ clientConnectedCallback(source, connection->GetReference());
218221 }
219−
220− delete data;
221222 }
222223
223224 void DataPublisher::ClientDisconnectedDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer)
224225 {
225− SubscriberConnectionInfo* data = *reinterpret_cast<SubscriberConnectionInfo**>(const_cast<uint8_t*>(&buffer[0]));
226+ SubscriberConnection* connection = *reinterpret_cast<SubscriberConnection**>(const_cast<uint8_t*>(&buffer[0]));
226227
227228 if (source != nullptr)
228229 {
229230 const SubscriberConnectionCallback clientDisconnectedCallback = source->m_clientDisconnectedCallback;
230231
231232 if (clientDisconnectedCallback != nullptr)
232− clientDisconnectedCallback(source, data->SubscriberID, data->ConnectionID);
233+ clientDisconnectedCallback(source, connection->GetReference());
234+
235+ source->RemoveConnection(connection->GetReference());
236+ }
237+}
238+
239+void 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());
233249 }
250+}
251+
252+void 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;
234259
235− delete data;
260+ if (temporalProcessingIntervalChangeRequestedCallback != nullptr)
261+ temporalProcessingIntervalChangeRequestedCallback(source, connection->GetReference());
262+ }
236263 }
237264
238265 int32_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
683710
684711 void DataPublisher::PublishMeasurements(const vector<Measurement>& measurements)
685712 {
686− for (const auto& connection : m_subscriberConnections)
687− connection->PublishMeasurements(measurements);
713+ vector<MeasurementPtr> measurementPtrs;
714+
715+ measurementPtrs.reserve(measurements.size());
716+
717+ for (const auto& measurement : measurements)
718+ measurementPtrs.push_back(ToPtr(measurement));
719+
720+ PublishMeasurements(measurementPtrs);
688721 }
689722
690723 void DataPublisher::PublishMeasurements(const vector<MeasurementPtr>& measurements)
691724 {
725+ m_subscriberConnectionsLock.lock();
726+
692727 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();
694734 }
695735
696736 const GSF::Guid& DataPublisher::GetNodeID() const
@@ -743,6 +783,16 @@ void DataPublisher::SetNaNValueFilterForced(bool forced) · 46 unmodified lines
743783 m_forceNaNValueFilter = forced;
744784 }
745785
786+bool DataPublisher::GetSupportsTemporalSubscriptions() const
787+{
788+ return m_supportsTemporalSubscriptions;
789+}
790+
791+void DataPublisher::SetSupportsTemporalSubscriptions(bool value)
792+{
793+ m_supportsTemporalSubscriptions = value;
794+}
795+
746796 uint32_t DataPublisher::GetCipherKeyRotationPeriod() const
747797 {
748798 return m_cipherKeyRotationPeriod;
@@ -823,4 +873,14 @@ void DataPublisher::RegisterClientConnectedCallback(const SubscriberConnectionCa · 74 unmodified lines
823873 void DataPublisher::RegisterClientDisconnectedCallback(const SubscriberConnectionCallback& clientDisconnectedCallback)
824874 {
825875 m_clientDisconnectedCallback = clientDisconnectedCallback;
826−}
876+}
877+
878+void DataPublisher::RegisterTemporalSubscriptionRequestedCallback(const SubscriberConnectionCallback& temporalSubscriptionRequestedCallback)
879+{
880+ m_temporalSubscriptionRequestedCallback = temporalSubscriptionRequestedCallback;
881+}
882+
883+void 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
4444 {
4545 class DataPublisher : public EnableSharedThisPtr<DataPublisher> // NOLINT
4646 {
47− private:
47+ public:
4848 // Function pointer types
4949 typedef std::function<void(DataPublisher*, const std::vector<uint8_t>&)> DispatcherFunction;
5050 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;
5252
53+ private:
5354 // Structure used to dispatch
5455 // callbacks on the callback thread.
5556 struct CallbackDispatcher
@@ -70,6 +71,7 @@ namespace Transport · 14 unmodified lines
7071 bool m_allowMetadataRefresh;
7172 bool m_allowNaNValueFilter;
7273 bool m_forceNaNValueFilter;
74+ bool m_supportsTemporalSubscriptions;
7375 uint32_t m_cipherKeyRotationPeriod;
7476 void* m_userData;
7577 bool m_disposing;
@@ -93,6 +95,7 @@ namespace Transport · 17 unmodified lines
9395 // Command channel handlers
9496 void StartAccept();
9597 void AcceptConnection(const SubscriberConnectionPtr& connection, const ErrorCode& error);
98+ void ConnectionTerminated(const SubscriberConnectionPtr& connection);
9699 void RemoveConnection(const SubscriberConnectionPtr& connection);
97100
98101 // Callbacks
@@ -100,19 +103,25 @@ namespace Transport · 1 unmodified line
100103 MessageCallback m_errorMessageCallback;
101104 SubscriberConnectionCallback m_clientConnectedCallback;
102105 SubscriberConnectionCallback m_clientDisconnectedCallback;
106+ SubscriberConnectionCallback m_temporalSubscriptionRequestedCallback;
107+ SubscriberConnectionCallback m_temporalProcessingIntervalChangeRequestedCallback;
103108
104109 // Dispatchers
105110 void Dispatch(const DispatcherFunction& function);
106111 void Dispatch(const DispatcherFunction& function, const uint8_t* data, uint32_t offset, uint32_t length);
107112 void DispatchStatusMessage(const std::string& message);
108113 void DispatchErrorMessage(const std::string& message);
109− void DispatchClientConnected(const GSF::Guid& subscriberID, const std::string& connectionID);
110− void DispatchClientDisconnected(const GSF::Guid& subscriberID, const std::string& connectionID);
114+ void DispatchClientConnected(const SubscriberConnectionPtr& connection);
115+ void DispatchClientDisconnected(const SubscriberConnectionPtr& connection);
116+ void DispatchTemporalSubscriptionRequested(const SubscriberConnectionPtr& connection);
117+ void DispatchTemporalProcessingIntervalChangeRequested(const SubscriberConnectionPtr& connection);
111118
112119 static void StatusMessageDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer);
113120 static void ErrorMessageDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer);
114121 static void ClientConnectedDispatcher(DataPublisher* source, const std::vector<uint8_t>& buffer);
115122 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);
116125 static int32_t GetColumnIndex(const GSF::Data::DataTablePtr& table, const std::string& columnName);
117126 public:
118127 // Creates a new instance of the data publisher.
@@ -123,14 +132,22 @@ namespace Transport · 4 unmodified lines
123132 // tied up by the publisher.
124133 ~DataPublisher();
125134
126− // Define metadata from existing metadata tables
135+ // Defines metadata from existing metadata records
127136 void DefineMetadata(const std::vector<DeviceMetadataPtr>& deviceMetadata, const std::vector<MeasurementMetadataPtr>& measurementMetadata, const std::vector<PhasorMetadataPtr>& phasorMetadata, int32_t versionNumber = 0);
128137
129− // Define metadata from an existing dataset
138+ // Defines metadata from an existing dataset
130139 void DefineMetadata(const GSF::Data::DataSetPtr& metadata);
131140
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.
132143 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'
133148 const GSF::Data::DataSetPtr& GetFilteringMetadata() const;
149+
150+ // Filters primary MeasurementDetail metadata returning values as measurement metadata records
134151 std::vector<MeasurementMetadataPtr> FilterMetadata(const std::string& filterExpression) const;
135152
136153 void PublishMeasurements(const std::vector<Measurement>& measurements);
@@ -154,6 +171,9 @@ namespace Transport · 17 unmodified lines
154171 bool IsNaNValueFilterForced() const;
155172 void SetNaNValueFilterForced(bool forced);
156173
174+ bool GetSupportsTemporalSubscriptions() const;
175+ void SetSupportsTemporalSubscriptions(bool value);
176+
157177 uint32_t GetCipherKeyRotationPeriod() const;
158178 void SetCipherKeyRotationPeriod(uint32_t period);
159179
@@ -169,17 +189,18 @@ namespace Transport · 9 unmodified lines
169189 // Callback registration
170190 //
171191 // Callback functions are defined with the following signatures:
172− // void ProcessStatusMessage(DataPublisher*, const string& message)
173− // void ProcessErrorMessage(DataPublisher*, const string& message)
174− // void ProcessClientConnected(DataPublisher*, const GSF::Guid& subscriberID, const string& connectionID);
175− // void ProcessClientDisconnected(DataPublisher*, const GSF::Guid& subscriberID, const string& connectionID);
192+ // void ProcessStatusMessage(DataPublisher* source, const string& message)
193+ // void ProcessErrorMessage(DataPublisher* source, const string& message)
194+ // void ProcessClientConnected(DataPublisher* source, const SubscriberConnectionPtr& connection);
195+ // void ProcessClientDisconnected(DataPublisher* source, const SubscriberConnectionPtr& connection);
196+ // void ProcessTemporalSubscriptionRequested(DataPublisher* source, const SubscriberConnectionPtr& connection);
197+ // void ProcessTemporalProcessingIntervalChangeRequested(DataPublisher* source, const SubscriberConnectionPtr& connection);
176198 void RegisterStatusMessageCallback(const MessageCallback& statusMessageCallback);
177199 void RegisterErrorMessageCallback(const MessageCallback& errorMessageCallback);
178200 void RegisterClientConnectedCallback(const SubscriberConnectionCallback& clientConnectedCallback);
179201 void RegisterClientDisconnectedCallback(const SubscriberConnectionCallback& clientDisconnectedCallback);
180−
181− //static std::string DecodeClientString(const SubscriberConnectionPtr& connection, const uint8_t* data, uint32_t offset, uint32_t length);
182− //static std::vector<uint8_t> EncodeClientString(const SubscriberConnectionPtr& connection, const std::string& value);
202+ void RegisterTemporalSubscriptionRequestedCallback(const SubscriberConnectionCallback& temporalSubscriptionRequestedCallback);
203+ void RegisterTemporalProcessingIntervalChangeRequestedCallback(const SubscriberConnectionCallback& temporalProcessingIntervalChangeRequestedCallback);
183204
184205 friend class SubscriberConnection;
185206 };
Source/Libraries/TimeSeriesPlatformLibrary/Transport/DataSubscriber.h+10−9
@@ -134,7 +134,7 @@ namespace Transport · 133 unmodified lines
134134
135135 class DataSubscriber // NOLINT
136136 {
137− private:
137+ public:
138138 // Function pointer types
139139 typedef std::function<void(DataSubscriber*, const std::vector<uint8_t>&)> DispatcherFunction;
140140 typedef std::function<void(DataSubscriber*, const std::string&)> MessageCallback;
@@ -144,6 +144,7 @@ namespace Transport · 3 unmodified lines
144144 typedef std::function<void(DataSubscriber*)> ConfigurationChangedCallback;
145145 typedef std::function<void(DataSubscriber*)> ConnectionTerminatedCallback;
146146
147+ private:
147148 // Structure used to dispatch
148149 // callbacks on the callback thread.
149150 struct CallbackDispatcher
@@ -263,14 +264,14 @@ namespace Transport · 113 unmodified lines
263264 // Callback registration
264265 //
265266 // Callback functions are defined with the following signatures:
266− // void ProcessStatusMessage(DataSubscriber*, const string& message)
267− // void ProcessErrorMessage(DataSubscriber*, const string& message)
268− // void ProcessDataStartTime(DataSubscriber*, int64_t startTime)
269− // void ProcessMetadata(DataSubscriber*, const vector<uint8_t>& metadata)
270− // void ProcessNewMeasurements(DataSubscriber*, const vector<MeasurementPtr>& newMeasurements)
271− // void ProcessProcessingComplete(DataSubscriber*, const string& message)
272− // void ProcessConfigurationChanged(DataSubscriber*)
273− // void ProcessConnectionTerminated(DataSubscriber*)
267+ // void ProcessStatusMessage(DataSubscriber* source, const string& message)
268+ // void ProcessErrorMessage(DataSubscriber* source, const string& message)
269+ // void ProcessDataStartTime(DataSubscriber* source, int64_t startTime)
270+ // void ProcessMetadata(DataSubscriber* source, const vector<uint8_t>& metadata)
271+ // void ProcessNewMeasurements(DataSubscriber* source, const vector<MeasurementPtr>& newMeasurements)
272+ // void ProcessProcessingComplete(DataSubscriber* source, const string& message)
273+ // void ProcessConfigurationChanged(DataSubscriber* source)
274+ // void ProcessConnectionTerminated(DataSubscriber* source)
274275 //
275276 // Metadata is provided to the user as zlib-compressed XML,
276277 // 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
5757 instance->ErrorMessage(message);
5858 }
5959
60−void PublisherInstance::HandleClientConnected(DataPublisher* source, const GSF::Guid& subscriberID, const std::string& connectionID)
60+void PublisherInstance::HandleClientConnected(DataPublisher* source, const SubscriberConnectionPtr& connection)
6161 {
6262 PublisherInstance* instance = static_cast<PublisherInstance*>(source->GetUserData());
63− instance->ClientConnected(subscriberID, connectionID);
63+ instance->ClientConnected(connection);
6464 }
6565
66−void PublisherInstance::HandleClientDisconnected(DataPublisher* source, const GSF::Guid& subscriberID, const std::string& connectionID)
66+void PublisherInstance::HandleClientDisconnected(DataPublisher* source, const SubscriberConnectionPtr& connection)
6767 {
6868 PublisherInstance* instance = static_cast<PublisherInstance*>(source->GetUserData());
69− instance->ClientDisconnected(subscriberID, connectionID);
69+ instance->ClientDisconnected(connection);
70+}
71+
72+void PublisherInstance::HandleTemporalSubscriptionRequested(DataPublisher* source, const SubscriberConnectionPtr& connection)
73+{
74+ PublisherInstance* instance = static_cast<PublisherInstance*>(source->GetUserData());
75+ instance->TemporalSubscriptionRequested(connection);
76+}
77+
78+void PublisherInstance::HandleTemporalProcessingIntervalChangeRequested(DataPublisher* source, const SubscriberConnectionPtr& connection)
79+{
80+ PublisherInstance* instance = static_cast<PublisherInstance*>(source->GetUserData());
81+ instance->TemporalProcessingIntervalChangeRequested(connection);
7082 }
7183
7284 void PublisherInstance::StatusMessage(const string& message)
@@ -79,14 +91,24 @@ void PublisherInstance::ErrorMessage(const string& message) · 6 unmodified lines
7991 cerr << message << endl << endl;
8092 }
8193
82−void PublisherInstance::ClientConnected(const GSF::Guid& subscriberID, const string& connectionID)
94+void PublisherInstance::ClientConnected(const SubscriberConnectionPtr& connection)
95+{
96+ cout << "Client \"" << connection->GetConnectionID() << "\" with subscriber ID " << ToString(connection->GetSubscriberID()) << " connected..." << endl << endl;
97+}
98+
99+void PublisherInstance::ClientDisconnected(const SubscriberConnectionPtr& connection)
100+{
101+ cout << "Client \"" << connection->GetConnectionID() << "\" with subscriber ID " << ToString(connection->GetSubscriberID()) << " disconnected..." << endl << endl;
102+}
103+
104+void PublisherInstance::TemporalSubscriptionRequested(const SubscriberConnectionPtr& connection)
83105 {
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;
85107 }
86108
87−void PublisherInstance::ClientDisconnected(const GSF::Guid& subscriberID, const std::string& connectionID)
109+void PublisherInstance::TemporalProcessingIntervalChangeRequested(const SubscriberConnectionPtr& connection)
88110 {
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;
90112 }
91113
92114 void PublisherInstance::Initialize()
@@ -96,6 +118,8 @@ void PublisherInstance::Initialize() · 3 unmodified lines
96118 m_publisher.RegisterErrorMessageCallback(&HandleErrorMessage);
97119 m_publisher.RegisterClientConnectedCallback(&HandleClientConnected);
98120 m_publisher.RegisterClientDisconnectedCallback(&HandleClientDisconnected);
121+ m_publisher.RegisterTemporalSubscriptionRequestedCallback(&HandleTemporalSubscriptionRequested);
122+ m_publisher.RegisterTemporalProcessingIntervalChangeRequestedCallback(&HandleTemporalProcessingIntervalChangeRequested);
99123
100124 m_initialized = true;
101125 }
Source/Libraries/TimeSeriesPlatformLibrary/Transport/PublisherInstance.h+8−4
@@ -43,14 +43,18 @@ namespace Transport · 42 unmodified lines
4343 // Internal subscription event handlers
4444 static void HandleStatusMessage(DataPublisher* source, const std::string& message);
4545 static void HandleErrorMessage(DataPublisher* source, const std::string& message);
46− static void HandleClientConnected(DataPublisher* source, const Guid& subscriberID, const std::string& connectionID);
47− static void HandleClientDisconnected(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 SubscriberConnectionPtr& connection);
48+ static void HandleTemporalSubscriptionRequested(DataPublisher* source, const SubscriberConnectionPtr& connection);
49+ static void HandleTemporalProcessingIntervalChangeRequested(DataPublisher* source, const SubscriberConnectionPtr& connection);
4850
4951 protected:
5052 virtual void StatusMessage(const std::string& message); // Defaults output to cout
5153 virtual void ErrorMessage(const std::string& message); // Defaults output to cerr
52− virtual void ClientConnected(const Guid& subscriberID, const std::string& connectionID);
53− virtual void ClientDisconnected(const Guid& subscriberID, const std::string& connectionID);
54+ virtual void ClientConnected(const SubscriberConnectionPtr& connection);
55+ virtual void ClientDisconnected(const SubscriberConnectionPtr& connection);
56+ virtual void TemporalSubscriptionRequested(const SubscriberConnectionPtr& connection);
57+ virtual void TemporalProcessingIntervalChangeRequested(const SubscriberConnectionPtr& connection);
5458
5559 public:
5660 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
4848 m_subscriberID(NewGuid()),
4949 m_operationalModes(OperationalModes::NoFlags),
5050 m_encoding(OperationalEncoding::UTF8),
51+ m_startTimeConstraint(DateTime::MaxValue),
52+ m_stopTimeConstraint(DateTime::MaxValue),
53+ m_processingInterval(-1),
5154 m_usePayloadCompression(false),
5255 m_useCompactMeasurementFormat(true),
5356 m_includeTime(true),
@@ -80,6 +83,11 @@ const DataPublisherPtr& SubscriberConnection::GetParent() const · 26 unmodified lines
8083 return m_parent;
8184 }
8285
86+SubscriberConnectionPtr SubscriberConnection::GetReference()
87+{
88+ return shared_from_this();
89+}
90+
8391 TcpSocket& SubscriberConnection::CommandChannelSocket()
8492 {
8593 return m_commandChannelSocket;
@@ -126,6 +134,43 @@ uint32_t SubscriberConnection::GetEncoding() const · 40 unmodified lines
126134 return m_encoding;
127135 }
128136
137+bool SubscriberConnection::GetIsTemporalSubscription() const
138+{
139+ return m_startTimeConstraint < DateTime::MaxValue;
140+}
141+
142+const GSF::datetime_t& SubscriberConnection::GetStartTimeConstraint() const
143+{
144+ return m_startTimeConstraint;
145+}
146+
147+void SubscriberConnection::SetStartTimeConstraint(const GSF::datetime_t& value)
148+{
149+ m_startTimeConstraint = value;
150+}
151+
152+const GSF::datetime_t& SubscriberConnection::GetStopTimeConstraint() const
153+{
154+ return m_stopTimeConstraint;
155+}
156+
157+void SubscriberConnection::SetStopTimeConstraint(const GSF::datetime_t& value)
158+{
159+ m_stopTimeConstraint = value;
160+}
161+
162+int32_t SubscriberConnection::GetProcessingInterval() const
163+{
164+ return m_processingInterval;
165+}
166+
167+void 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+
129174 bool SubscriberConnection::GetUsePayloadCompression() const
130175 {
131176 return m_usePayloadCompression;
@@ -313,50 +358,7 @@ void SubscriberConnection::Stop() · 181 unmodified lines
313358 m_pingTimer.Stop();
314359 m_commandChannelSocket.shutdown(socket_base::shutdown_both);
315360 m_commandChannelSocket.cancel();
316− m_parent->RemoveConnection(shared_from_this());
317−}
318−
319−void 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);
361+ m_parent->ConnectionTerminated(shared_from_this());
360362 }
361363
362364 void SubscriberConnection::PublishMeasurements(const vector<MeasurementPtr>& measurements)
@@ -402,6 +404,11 @@ void SubscriberConnection::PublishMeasurements(const vector<MeasurementPtr>& mea · 39 unmodified lines
402404 PublishDataPacket(packet, count);
403405 }
404406
407+void SubscriberConnection::CompleteTemporalSubscription()
408+{
409+ SendResponse(ServerResponse::ProcessingComplete, ServerCommand::Subscribe, ToString(m_parent->GetNodeID()));
410+}
411+
405412 void SubscriberConnection::HandleSubscribe(uint8_t* data, uint32_t length)
406413 {
407414 try
@@ -441,6 +448,24 @@ void SubscriberConnection::HandleSubscribe(uint8_t* data, uint32_t length) · 33 unmodified lines
441448 if (TryGetValue(settings, "requestNaNValueFilter", setting))
442449 SetIsNaNFiltered(ParseBoolean(setting));
443450
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+
444469 SetUsePayloadCompression(usePayloadCompression);
445470 SetUseCompactMeasurementFormat(useCompactMeasurementFormat);
446471
@@ -518,36 +543,48 @@ void SubscriberConnection::HandleSubscribe(uint8_t* data, uint32_t length) · 71 unmodified lines
518543 SetIsSubscribed(true);
519544 SendResponse(ServerResponse::Succeeded, ServerCommand::Subscribe, message);
520545 m_parent->DispatchStatusMessage(message);
546+
547+ if (GetIsTemporalSubscription())
548+ m_parent->DispatchTemporalSubscriptionRequested(shared_from_this());
521549 }
522550 else
523551 {
524− const string message = byteLength > 0 ?
552+ HandleSubscribeFailure(byteLength > 0 ?
525553 "Not enough buffer was provided to parse client data subscription." :
526− "Cannot initialize client data subscription without a connection string.";
527−
528− SendResponse(ServerResponse::Failed, ServerCommand::Subscribe, message);
529− m_parent->DispatchErrorMessage(message);
554+ "Cannot initialize client data subscription without a connection string.");
530555 }
531556 }
532557 }
533558 else
534559 {
535− const string message = "Not enough buffer was provided to parse client data subscription.";
536− SendResponse(ServerResponse::Failed, ServerCommand::Subscribe, message);
537− m_parent->DispatchErrorMessage(message);
560+ HandleSubscribeFailure("Not enough buffer was provided to parse client data subscription.");
538561 }
539562 }
540− catch (const std::exception& ex)
563+ catch (const PublisherException& ex)
541564 {
542− const string message = "Failed to process client data subscription due to exception: " + string(ex.what());
543− SendResponse(ServerResponse::Failed, ServerCommand::Subscribe, message);
544− m_parent->DispatchErrorMessage(message);
565+ HandleSubscribeFailure("Failed to process client data subscription due to exception: " + string(ex.what()));
566+ }
567+ catch (...)
568+ {
569+ HandleSubscribeFailure("Failed to process client data subscription due to exception: " + boost::current_exception_diagnostic_information(true));
545570 }
546571 }
547572
573+void 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+
548582 void SubscriberConnection::HandleUnsubscribe()
549583 {
550584 SetIsSubscribed(false);
585+
586+ if (GetIsTemporalSubscription())
587+ CompleteTemporalSubscription();
551588 }
552589
553590 void SubscriberConnection::HandleMetadataRefresh(uint8_t* data, uint32_t length)
@@ -559,7 +596,7 @@ void SubscriberConnection::HandleMetadataRefresh(uint8_t* data, uint32_t length) · 5 unmodified lines
559596 m_parent->DispatchStatusMessage("Received meta-data refresh request from " + GetConnectionID() + ", preparing response...");
560597
561598 StringMap<ExpressionTreePtr> filterExpressions;
562− const DateTime startTime = UtcNow(); //-V821
599+ const datetime_t startTime = UtcNow(); //-V821
563600
564601 try
565602 {
@@ -622,8 +659,22 @@ void SubscriberConnection::HandleRotateCipherKeys() · 56 unmodified lines
622659 {
623660 }
624661
625−void SubscriberConnection::HandleUpdateProcessingInterval(uint8_t* data, uint32_t length)
662+void SubscriberConnection::HandleUpdateProcessingInterval(const uint8_t* data, uint32_t length)
626663 {
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+ }
627678 }
628679
629680 void SubscriberConnection::HandleDefineOperationalModes(uint8_t* data, uint32_t length)
@@ -1056,6 +1107,11 @@ void SubscriberConnection::WriteHandler(const ErrorCode& error, uint32_t bytesTr · 426 unmodified lines
10561107 }
10571108 }
10581109
1110+bool SubscriberConnection::SendResponse(uint8_t responseCode, uint8_t commandCode)
1111+{
1112+ return SendResponse(responseCode, commandCode, vector<uint8_t>(0));
1113+}
1114+
10591115 bool SubscriberConnection::SendResponse(uint8_t responseCode, uint8_t commandCode, const string& message)
10601116 {
10611117 return SendResponse(responseCode, commandCode, EncodeString(message));
Source/Libraries/TimeSeriesPlatformLibrary/Transport/SubscriberConnection.h+48−5
@@ -37,6 +37,9 @@ namespace Transport · 36 unmodified lines
3737 class DataPublisher;
3838 typedef GSF::SharedPtr<DataPublisher> DataPublisherPtr;
3939
40+ class SubscriberConnection;
41+ typedef GSF::SharedPtr<SubscriberConnection> SubscriberConnectionPtr;
42+
4043 // Represents a subscriber connection to a data publisher
4144 class SubscriberConnection : public GSF::EnableSharedThisPtr<SubscriberConnection> // NOLINT
4245 {
@@ -49,6 +52,9 @@ namespace Transport · 6 unmodified lines
4952 std::string m_subscriptionInfo;
5053 uint32_t m_operationalModes;
5154 uint32_t m_encoding;
55+ GSF::datetime_t m_startTimeConstraint;
56+ GSF::datetime_t m_stopTimeConstraint;
57+ int32_t m_processingInterval;
5258 bool m_usePayloadCompression;
5359 bool m_useCompactMeasurementFormat;
5460 bool m_includeTime;
@@ -79,17 +85,18 @@ namespace Transport · 24 unmodified lines
7985 SignalIndexCachePtr m_signalIndexCache;
8086 int32_t m_timeIndex;
8187 int64_t m_baseTimeOffsets[2];
82− DateTime m_lastPublishTime;
88+ datetime_t m_lastPublishTime;
8389 //TSSCMeasurementParser m_tsscMeasurementParser;
8490 //bool m_tsscResetRequested;
8591 //uint16_t m_tsscSequenceNumber;
8692
8793 // Server request handlers
8894 void HandleSubscribe(uint8_t* data, uint32_t length);
95+ void HandleSubscribeFailure(const std::string& message);
8996 void HandleUnsubscribe();
9097 void HandleMetadataRefresh(uint8_t* data, uint32_t length);
9198 void HandleRotateCipherKeys();
92− void HandleUpdateProcessingInterval(uint8_t* data, uint32_t length);
99+ void HandleUpdateProcessingInterval(const uint8_t* data, uint32_t length);
93100 void HandleDefineOperationalModes(uint8_t* data, uint32_t length);
94101 void HandleConfirmNotification(uint8_t* data, uint32_t length);
95102 void HandleConfirmBufferBlock(uint8_t* data, uint32_t length);
@@ -112,43 +119,78 @@ namespace Transport · 16 unmodified lines
112119 ~SubscriberConnection();
113120
114121 const DataPublisherPtr& GetParent() const;
122+ SubscriberConnectionPtr GetReference();
115123
116124 GSF::TcpSocket& CommandChannelSocket();
117125
118− // Gets or sets subscriber identification used when subscriber is known and pre-established
126+ // Gets or sets subscriber UUID used when subscriber is known and pre-established
119127 const GSF::Guid& GetSubscriberID() const;
120128 void SetSubscriberID(const GSF::Guid& id);
121129
130+ // Gets subscriber connection identification, e.g., remote IP/port, for display and logging references
122131 const std::string& GetConnectionID() const;
132+
133+ // Gets subscriber remote IP address
123134 const GSF::IPAddress& GetIPAddress() const;
135+
136+ // Gets subscriber communications port
124137 const std::string& GetHostName() const;
125138
139+ // Gets or sets established subscriber operational modes
126140 uint32_t GetOperationalModes() const;
127141 void SetOperationalModes(uint32_t value);
128142
143+ // Gets established subscriber string encoding
129144 uint32_t GetEncoding() const;
130145
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
131165 bool GetUsePayloadCompression() const;
132166 void SetUsePayloadCompression(bool value);
133167
168+ // Gets or sets flag that determines if the compact measurement format should be used in data packets
134169 bool GetUseCompactMeasurementFormat() const;
135170 void SetUseCompactMeasurementFormat(bool value);
136171
172+ // Gets or sets flag that determines if time should be included in data packets when the compact measurement format used
137173 bool GetIncludeTime() const;
138174 void SetIncludeTime(bool value);
139175
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
140178 bool GetUseMillisecondResolution() const;
141179 void SetUseMillisecondResolution(bool value);
142180
181+ // Gets or sets flag that determines if NaN values should be excluded from data packets
143182 bool GetIsNaNFiltered() const;
144183 void SetIsNaNFiltered(bool value);
145184
185+ // Gets or sets flag that determines if subscriber connection is currently subscribed
146186 bool GetIsSubscribed() const;
147187 void SetIsSubscribed(bool value);
148188
189+ // Gets or sets subscription details about subscriber
149190 const std::string& GetSubscriptionInfo() const;
150191 void SetSubscriptionInfo(const std::string& value);
151192
193+ // Gets or sets signal index cache for subscriber representing run-time mappings for subscribed points
152194 const SignalIndexCachePtr& GetSignalIndexCache() const;
153195 void SetSignalIndexCache(SignalIndexCachePtr signalIndexCache);
154196
@@ -164,15 +206,16 @@ namespace Transport · 9 unmodified lines
164206 void Start();
165207 void Stop();
166208
167− void PublishMeasurements(const std::vector<Measurement>& measurements);
168209 void PublishMeasurements(const std::vector<MeasurementPtr>& measurements);
210+ void CompleteTemporalSubscription();
169211
170212 void CommandChannelSendAsync(uint8_t* data, uint32_t offset, uint32_t length);
171213 void DataChannelSendAsync(uint8_t* data, uint32_t offset, uint32_t length);
172214 void WriteHandler(const ErrorCode& error, uint32_t bytesTransferred);
173215
216+ bool SendResponse(uint8_t responseCode, uint8_t commandCode);
174217 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);
176219
177220 std::string DecodeString(const uint8_t* data, uint32_t offset, uint32_t length) const;
178221 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
562562 {
563563 }
564564
565−void SubscriberInstance::DataStartTime(DateTime startTime)
565+void SubscriberInstance::DataStartTime(datetime_t startTime)
566566 {
567567 }
568568
@@ -876,7 +876,7 @@ void SubscriberInstance::ConstructConfigurationFrames(const StringMap<DeviceMeta · 307 unmodified lines
876876 phasorReference->Phasor->Type = "?";
877877 phasorReference->Phasor->Phase = "+";
878878 phasorReference->Phasor->SourceIndex = i;
879− phasorReference->Phasor->UpdatedOn = DateTime();
879+ phasorReference->Phasor->UpdatedOn = datetime_t();
880880
881881 phasorReference->Angle = nullptr;
882882 phasorReference->Magnitude = nullptr;
@@ -912,7 +912,7 @@ void SubscriberInstance::ConstructConfigurationFrames(const StringMap<DeviceMeta · 29 unmodified lines
912912 measurement->Reference.Kind = SignalKind::Analog;
913913 measurement->PhasorSourceIndex = 0U;
914914 measurement->Description = "";
915− measurement->UpdatedOn = DateTime();
915+ measurement->UpdatedOn = datetime_t();
916916
917917 configurationFrame->Analogs.push_back(measurement);
918918 }
@@ -946,7 +946,7 @@ void SubscriberInstance::ConstructConfigurationFrames(const StringMap<DeviceMeta · 27 unmodified lines
946946 measurement->Reference.Kind = SignalKind::Digital;
947947 measurement->PhasorSourceIndex = 0U;
948948 measurement->Description = "";
949− measurement->UpdatedOn = DateTime();
949+ measurement->UpdatedOn = datetime_t();
950950
951951 configurationFrame->Digitals.push_back(measurement);
952952 }
Source/Libraries/TimeSeriesPlatformLibrary/Transport/SubscriberInstance.h+1−1
@@ -79,7 +79,7 @@ namespace Transport · 78 unmodified lines
7979 virtual void StatusMessage(const std::string& message); // Defaults output to cout
8080 virtual void ErrorMessage(const std::string& message); // Defaults output to cerr
8181 virtual void DataStartTime(time_t unixSOC, uint16_t milliseconds);
82− virtual void DataStartTime(DateTime startTime);
82+ virtual void DataStartTime(datetime_t startTime);
8383 virtual void ReceivedMetadata(const std::vector<uint8_t>& payload);
8484 virtual void ParsedMetadata();
8585 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
6464 return Value * Multiplier + Adder;
6565 }
6666
67−DateTime Measurement::GetDateTime() const
67+datetime_t Measurement::GetDateTime() const
6868 {
6969 return FromTicks(Timestamp);
7070 }
@@ -74,6 +74,23 @@ void Measurement::GetUnixTime(time_t& unixSOC, uint16_t& milliseconds) const · 3 unmodified lines
7474 ToUnixTime(Timestamp, unixSOC, milliseconds);
7575 }
7676
77+MeasurementPtr 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+
7794 SignalReference::SignalReference() :
7895 SignalID(Empty::Guid),
7996 Index(0),
Source/Libraries/TimeSeriesPlatformLibrary/Transport/TransportTypes.h+5−4
@@ -97,13 +97,14 @@ namespace TimeSeries · 96 unmodified lines
9797 float64_t AdjustedValue() const;
9898
9999 // Gets Timestamp as DateTime
100− DateTime GetDateTime() const;
100+ datetime_t GetDateTime() const;
101101
102102 // Gets Timestamp in Unix second of century and milliseconds
103103 void GetUnixTime(time_t& unixSOC, uint16_t& milliseconds) const;
104104 };
105105
106106 typedef SharedPtr<Measurement> MeasurementPtr;
107+ MeasurementPtr ToPtr(const Measurement& source);
107108
108109 enum SignalKind : int16_t
109110 {
@@ -162,7 +163,7 @@ namespace TimeSeries · 52 unmodified lines
162163 SignalReference Reference; // Parsed signal reference structure
163164 uint16_t PhasorSourceIndex; // Measurement phasor index, if measurement represents a "Phasor"
164165 std::string Description; // Detailed measurement description (free-form)
165− DateTime UpdatedOn; // Time of last meta-data update
166+ datetime_t UpdatedOn; // Time of last meta-data update
166167 };
167168
168169 typedef SharedPtr<MeasurementMetadata> MeasurementMetadataPtr;
@@ -174,7 +175,7 @@ namespace TimeSeries · 5 unmodified lines
174175 std::string Type; // Phasor type, i.e., "V" for voltage or "I" for current
175176 std::string Phase; // Phasor phase, one of, "+", "-", "0", "A", "B" or "C"
176177 uint16_t SourceIndex; // Phasor ordered index, uses 1-based indexing (key to MeasurementMetadata.PhasorSourceIndex)
177− DateTime UpdatedOn; // Time of last meta-data update
178+ datetime_t UpdatedOn; // Time of last meta-data update
178179 };
179180
180181 typedef SharedPtr<PhasorMetadata> PhasorMetadataPtr;
@@ -202,7 +203,7 @@ namespace TimeSeries · 21 unmodified lines
202203 std::string VendorDeviceName; // Original vendor device name, e.g., PMU brand (if useful / provided)
203204 float64_t Longitude; // Device longitude (if reported)
204205 float64_t Latitude; // Device latitude (if reported)
205− DateTime UpdatedOn; // Time of last meta-data update
206+ datetime_t UpdatedOn; // Time of last meta-data update
206207
207208 // Associated measurement and phasor meta-data
208209 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