As I’m testing my Message Queue Telemetry Transport(MQTT) LoRa gateway I’m building a proof of concept(PoC) .Net core console application for each IoT platform I would like to support.
This PoC was to confirm that my device could connect to the Microsoft Azure IoT Hub MQTT API then format topics and payloads correctly.

I had tried with a couple of different MQTT libraries from micro controllers and embedded devices without success. With the benefit of hindsight (plus this article) I think I had the SAS key format wrong.
The Azure IoT Hub MQTT broker requires only a server name (fully resolved CName), device ID and SAS Key.
class Program
{
private static IMqttClient mqttClient = null;
private static IMqttClientOptions mqttOptions = null;
private static string server;
private static string username;
private static string password;
private static string clientId;
private static string topicD2C;
private static string topicC2D;
static void Main(string[] args)
{
MqttFactory factory = new MqttFactory();
mqttClient = factory.CreateMqttClient();
if (args.Length != 3)
{
Console.WriteLine("[AzureIoTHubHostName] [deviceID] [SASKey]");
Console.WriteLine("Press <enter> to exit");
Console.ReadLine();
return;
}
server = args[0];
clientId = args[1];
sasKey= args[2];
username = $"{server}/{clientId}/api-version=2018-06-30";
topicD2C = $"devices/{clientId}/messages/events/";
topicC2D = $"devices/{clientId}/messages/devicebound/#";
Console.WriteLine($"MQTT Server:{server} Username:{username} ClientID:{clientId}");
mqttOptions = new MqttClientOptionsBuilder()
.WithTcpServer(server, 8883)
.WithCredentials(username, sasKey)
.WithClientId(clientId)
.WithTls()
.Build();
mqttClient.UseDisconnectedHandler(new MqttClientDisconnectedHandlerDelegate(e => MqttClient_Disconnected(e)));
mqttClient.UseApplicationMessageReceivedHandler(new MqttApplicationMessageReceivedHandlerDelegate(e => MqttClient_ApplicationMessageReceived(e)));
mqttClient.ConnectAsync(mqttOptions).Wait();
mqttClient.SubscribeAsync(topicC2D, MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce).GetAwaiter().GetResult();
while (true)
{
JObject payloadJObject = new JObject();
payloadJObject.Add("OfficeTemperature", "22." + DateTime.UtcNow.Millisecond.ToString());
payloadJObject.Add("OfficeHumidity", (DateTime.UtcNow.Second + 40).ToString());
string payload = JsonConvert.SerializeObject(payloadJObject);
Console.WriteLine($"Topic:{topicD2C} Payload:{payload}");
var message = new MqttApplicationMessageBuilder()
.WithTopic(topicD2C)
.WithPayload(payload)
.WithAtLeastOnceQoS()
.Build();
Console.WriteLine("PublishAsync start");
mqttClient.PublishAsync(message).Wait();
Console.WriteLine("PublishAsync finish");
Thread.Sleep(30100);
}
}
private static void MqttClient_ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs e)
{
Console.WriteLine($"ClientId:{e.ClientId} Topic:{e.ApplicationMessage.Topic} Payload:{e.ApplicationMessage.ConvertPayloadToString()}");
}
private static async void MqttClient_Disconnected(MqttClientDisconnectedEventArgs e)
{
Debug.WriteLine("Disconnected");
await Task.Delay(TimeSpan.FromSeconds(5));
try
{
await mqttClient.ConnectAsync(mqttOptions);
}
catch (Exception ex)
{
Debug.WriteLine("Reconnect failed {0}", ex.Message);
}
}
}
Overall the initial configuration went smoothly after I figured out the required Quality of Service (QoS) settings, and the SAS Key format.
Using the approach described in the Microsoft documentation I manually generated the SAS Key.(In my Netduino samples I have code for generating a SAS Key in my HTTPS Azure IoT Hub Client)


Once I had the configuration correct I could see telemetry from the device and send it messages.

In a future post I will upload data to the Azure IoT Central for display. Then explore using a “module” attached to a device which maybe useful for my field gateway.
Pingback: Azure IoT Hub SAS Keys revisited | devMobile's blog
Pingback: Azure IoT Hub SAS Tokens revisited again | devMobile's blog
Pingback: Azure IoT Hub SAS Tokens revisited yet again | devMobile's blog