Created
August 14, 2020 15:43
-
-
Save sandervandevelde/06bbcd8136f864890e208a9b5bac1eb0 to your computer and use it in GitHub Desktop.
Azure IoT device client SDK Example (.Net C#)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Azure.Storage.Blobs; | |
using Microsoft.Azure.Devices.Client; | |
using Microsoft.Azure.Devices.Client.Transport; | |
using Microsoft.Azure.Devices.Shared; | |
using Newtonsoft.Json; | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Text; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace DeviceClientConsoleApp | |
{ | |
internal class Program | |
{ | |
private static void Main(string[] args) | |
{ | |
var connectionString = "[your device connection string]"; | |
using var deviceClient = DeviceClient.CreateFromConnectionString(connectionString); | |
//// Set various callback messages: connection status, device twin, a single named method, multiple methods | |
SetVariousCallbackMethods(deviceClient); | |
//// open connection explicitly | |
deviceClient.OpenAsync().Wait(); | |
//// Force the retrieval of the devicetwin | |
ForceDeviceTwinRetrieval(deviceClient); | |
//// send a single message | |
SendSingleMessage(deviceClient); | |
//// send multiple message in batch in one call | |
SendBatchOfMessages(deviceClient); | |
//// Send a file to the Blob storage configured in the IoT Hub | |
SendFileToBlobStorage(deviceClient); | |
//// Stall application closing | |
Console.WriteLine("Press a key to exit..."); | |
Console.ReadKey(); | |
} | |
private static void SendFileToBlobStorage(DeviceClient deviceClient) | |
{ | |
//// Send a file | |
using var stream = File.OpenRead("upload.txt"); | |
var fileUploadSasUri = deviceClient.GetFileUploadSasUriAsync( | |
new FileUploadSasUriRequest | |
{ | |
BlobName = $"upload-{DateTime.Now.Ticks}.txt" | |
}).Result; | |
var correlationId = fileUploadSasUri.CorrelationId; | |
var isSuccess = false; | |
try | |
{ | |
var blobClient = new BlobClient(fileUploadSasUri.GetBlobUri()); | |
var response = blobClient.UploadAsync(stream).Result; | |
isSuccess = (response.GetRawResponse().Status == 201); | |
} | |
catch | |
{ | |
// ignore all exceptions | |
} | |
finally | |
{ | |
// Be sure to complete the fileupload so we prevent : Number of active file upload requests exceeded limit | |
var fileUploadCompletionNotification = new FileUploadCompletionNotification { CorrelationId = correlationId, IsSuccess = isSuccess }; | |
deviceClient.CompleteFileUploadAsync(fileUploadCompletionNotification).Wait(); | |
Console.WriteLine($"A file is sent; success={isSuccess} - {fileUploadSasUri.BlobName}"); | |
} | |
} | |
private static void ForceDeviceTwinRetrieval(DeviceClient deviceClient) | |
{ | |
var twin = deviceClient.GetTwinAsync().Result; | |
OnDesiredPropertyChanged(twin.Properties.Desired, deviceClient).Wait(); | |
Console.WriteLine("The Devicetwin is forced retrieved"); | |
} | |
private static void SetVariousCallbackMethods(DeviceClient deviceClient) | |
{ | |
deviceClient.SetConnectionStatusChangesHandler(ConnectionStatusChangeHandler); | |
deviceClient.SetDesiredPropertyUpdateCallbackAsync(OnDesiredPropertyChanged, deviceClient).ConfigureAwait(false); | |
deviceClient.SetMethodHandlerAsync("Ping", HandleMethodPing, deviceClient).ConfigureAwait(false); | |
deviceClient.SetMethodDefaultHandlerAsync(HandleDefaultMethods, deviceClient).ConfigureAwait(false); | |
var thread = new Thread(() => ThreadBody(deviceClient)); | |
thread.Start(); | |
Console.WriteLine("Callback methods are set"); | |
} | |
private static void SendBatchOfMessages(DeviceClient deviceClient) | |
{ | |
string jsonDataOne = "{ \"number\": \"one\" }"; | |
var messageOne = new Message(Encoding.ASCII.GetBytes(jsonDataOne)); | |
messageOne.Properties.Add("batch", "true"); | |
string jsonDataTwo = "{ \"number\": \"two\" }"; | |
var messageTwo = new Message(Encoding.ASCII.GetBytes(jsonDataTwo)); | |
messageTwo.Properties.Add("batch", "true"); | |
deviceClient.SendEventBatchAsync(new List<Message> { messageOne, messageTwo }).Wait(); | |
Console.WriteLine("Messages are sent in batch"); | |
} | |
private static void SendSingleMessage(DeviceClient deviceClient) | |
{ | |
string jsonData = "{ \"single\":true }"; | |
var message = new Message(Encoding.ASCII.GetBytes(jsonData)); | |
message.Properties.Add("messagetype", "normal"); | |
deviceClient.SendEventAsync(message).Wait(); | |
Console.WriteLine("A single message is sent"); | |
} | |
private static async void ThreadBody(object deviceClient) | |
{ | |
var client = deviceClient as DeviceClient; | |
Console.WriteLine("Waiting for C2D messages (aka commands)"); | |
while (true) | |
{ | |
// The following line is blocking until a timeout occurs | |
using var message = await client.ReceiveAsync(); | |
if (message == null) | |
{ | |
Console.WriteLine("Timeout. Command is null"); | |
continue; | |
} | |
string data = Encoding.UTF8.GetString(message.GetBytes()); | |
Console.WriteLine($"A message is received with body {data}"); | |
await client.CompleteAsync(message); // mark the message as handled | |
//await client.RejectAsync(message); // drops the message as unhandled | |
//await client.AbandonAsync(message); // puts message back on queue | |
} | |
} | |
private static Task<MethodResponse> HandleMethodPing(MethodRequest methodRequest, object userContext) | |
{ | |
Console.WriteLine($"method {methodRequest.Name} handled with body {methodRequest.DataAsJson}"); | |
return Task.FromResult(new MethodResponse(new byte[0], 200)); | |
} | |
private static Task<MethodResponse> HandleDefaultMethods(MethodRequest methodRequest, object userContext) | |
{ | |
Console.WriteLine($"Default method {methodRequest.Name} handled with body {methodRequest.DataAsJson}"); | |
return Task.FromResult(new MethodResponse(new byte[0], 200)); | |
} | |
private static void ConnectionStatusChangeHandler(ConnectionStatus status, ConnectionStatusChangeReason reason) | |
{ | |
Console.WriteLine($"Connection Status Changed to {status} ({reason}) at {DateTime.Now}"); | |
} | |
private static async Task OnDesiredPropertyChanged(TwinCollection desiredProperties, object userContext) | |
{ | |
Console.WriteLine("One or more device twin desired properties changed:"); | |
Console.WriteLine(JsonConvert.SerializeObject(desiredProperties)); | |
var client = userContext as DeviceClient; | |
var reportedProperties = new TwinCollection | |
{ | |
["DateTimeLastDesiredPropertyChangeReceived"] = DateTime.Now | |
}; | |
await client.UpdateReportedPropertiesAsync(reportedProperties).ConfigureAwait(false); | |
Console.WriteLine("Sent current time as reported property to device twin"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment