como-usar-el-protocolo-mqtt-con-c-y-la-libreria-mqttnet

Cómo usar el protocolo MQTT con C# y la librería MQTTNET

MQTTNet es una librería .NET que nos permite implementa una comunicación bajo protocolo MQTT, actuando tanto como cliente como broker.

La librería es una de las más completas disponibles para .NET. Está diseñada para ser ligera y altamente eficiente, siendo capaz de gestionar decenas de miles de mensajes por segundos.

MQTTNet soporta las versiones de protocolo MQTT 3.1.0, 3.1.1 y 5.0.0, así como comunicación tanto por TCP como Websockets, en ambos casos con o sin TLS.

Es multiplataforma, y compatible con .NET Standard 1.3+, .NET Core 1.1+.NET, Framework 4.5.2+, Xamarin.Android 7.5+, Mono 5.2+, entre otros. Por tanto, es posible ejecutarlo en Windows, Linux y macOs.

Usando MQTTNet

Podemos añadir la biblioteca a un proyecto de .NET fácilmente, a través del paquete Nuget correspondiente.

Install-Package MQTTnet

La librería proporciona una extensa documentación en la página web del proyecto, incluidos numerosos ejemplos de uso en la wiki https://github.com/chkr1011/MQTTnet/wiki.

No obstante, un ejemplo sencillo de uso sería el siguiente.

public class MqttService
{
    IMqttClient mqttClient;
     
    public async Task Start(string brokerIp, string clientId, Action<string> callback = null)
    {
        var factory = new MqttFactory();

        var options = new MqttClientOptionsBuilder()
        .WithTcpServer(brokerIp)
        .WithClientId(clientId)
        .Build();

        mqttClient = factory.CreateMqttClient();

        mqttClient.ConnectedAsync += (async e =>
        {
            Console.WriteLine("MQTT connected");
            Console.WriteLine("");
            await mqttClient.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("my/topic/receive").Build());
        });

        mqttClient.ApplicationMessageReceivedAsync += (async e =>
        {
            var payload = Encoding.UTF8.GetString(e.ApplicationMessage.PayloadSegment);

            Console.WriteLine("Received MQTT message");
            Console.WriteLine($" - Topic = {e.ApplicationMessage.Topic}");
            Console.WriteLine($" - Payload = {payload}");
            Console.WriteLine($" - QoS = {e.ApplicationMessage.QualityOfServiceLevel}");
            Console.WriteLine($" - Retain = {e.ApplicationMessage.Retain}");
            Console.WriteLine("");

            callback?.Invoke(payload);
        });

        mqttClient.DisconnectedAsync += (async e =>
        {
            Console.WriteLine("MQTT reconnecting");
            await Task.Delay(TimeSpan.FromSeconds(5));
            await mqttClient.ConnectAsync(options, CancellationToken.None);
        });

        await mqttClient.ConnectAsync(options, CancellationToken.None);
    }

    public async Task SendCode(string message)
    {
        var topic = "my/topic/send";

        Console.WriteLine("Publish MQTT message");
        Console.WriteLine($" - Topic: {topic}");
        Console.WriteLine($" - Payload: {message}");
        Console.WriteLine("");

        var applicationMessage = new MqttApplicationMessageBuilder()
          .WithTopic(topic)
          .WithPayload(message)
          .Build();
        await mqttClient.PublishAsync(applicationMessage);
    }
}

Con este servicio de ejemplo que nos hemos creado el uso desde una aplicación de consola, por ejemplo, sería así de sencillo,

MqttService mqttService = new();

string clientId = Guid.NewGuid().ToString();
await mqttService.Start("your_broker_address", clientId, async (m) =>
{
        // hacer algo con el mensaje recibido
});

Console.ReadLine();