Search code examples
c#async-awaittaskmqttnet

MqttNet version 4.1.3.563 Basic example


Following this example I have now therefore been required to update the MQTT.NET from version 3 (that works thanks the provided help) to version 4.

A very basic set of capabilities would be enough:

  1. Connect to an adress with a timeout
  2. Check if the connection has gone well
  3. Receive messages
  4. check disconnection

that was extremely easy in version 3

MqttClientOptionsBuilder builder = new MqttClientOptionsBuilder()
                                .WithClientId("IoApp" + HelperN.MQTT.GetClientID(true))
                                .WithTcpServer("localhost", 1883);

ManagedMqttClientOptions options = new ManagedMqttClientOptionsBuilder()
                                .WithAutoReconnectDelay(TimeSpan.FromSeconds(60))
                                .WithClientOptions(builder.Build())
                                .Build();

mqttClient = new MqttFactory().CreateManagedMqttClient();

mqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(OnConnected);
mqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(OnDisconnected);
mqttClient.ConnectingFailedHandler = new ConnectingFailedHandlerDelegate(OnConnectingFailed);

mqttClient.SubscribeAsync(...);
mqttClient.SubscribeAsync(...);
mqttClient.StartAsync(options).GetAwaiter().GetResult();

mqttClient.UseApplicationMessageReceivedHandler(args => { OnMessageReceived(args); });

but when it comes to version 4 if I have to relay on those examples I have problems. Let's start from the connection

public static async Task Connect_Client_Timeout()
{
    /*
     * This sample creates a simple MQTT client and connects to an invalid broker using a timeout.
     * 
     * This is a modified version of the sample _Connect_Client_! See other sample for more details.
     */

    var mqttFactory = new MqttFactory();
    strError = String.Empty;

    using (var mqttClient = mqttFactory.CreateMqttClient())
    {
        var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer("aaaa127.0.0.1",1883).Build();

        try
        {
                
            using (var timeoutToken = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
            {
                await mqttClient.ConnectAsync(mqttClientOptions, timeoutToken.Token);
            }
        }
        catch (OperationCanceledException exc)
        {
            strError = "Connect_Client_Timeout exc:" + exc.Message;
        }
    }
}

And I call this task from the main awaiting the result.

var connectTask  = Connect_Client_Timeout();
connectTask.Wait();<-----never ends

Since I put a wrong address "aaaa127.0.0.1" I expect a failure after 5 seconds. But the connectTask.Wait never ends. But even if I put the right address "127.0.0.1" it never exits. So perhaps the error stands in the connectTask.Wait();.


Solution

  • The solution is here In short you have to do this:

    static async Task  Connect()
    {
        IManagedMqttClient _mqttClient = new MqttFactory().CreateManagedMqttClient();
    
        // Create client options object
        MqttClientOptionsBuilder builder = new MqttClientOptionsBuilder()
                                            .WithClientId("behroozbc")
                                            .WithTcpServer("localhost");
        ManagedMqttClientOptions options = new ManagedMqttClientOptionsBuilder()
                                    .WithAutoReconnectDelay(TimeSpan.FromSeconds(60))
                                    .WithClientOptions(builder.Build())
                                    .Build();
    
    
    
        // Set up handlers
        _mqttClient.ConnectedAsync += _mqttClient_ConnectedAsync;
    
    
        _mqttClient.DisconnectedAsync += _mqttClient_DisconnectedAsync;
    
    
        _mqttClient.ConnectingFailedAsync += _mqttClient_ConnectingFailedAsync;
    
    
        // Connect to the broker
        await _mqttClient.StartAsync(options);
    
        // Send a new message to the broker every second
        while (true)
        {
            string json = JsonSerializer.Serialize(new { message = "Hi Mqtt", sent = DateTime.UtcNow });
            await _mqttClient.EnqueueAsync("behroozbc.ir/topic/json", json);
    
            await Task.Delay(TimeSpan.FromSeconds(1));
        }
        Task _mqttClient_ConnectedAsync(MqttClientConnectedEventArgs arg)
        {
            Console.WriteLine("Connected");
            return Task.CompletedTask;
        };
        Task _mqttClient_DisconnectedAsync(MqttClientDisconnectedEventArgs arg)
        {
            Console.WriteLine("Disconnected");
            return Task.CompletedTask;
        };
        Task _mqttClient_ConnectingFailedAsync(ConnectingFailedEventArgs arg)
        {
            Console.WriteLine("Connection failed check network or broker!");
            return Task.CompletedTask;
        }
    }
    

    and then just call Connect() and rely on the subscribed examples