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 I could connect to the AllThingsTalk MQTT API then format topics and payloads correctly.
![](https://blog.devmobile.co.nz/wp-content/uploads/2020/02/mqttclientdata.jpg?w=978)
The AllThingsTalk MQTT broker, username, and device ID are required command line parameters.
namespace devmobile.Mqtt.TestClient.AllThingsTalk
{
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Disconnecting;
using MQTTnet.Client.Options;
using MQTTnet.Client.Receiving;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
class Program
{
private static IMqttClient mqttClient = null;
private static IMqttClientOptions mqttOptions = null;
private static string server;
private static string username;
private static string deviceID;
static void Main(string[] args)
{
MqttFactory factory = new MqttFactory();
mqttClient = factory.CreateMqttClient();
if ((args.Length != 3))
{
Console.WriteLine("[MQTT Server] [UserName] [ClientID]");
Console.WriteLine("Press <enter> to exit");
Console.ReadLine();
return;
}
server = args[0];
username = args[1];
deviceID = args[2];
Console.WriteLine($"MQTT Server:{server} DeviceID:{deviceID}");
// AllThingsTalk formatted device state update topic
string topicD2C = $"device/{deviceID}/state";
mqttOptions = new MqttClientOptionsBuilder()
.WithTcpServer(server)
.WithCredentials(username, "HighlySecurePassword")
.WithClientId(deviceID)
.WithTls()
.Build();
mqttClient.UseDisconnectedHandler(new MqttClientDisconnectedHandlerDelegate(e => MqttClient_Disconnected(e)));
mqttClient.UseApplicationMessageReceivedHandler(new MqttApplicationMessageReceivedHandlerDelegate(e => MqttClient_ApplicationMessageReceived(e)));
mqttClient.ConnectAsync(mqttOptions).Wait();
// AllThingsTalk formatted device command with wildcard topic
string topicC2D = $"device/{deviceID}/asset/+/command";
mqttClient.SubscribeAsync(topicC2D, MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce).GetAwaiter().GetResult();
while (true)
{
JObject payloadJObject = new JObject();
double temperature = 22.0 + (DateTime.UtcNow.Millisecond / 1000.0);
temperature = Math.Round( temperature, 1 );
double humidity = 50 + (DateTime.UtcNow.Millisecond / 100.0);
humidity = Math.Round(humidity, 1);
JObject temperatureJObject = new JObject
{
{ "value", temperature }
};
payloadJObject.Add("Temperature", temperatureJObject);
JObject humidityJObject = new JObject
{
{ "value", humidity }
};
payloadJObject.Add("Humidity", humidityJObject);
string payload = JsonConvert.SerializeObject(payloadJObject);
Console.WriteLine($"Topic:{topicD2C} Payload:{payload}");
var message = new MqttApplicationMessageBuilder()
.WithTopic(topicD2C)
.WithPayload(payload)
.WithAtMostOnceQoS()
// .WithAtLeastOnceQoS()
.Build();
Console.WriteLine("PublishAsync start");
mqttClient.PublishAsync(message).Wait();
Console.WriteLine("PublishAsync finish");
Thread.Sleep(15100);
}
}
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);
}
}
}
The AllThingsTalk device configuration was relatively easy but I need to investigate “Gateway” functionality and configuration further.
![](https://blog.devmobile.co.nz/wp-content/uploads/2020/02/humidityassetsetup.jpg?w=854)
![](https://blog.devmobile.co.nz/wp-content/uploads/2020/02/watchdog-1.jpg?w=486)
![](https://blog.devmobile.co.nz/wp-content/uploads/2020/02/commandsend.jpg?w=1024)
![](https://blog.devmobile.co.nz/wp-content/uploads/2020/02/commandreceive.jpg?w=983)
The ability to look at message payloads in the Debug tab would be very helpful when working out why a payload was not being processed as expected.
![](https://blog.devmobile.co.nz/wp-content/uploads/2020/02/debug.jpg?w=1024)
Overall the AllThingsTalk configuration went fairly smoothly, though I need to investigate the “Gateway” configuration and functionality further. The way that assets are name by the system could make support in my MQTT Gateway more complex.