|
| 1 | +// |
| 2 | +// Copyright (c) .NET Foundation and Contributors |
| 3 | +// See LICENSE file in the project root for full license information. |
| 4 | +// |
| 5 | + |
| 6 | +using nanoFramework.Azure.Devices.Client; |
| 7 | +using nanoFramework.Azure.Devices.Shared; |
| 8 | +using nanoFramework.Networking; |
| 9 | +using System; |
| 10 | +using System.Collections; |
| 11 | +using System.Threading; |
| 12 | +using System.Diagnostics; |
| 13 | +using nanoFramework.Json; |
| 14 | +using System.Security.Cryptography.X509Certificates; |
| 15 | +using TestAzureMqtt; |
| 16 | +using nanoFramework.Hardware.Esp32; |
| 17 | + |
| 18 | +const string DeviceID = "YourDeviceId"; |
| 19 | +const string IotBrokerAddress = "yourIOTHub.azure-devices.net"; |
| 20 | +const string SasKey = "the_SAS_token"; |
| 21 | +const string Ssid = "YouSsid"; |
| 22 | +const string Password = "YouWifiPassword"; |
| 23 | + |
| 24 | +bool ShoudIStop = false; |
| 25 | + |
| 26 | +// If you haven't uploaded the Azure certificate into your device, use this line: |
| 27 | +DeviceClient azureIoT = new DeviceClient(IotBrokerAddress, DeviceID, SasKey, azureCert: new X509Certificate(Resource.GetBytes(Resource.BinaryResources.AzureRoot))); |
| 28 | +// Otherwise you can just use this line: |
| 29 | +//DeviceClient azureIoT = new DeviceClient(IotBrokerAddress, DeviceID, SasKey); |
| 30 | + |
| 31 | +try |
| 32 | +{ |
| 33 | +wifiRetry: |
| 34 | + // Step 1: we must have a proper wifi connection |
| 35 | + if (!ConnectToWifi()) |
| 36 | + { |
| 37 | + // If we are not properly connected we will rety. Waiting 1 second and then we will try again. |
| 38 | + // You may in a real project want to adjust this pattern a bit. |
| 39 | + Thread.Sleep(1000); |
| 40 | + Console.WriteLine("Trying again to connect to your wifi. Please make sure that the information is correct."); |
| 41 | + goto wifiRetry; |
| 42 | + } |
| 43 | + |
| 44 | + // Step 2: setting up events and call backs. |
| 45 | + // We are subscribing to twin update, statuc changes and cloud to device. |
| 46 | + // Adjust by removing what you don't need. |
| 47 | + azureIoT.TwinUpdated += TwinUpdatedEvent; |
| 48 | + azureIoT.StatusUpdated += StatusUpdatedEvent; |
| 49 | + azureIoT.CloudToDeviceMessage += CloudToDeviceMessageEvent; |
| 50 | + |
| 51 | + // Adding few direct methods as well. |
| 52 | + // Adjust by removing what you don't need. |
| 53 | + azureIoT.AddMethodCallback(MethodCalbackTest); |
| 54 | + azureIoT.AddMethodCallback(MakeAddition); |
| 55 | + azureIoT.AddMethodCallback(RaiseExceptionCallbackTest); |
| 56 | + |
| 57 | + // Step 3: trying to open Azure IoT |
| 58 | + ConnectAzureIot(); |
| 59 | + |
| 60 | + // Ste 4: get the twin configuration. |
| 61 | + // Important: this require to have an Azure IoT |
| 62 | + var twin = azureIoT.GetTwin(new CancellationTokenSource(5000).Token); |
| 63 | + if (twin == null) |
| 64 | + { |
| 65 | + // We will just display an error message here. |
| 66 | + Console.WriteLine($"Can't get the twins"); |
| 67 | + // As an alternative, you can decide to close the connectin, go to sleep |
| 68 | + // And wake up after a while by uncommenting the following lines: |
| 69 | + //azureIoT.Close(); |
| 70 | + //Thread.Sleep(100); |
| 71 | + //Sleep.EnableWakeupByTimer(new TimeSpan(0, 0, 0, 10)); |
| 72 | + //Sleep.StartDeepSleep(); ; |
| 73 | + } |
| 74 | + |
| 75 | + Console.WriteLine($"Twin DeviceID: {twin.DeviceId}, #desired: {twin.Properties.Desired.Count}, #reported: {twin.Properties.Reported.Count}"); |
| 76 | + |
| 77 | + // Step 5: we can report our twin |
| 78 | + TwinCollection reported = new TwinCollection(); |
| 79 | + // This is just a basic example, you can adjust and report anything including real classes |
| 80 | + reported.Add("firmware", "myNano"); |
| 81 | + reported.Add("sdk", 0.2); |
| 82 | + azureIoT.UpdateReportedProperties(reported); |
| 83 | + |
| 84 | + // Step 6: we will publish some telemetry |
| 85 | + while (!ShoudIStop) |
| 86 | + { |
| 87 | + // Step 6: publishing the telemetry |
| 88 | + // This is just a static example but in general, you will have a real sensor and you will publish the data |
| 89 | + // Note that the standard format used in Azure IoT is Json. |
| 90 | + if (azureIoT.IsConnected) |
| 91 | + { |
| 92 | + // We only publish if we are connected! |
| 93 | + Console.WriteLine("Sending telemetry to Azure IoT"); |
| 94 | + azureIoT.SendMessage($"{{\"Temperature\":42,\"Pressure\":1023}}"); |
| 95 | + } |
| 96 | + else |
| 97 | + { |
| 98 | + Console.WriteLine("We are not connected, can't send telemetry"); |
| 99 | + } |
| 100 | + // Here we are waiting 20 seconds, you can adjust for any value. You can as well wait for a specific event. |
| 101 | + Thread.Sleep(20_000); |
| 102 | + } |
| 103 | + |
| 104 | + Console.WriteLine("A stop have been requested"); |
| 105 | + Thread.Sleep(Timeout.Infinite); |
| 106 | + |
| 107 | +} |
| 108 | +catch (Exception ex) |
| 109 | +{ |
| 110 | + // This global try catch is to make sure whatever happen, we will safely be able to handle anything. |
| 111 | + Console.WriteLine($"Global exception: {ex.Message})"); |
| 112 | + // In this example, we will sleep a bit and then reboot. |
| 113 | + ClosAndGoToSleep(); |
| 114 | +} |
| 115 | + |
| 116 | +Thread.Sleep(Timeout.InfiniteTimeSpan); |
| 117 | + |
| 118 | +void ConnectAzureIot() |
| 119 | +{ |
| 120 | +azureOpenRetry: |
| 121 | + bool isOpen = azureIoT.Open(); |
| 122 | + Console.WriteLine($"Connection is open: {isOpen}"); |
| 123 | + if (!isOpen) |
| 124 | + { |
| 125 | + azureIoT.Close(); |
| 126 | + // If we can't open, let's wait for 1 second and retry. You may want to adjust this time and used incremental waiting time. |
| 127 | + // You may in a real project want to adjust this pattern a bit. |
| 128 | + Thread.Sleep(1_000); |
| 129 | + Console.WriteLine("Trying to reconnect to Azure IoT. Please check that all the credentials are correct."); |
| 130 | + goto azureOpenRetry; |
| 131 | + } |
| 132 | +} |
| 133 | + |
| 134 | +bool ConnectToWifi() |
| 135 | +{ |
| 136 | + Console.WriteLine("Program Started, connecting to Wifi."); |
| 137 | + |
| 138 | + // As we are using TLS, we need a valid date & time |
| 139 | + // We will wait maximum 1 minute to get connected and have a valid date |
| 140 | + var success = WifiNetworkHelper.ConnectDhcp(Ssid, Password, requiresDateTime: true, token: new CancellationTokenSource(60_000).Token); |
| 141 | + if (!success) |
| 142 | + { |
| 143 | + Console.WriteLine($"Can't connect to wifi: {WifiNetworkHelper.Status}"); |
| 144 | + if (WifiNetworkHelper.HelperException != null) |
| 145 | + { |
| 146 | + Console.WriteLine($"WifiNetworkHelper.HelperException"); |
| 147 | + } |
| 148 | + } |
| 149 | + |
| 150 | + Console.WriteLine($"Date and time is now {DateTime.UtcNow}"); |
| 151 | + return success; |
| 152 | +} |
| 153 | + |
| 154 | +void ClosAndGoToSleep() |
| 155 | +{ |
| 156 | + azureIoT?.Close(); |
| 157 | + Thread.Sleep(1000); |
| 158 | + // Setup sleep for 10 seconds and then wake up. |
| 159 | + Sleep.EnableWakeupByTimer(new TimeSpan(0, 0, 0, 10)); |
| 160 | + Sleep.StartDeepSleep(); |
| 161 | +} |
| 162 | + |
| 163 | +void TwinUpdatedEvent(object sender, TwinUpdateEventArgs e) |
| 164 | +{ |
| 165 | + Console.WriteLine($"Twin update received: {e.Twin.Count}"); |
| 166 | +} |
| 167 | + |
| 168 | +void StatusUpdatedEvent(object sender, StatusUpdatedEventArgs e) |
| 169 | +{ |
| 170 | + Console.WriteLine($"Status changed: {e.IoTHubStatus.Status}, {e.IoTHubStatus.Message}"); |
| 171 | + // You may want to reconnect or use a similar retry mechanism |
| 172 | + if (e.IoTHubStatus.Status == Status.Disconnected) |
| 173 | + { |
| 174 | + Console.WriteLine("Being disconnected from Azure IoT"); |
| 175 | + // Trying to reconnect |
| 176 | + ConnectAzureIot(); |
| 177 | + } |
| 178 | +} |
| 179 | + |
| 180 | +string MethodCalbackTest(int rid, string payload) |
| 181 | +{ |
| 182 | + Console.WriteLine($"Call back called :-) rid={rid}, payload={payload}"); |
| 183 | + return "{\"Yes\":\"baby\",\"itisworking\":42}"; |
| 184 | +} |
| 185 | + |
| 186 | +string MakeAddition(int rid, string payload) |
| 187 | +{ |
| 188 | + Hashtable variables = (Hashtable)JsonConvert.DeserializeObject(payload, typeof(Hashtable)); |
| 189 | + int arg1 = (int)variables["arg1"]; |
| 190 | + int arg2 = (int)variables["arg2"]; |
| 191 | + return $"{{\"result\":{arg1 + arg2}}}"; |
| 192 | +} |
| 193 | + |
| 194 | +string RaiseExceptionCallbackTest(int rid, string payload) |
| 195 | +{ |
| 196 | + throw new Exception("I got you, it's to test the 504"); |
| 197 | +} |
| 198 | + |
| 199 | +void CloudToDeviceMessageEvent(object sender, CloudToDeviceMessageEventArgs e) |
| 200 | +{ |
| 201 | + Console.WriteLine($"Message arrived: {e.Message}"); |
| 202 | + foreach (string key in e.Properties.Keys) |
| 203 | + { |
| 204 | + Debug.Write($" Key: {key} = "); |
| 205 | + if (e.Properties[key] == null) |
| 206 | + { |
| 207 | + Console.WriteLine("null"); |
| 208 | + } |
| 209 | + else |
| 210 | + { |
| 211 | + Console.WriteLine((string)e.Properties[key]); |
| 212 | + } |
| 213 | + } |
| 214 | + |
| 215 | + // Example of a simple stop message, in this case, we are stopping to send the telemetry. |
| 216 | + if (e.Message == "stop") |
| 217 | + { |
| 218 | + ShoudIStop = true; |
| 219 | + } |
| 220 | + else if (e.Message == "reboot42") |
| 221 | + { |
| 222 | + // Here, an example where we will just reboot the device. |
| 223 | + Console.WriteLine("Reboot requested"); |
| 224 | + ClosAndGoToSleep(); |
| 225 | + } |
| 226 | +} |
0 commit comments