After some testing I have improved the error handling and robustness of my Netduino 3 wifi based Azure Eventhub field gateway.
private void OnReceive(byte[] data) { activityLed.Write(!activityLed.Read()); // Ensure that we have a payload if (data.Length < 1 ) { Debug.Print( "ERROR - Message has no payload" ) ; return ; } string message = new String(Encoding.UTF8.GetChars(data)); Debug.Print(DateTime.UtcNow.ToString("HH:mm:ss") + " L=" + data.Length + " M=" + message); Thread thread = new Thread(() => EventHubSendMessage( data)); thread.Start(); } private void EventHubSendMessage( byte[] messageBody) { #region Diagnostic assertions Debug.Assert(eventHubName != null); Debug.Assert(deviceId != null); Debug.Assert(gatewayId != null); Debug.Assert(messageBody != null); Debug.Assert(messageBody.Length > 0); #endregion if ((connection == null) || (session == null ) || (senderLink == null )) { lock (lockThis) { if (connection == null) { Debug.Print("AMQP Establish connection"); try { connection = new Connection(new Address(serviceBusHost, serviceBusPort, serviceBusSasKeyName, serviceBusSasKey)); connection.Closed = ConnectionClosedCallback; Debug.Print("AMQP Establish connection done"); } catch (Exception ex) { Debug.Print("ERROR: AMQP Establish connection: " + ex.Message); } } if (connection == null) { return; } if (session == null) { Debug.Print("AMQP Establish session"); try { session = new Session(connection); session.Closed = SessionClosedCallback; Debug.Print("AMQP Establish session done"); } catch (Exception ex) { Debug.Print("ERROR: AMQP Establish session: " + ex.Message); } } if (session == null) { return; } if (senderLink == null) { Debug.Print("AMQP Establish SenderLink"); try { senderLink = new SenderLink(session, "send-link", eventHubName); senderLink.Closed = SenderLinkClosedCallback; Debug.Print("AMQP Establish SenderLink done"); } catch (Exception ex) { Debug.Print("ERROR: AMQP Establish SenderLink: " + ex.Message); } } if (senderLink == null) { return; } } } try { Debug.Print("AMQP Send start"); DateTime startAtUtc = DateTime.UtcNow; Message message = new Message() { BodySection = new Data() { Binary = messageBody }, ApplicationProperties = new Amqp.Framing.ApplicationProperties(), }; message.ApplicationProperties["UploadedAtUtc"] = DateTime.UtcNow; message.ApplicationProperties["GatewayId"] = gatewayId; message.ApplicationProperties["DeviceId"] = deviceId; message.ApplicationProperties["EventId"] = Guid.NewGuid(); senderLink.Send(message); DateTime finishAtUtc = DateTime.UtcNow; TimeSpan duration = finishAtUtc - startAtUtc; Debug.Print("AMQP Send done duration " + duration.ToString()); } catch (Exception ex) { Debug.Print("ERROR: Publish failed with error: " + ex.Message); } }
The software is quite reliable, when my internet connection fails it recovers gracefully and resumes uploading events when connectivity is restored.
The only issue is when the wireless access point is restarted, when the device reconnects it locks up and doesn’t recover. I have posted in the Netduino forums and logged at issue at the Github Netduino wifi repository.
I have been exploring rebooting the device in the NetworkChange_NetworkAvailabilityChanged handler when connectivity is restored.
Based on my logging the sending of events is pretty quick and the threads are interleaved
03:20:59 L=25 M={“D”:2,”H”:63.0,”T”:18.8}
AMQP Send start
03:20:59 L=25 M={“D”:1,”H”:54.5,”T”:18.7}
AMQP Send start
03:20:59 L=17 M={“D”:10,”P”:27.9}
AMQP Send start
AMQP Send done duration 00:00:00.2738220
AMQP Send done duration 00:00:00.4709960
AMQP Send done duration 00:00:01.0813910
03:21:01 L=17 M={“D”:10,”P”:27.4}
AMQP Send start
AMQP Send done duration 00:00:00.2820090
03:21:03 L=17 M={“D”:10,”P”:26.9}
Here is the code with usual caveats.
Next steps queuing messages in memory and then on the MicroSD card.