@@ -137,7 +137,7 @@ public async Task<bool> InitAsync()
137137 }
138138 else
139139 {
140- Trace ( $ "Attempting to register ourselves with IoT Hub using owner connection string: { _iotHubOwnerConnectionString } ") ;
140+ Trace ( $ "Attempting to register ourselves with IoT Hub using owner connection string. ") ;
141141 RegistryManager manager = RegistryManager . CreateFromConnectionString ( _iotHubOwnerConnectionString ) ;
142142
143143 // remove any existing device
@@ -154,13 +154,13 @@ public async Task<bool> InitAsync()
154154 {
155155 string hostname = _iotHubOwnerConnectionString . Substring ( 0 , _iotHubOwnerConnectionString . IndexOf ( ";" ) ) ;
156156 deviceConnectionString = hostname + ";DeviceId=" + ApplicationName + ";SharedAccessKey=" + newDevice . Authentication . SymmetricKey . PrimaryKey ;
157- Trace ( $ "Device connection string is: { deviceConnectionString } ") ;
157+ Trace ( $ "Generated device connection string. ") ;
158158 Trace ( $ "Adding it to device cert store.") ;
159159 await SecureIoTHubToken . WriteAsync ( ApplicationName , deviceConnectionString , IotDeviceCertStoreType , IotDeviceCertStorePath ) ;
160160 }
161161 else
162162 {
163- Trace ( $ "Could not register ourselves with IoT Hub using owner connection string: { _iotHubOwnerConnectionString } ") ;
163+ Trace ( $ "Could not register ourselves with IoT Hub using owner connection string. ") ;
164164 Trace ( "exiting..." ) ;
165165 return false ;
166166 }
@@ -171,7 +171,7 @@ public async Task<bool> InitAsync()
171171 deviceConnectionString = await SecureIoTHubToken . ReadAsync ( ApplicationName , IotDeviceCertStoreType , IotDeviceCertStorePath ) ;
172172 if ( ! string . IsNullOrEmpty ( deviceConnectionString ) )
173173 {
174- Trace ( $ "Create Publisher IoTHub client with device connection string: ' { deviceConnectionString } ' using '{ IotHubProtocol } ' for communication.") ;
174+ Trace ( $ "Create Publisher IoTHub client with device connection string using '{ IotHubProtocol } ' for communication.") ;
175175 _iotHubClient = DeviceClient . CreateFromConnectionString ( deviceConnectionString , IotHubProtocol ) ;
176176 ExponentialBackoff exponentialRetryPolicy = new ExponentialBackoff ( int . MaxValue , TimeSpan . FromMilliseconds ( 2 ) , TimeSpan . FromMilliseconds ( 1024 ) , TimeSpan . FromMilliseconds ( 3 ) ) ;
177177 _iotHubClient . SetRetryPolicy ( exponentialRetryPolicy ) ;
@@ -270,16 +270,12 @@ public void Enqueue(string json)
270270 /// </summary>
271271 private async Task MonitoredItemsProcessor ( CancellationToken ct )
272272 {
273- string contentPropertyKey = "content-type" ;
274- string contentPropertyValue = "application/opcua+uajson" ;
275- string devicenamePropertyKey = "devicename" ;
276- string devicenamePropertyValue = ApplicationName ;
277- int userPropertyLength = contentPropertyKey . Length + contentPropertyValue . Length + devicenamePropertyKey . Length + devicenamePropertyValue . Length ;
273+ uint jsonSquareBracketLength = 2 ;
278274 Microsoft . Azure . Devices . Client . Message tempMsg = new Microsoft . Azure . Devices . Client . Message ( ) ;
279275 // the system properties are MessageId (max 128 byte), Sequence number (ulong), ExpiryTime (DateTime) and more. ideally we get that from the client.
280276 int systemPropertyLength = 128 + sizeof ( ulong ) + tempMsg . ExpiryTimeUtc . ToString ( ) . Length ;
281277 // if batching is requested the buffer will have the requested size, otherwise we reserve the max size
282- uint iotHubMessageBufferSize = ( _iotHubMessageSize > 0 ? _iotHubMessageSize : IotHubMessageSizeMax ) - ( uint ) userPropertyLength - ( uint ) systemPropertyLength ;
278+ uint iotHubMessageBufferSize = ( _iotHubMessageSize > 0 ? _iotHubMessageSize : IotHubMessageSizeMax ) - ( uint ) systemPropertyLength - ( uint ) jsonSquareBracketLength ;
283279 byte [ ] iotHubMessageBuffer = new byte [ iotHubMessageBufferSize ] ;
284280 MemoryStream iotHubMessage = new MemoryStream ( iotHubMessageBuffer ) ;
285281 DateTime nextSendTime = DateTime . UtcNow + TimeSpan . FromSeconds ( _defaultSendIntervalSeconds ) ;
@@ -295,6 +291,7 @@ private async Task MonitoredItemsProcessor(CancellationToken ct)
295291
296292 iotHubMessage . Position = 0 ;
297293 iotHubMessage . SetLength ( 0 ) ;
294+ iotHubMessage . Write ( Encoding . UTF8 . GetBytes ( "[" ) , 0 , 1 ) ;
298295 while ( true )
299296 {
300297 // sanity check the send interval, compute the timeout and get the next monitored item message
@@ -327,7 +324,7 @@ private async Task MonitoredItemsProcessor(CancellationToken ct)
327324 // sanity check that the user has set a large enough IoTHub messages size
328325 if ( ( _iotHubMessageSize > 0 && jsonMessageSize > _iotHubMessageSize ) || ( _iotHubMessageSize == 0 && jsonMessageSize > iotHubMessageBufferSize ) )
329326 {
330- Trace ( Utils . TraceMasks . Error , $ "There is a telemetry message (size: { jsonMessageSize } ), which will not fit into an IoTHub message (max size: { _iotHubMessageSize } ].") ;
327+ Trace ( Utils . TraceMasks . Error , $ "There is a telemetry message (size: { jsonMessageSize } ), which will not fit into an IoTHub message (max size: { iotHubMessageBufferSize } ].") ;
331328 Trace ( Utils . TraceMasks . Error , $ "Please check your IoTHub message size settings. The telemetry message will be discarded silently. Sorry:(") ;
332329 _tooLargeCount ++ ;
333330 continue ;
@@ -338,10 +335,12 @@ private async Task MonitoredItemsProcessor(CancellationToken ct)
338335 if ( _iotHubMessageSize > 0 || ( _iotHubMessageSize == 0 && _defaultSendIntervalSeconds > 0 ) )
339336 {
340337 // if there is still space to batch, do it. otherwise send the buffer and flag the message for later buffering
341- if ( iotHubMessage . Position + jsonMessageSize <= iotHubMessage . Capacity )
338+ if ( iotHubMessage . Position + jsonMessageSize + 1 <= iotHubMessage . Capacity )
342339 {
340+ // add the message and a comma to the buffer
343341 iotHubMessage . Write ( Encoding . UTF8 . GetBytes ( jsonMessage . ToString ( ) ) , 0 , jsonMessageSize ) ;
344- Trace ( Utils . TraceMasks . OperationDetail , $ "Added new message with size { jsonMessageSize } to IoTHub message (size is now { iotHubMessage . Position } ).") ;
342+ iotHubMessage . Write ( Encoding . UTF8 . GetBytes ( "," ) , 0 , 1 ) ;
343+ Trace ( Utils . TraceMasks . OperationDetail , $ "Added new message with size { jsonMessageSize } to IoTHub message (size is now { ( iotHubMessage . Position - 1 ) } ).") ;
345344 continue ;
346345 }
347346 else
@@ -368,25 +367,28 @@ private async Task MonitoredItemsProcessor(CancellationToken ct)
368367 Microsoft . Azure . Devices . Client . Message encodedIotHubMessage = null ;
369368
370369 // if we reached the send interval, but have nothing to send, we continue
371- if ( ! gotItem && iotHubMessage . Position == 0 )
370+ if ( ! gotItem && iotHubMessage . Position == 1 )
372371 {
373372 nextSendTime += TimeSpan . FromSeconds ( _defaultSendIntervalSeconds ) ;
374373 iotHubMessage . Position = 0 ;
375374 iotHubMessage . SetLength ( 0 ) ;
375+ iotHubMessage . Write ( Encoding . UTF8 . GetBytes ( "[" ) , 0 , 1 ) ;
376376 continue ;
377377 }
378378
379379 // if there is no batching and not interval configured, we send the JSON message we just got, otherwise we send the buffer
380380 if ( _iotHubMessageSize == 0 && _defaultSendIntervalSeconds == 0 )
381381 {
382- encodedIotHubMessage = new Microsoft . Azure . Devices . Client . Message ( Encoding . UTF8 . GetBytes ( jsonMessage . ToString ( ) ) ) ;
382+ // we use also an array for a single message to make backend processing more consistent
383+ encodedIotHubMessage = new Microsoft . Azure . Devices . Client . Message ( Encoding . UTF8 . GetBytes ( "[" + jsonMessage . ToString ( ) + "]" ) ) ;
383384 }
384385 else
385386 {
387+ // remove the trailing comma and add a closing square bracket
388+ iotHubMessage . SetLength ( iotHubMessage . Length - 1 ) ;
389+ iotHubMessage . Write ( Encoding . UTF8 . GetBytes ( "]" ) , 0 , 1 ) ;
386390 encodedIotHubMessage = new Microsoft . Azure . Devices . Client . Message ( iotHubMessage . ToArray ( ) ) ;
387391 }
388- encodedIotHubMessage . Properties . Add ( contentPropertyKey , contentPropertyValue ) ;
389- encodedIotHubMessage . Properties . Add ( devicenamePropertyKey , devicenamePropertyValue ) ;
390392 if ( _iotHubClient != null )
391393 {
392394 nextSendTime += TimeSpan . FromSeconds ( _defaultSendIntervalSeconds ) ;
@@ -406,11 +408,14 @@ private async Task MonitoredItemsProcessor(CancellationToken ct)
406408 // reset the messaage
407409 iotHubMessage . Position = 0 ;
408410 iotHubMessage . SetLength ( 0 ) ;
411+ iotHubMessage . Write ( Encoding . UTF8 . GetBytes ( "[" ) , 0 , 1 ) ;
409412
410413 // if we had not yet buffered the last message because there was not enough space, buffer it now
411414 if ( needToBufferMessage )
412415 {
416+ // add the message and a comma to the buffer
413417 iotHubMessage . Write ( Encoding . UTF8 . GetBytes ( jsonMessage . ToString ( ) ) , 0 , jsonMessageSize ) ;
418+ iotHubMessage . Write ( Encoding . UTF8 . GetBytes ( "," ) , 0 , 1 ) ;
414419 }
415420 }
416421 else
@@ -459,23 +464,5 @@ private async Task MonitoredItemsProcessor(CancellationToken ct)
459464 private static CancellationTokenSource _tokenSource ;
460465 private static Task _monitoredItemsProcessorTask ;
461466 private static DeviceClient _iotHubClient ;
462-
463- /// <summary>
464- /// Classes for the telemetry message sent to IoTHub.
465- /// </summary>
466- private class OpcUaMessage
467- {
468- public string ApplicationUri ;
469- public string DisplayName ;
470- public string NodeId ;
471- public OpcUaValue Value ;
472- }
473-
474- private class OpcUaValue
475- {
476- public string Value ;
477- public string SourceTimestamp ;
478- }
479-
480467 }
481468}
0 commit comments