Last active
May 5, 2022 14:51
-
-
Save ridomin/8572122aa346e6bedd2ae0de0b95fcd0 to your computer and use it in GitHub Desktop.
Demystify IoTHub SDKs
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
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<OutputType>Exe</OutputType> | |
<TargetFramework>net6.0</TargetFramework> | |
<RootNamespace>demistify_iothub</RootNamespace> | |
<ImplicitUsings>enable</ImplicitUsings> | |
<Nullable>enable</Nullable> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="MQTTnet" Version="3.1.2" /> | |
</ItemGroup> | |
</Project> |
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 MQTTnet.Client.Options; | |
using System.Text; | |
namespace demistify_iothub | |
{ | |
public static class MqttNetExtensions | |
{ | |
public static MqttClientOptionsBuilder WithAzureIoTHubCredentialsSas(this MqttClientOptionsBuilder builder, string hostName, string deviceId, string sasKey, string modelId = "", int sasMinutes = 60) | |
{ | |
(string username, string password) = SasAuth.GenerateHubSasCredentials(hostName, deviceId, sasKey, modelId, sasMinutes); | |
builder | |
.WithTcpServer(hostName, 8883) | |
.WithTls() | |
.WithClientId(deviceId) | |
.WithCredentials(username, password); | |
return builder; | |
} | |
} | |
} |
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 demistify_iothub; | |
using MQTTnet; | |
using MQTTnet.Client; | |
using MQTTnet.Client.Options; | |
using System.Text; | |
using System.Text.Json; | |
using System.Web; | |
// Connect | |
IMqttClient mqttClient = new MqttFactory().CreateMqttClient(); | |
var connAck = await mqttClient.ConnectAsync(new MqttClientOptionsBuilder() | |
.WithAzureIoTHubCredentialsSas( | |
hostName: "rido-freetier.azure-devices.net", | |
deviceId: "myDevice", | |
sasKey: "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA=" | |
) | |
.Build()); | |
Console.WriteLine($"connAck resaon: {connAck.ResultCode} IsConnected: {mqttClient.IsConnected}"); | |
// Telemetry | |
var pubAck = await mqttClient.PublishAsync( | |
$"devices/{mqttClient.Options.ClientId}/messages/events/", | |
JsonSerializer.Serialize(new { Environment.WorkingSet }) ); | |
Console.WriteLine($"Telemetry sent with pubAck: {pubAck.ReasonCode}" ); | |
await mqttClient.SubscribeAsync("$iothub/methods/POST/#"); | |
await mqttClient.SubscribeAsync("$iothub/twin/res/#"); | |
await mqttClient.SubscribeAsync("$iothub/twin/PATCH/properties/desired/#"); | |
mqttClient.UseApplicationMessageReceivedHandler(async m => | |
{ | |
var topic = m.ApplicationMessage.Topic; | |
var segments = topic.Split('/'); | |
// Command | |
if (topic.StartsWith("$iothub/methods/POST/")) | |
{ | |
var qs = HttpUtility.ParseQueryString(segments[^1]); | |
_ = int.TryParse(qs["$rid"], out int rid); | |
var cmdName = segments[3]; | |
var cmdPayload = Encoding.UTF8.GetString(m.ApplicationMessage.Payload); | |
Console.WriteLine($"Executing command {cmdName} with rid {rid} and payload {cmdPayload}"); | |
await mqttClient.PublishAsync($"$iothub/methods/res/200/?$rid={rid}", cmdPayload); | |
} | |
//GetTwin reponse | |
if (topic.StartsWith("$iothub/twin/res/200")) | |
{ | |
var qs = HttpUtility.ParseQueryString(segments[^1]); | |
_ = int.TryParse(qs["$rid"], out int rid); | |
var twin = Encoding.UTF8.GetString(m.ApplicationMessage.Payload); | |
Console.WriteLine(twin); | |
} | |
// UpdateTwin response | |
if (topic.StartsWith("$iothub/twin/res/204")) | |
{ | |
var qs = HttpUtility.ParseQueryString(segments[^1]); | |
var twinVersion = Convert.ToInt32(qs["$version"]); | |
System.Console.WriteLine(twinVersion); | |
} | |
if (topic.StartsWith("$iothub/twin/PATCH/properties/desired")) | |
{ | |
string msg = Encoding.UTF8.GetString(m.ApplicationMessage.Payload); | |
System.Console.WriteLine(msg); | |
} | |
}); | |
await mqttClient.PublishAsync($"$iothub/twin/GET/?$rid=1"); | |
await mqttClient.PublishAsync( | |
"$iothub/twin/PATCH/properties/reported/?$rid=2", | |
JsonSerializer.Serialize(new { myProperty = "myValue" })); | |
Console.ReadLine(); |
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 System.Text; | |
namespace demistify_iothub | |
{ | |
public class SasAuth | |
{ | |
private const string apiversion_2020_09_30 = "2020-09-30"; | |
public static string GetUserName(string hostName, string deviceId, string modelId = "") => | |
$"{hostName}/{deviceId}/?api-version={apiversion_2020_09_30}&model-id={modelId}"; | |
private static string Sign(string requestString, string key) | |
{ | |
using (var algorithm = new System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(key))) | |
{ | |
return Convert.ToBase64String(algorithm.ComputeHash(Encoding.UTF8.GetBytes(requestString))); | |
} | |
} | |
public static string CreateSasToken(string resource, string sasKey, int minutes) | |
{ | |
var expiry = DateTimeOffset.UtcNow.AddMinutes(minutes).ToUnixTimeSeconds().ToString(); | |
var sig = System.Net.WebUtility.UrlEncode(Sign($"{resource}\n{expiry}", sasKey)); | |
return $"SharedAccessSignature sr={resource}&sig={sig}&se={expiry}"; | |
} | |
public static (string username, string password) GenerateHubSasCredentials(string hostName, string deviceId, string sasKey, string modelId, int minutes = 60) => | |
(GetUserName(hostName, deviceId, modelId), CreateSasToken($"{hostName}/devices/{deviceId}", sasKey, minutes)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
companion code for post https://blog.rido.dev/mqtt/2022/04/04/demystify-iothub-sdk