Mqttnet: Upgrade-Guide from 2.8.5 to 3.0.0

Created on 6 May 2019  路  15Comments  路  Source: chkr1011/MQTTnet

As you updated your NuGet package yesterday, I updated it today in my application.

There are some major changes, where I'm not sure how to modify my code correctly.

A upgrade guide in your wiki would be very helpful (starting with your "BREAKING CHANGES").

As for me: How to update from client.Disconnected += async (sender, args) { /* stuff to do when disconnected */ }; to your new client.DisconnectedHandler ?

... and why did you remove the good old style of the subscriptionresult.failure ?

Thanks so far

Most helpful comment

The reason is that event handlers are not fully compatible with async. So having them in the first place was wrong. The new approach is fully compatible with async. The new approach gives you 3 different ways on handling events.

  1. Implement the required interface of a handler in your own class. You can do whatever you want. You can access fields. Inject stuff etc.
  2. If you don't need that and your handler is basically a one-liner you can use the "Delegate" classes which accept a async function.
  3. If you don't have async code you can still use the "Delegate" class because it also supports a not async method (Action instead of Func).

This gives you some flexibility. If you want to call multiple handlers you have to implement this on your own (create a new class and implement the required interface). This also allows you to deal with special use cases like stopping the event handler chain if one call fails or move data from the first handler to another one. This was all impossible when using event handlers.

All 15 comments

Seconded!

Can someone say where Serializer went, and MqttProtocolVersion please?

OK, found MqttProtocolVersion - it's now in:

using MQTTnet.Formatter;

@AndreasAmMueller

I'm getting there, using something like:

var client = new MqttFactory().CreateManagedMqttClient();

client.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(e => OnAppMessage(e));
client.ConnectedHandler = new MqttClientConnectedHandlerDelegate(e => OnConnected(e));
client.ConnectingFailedHandler = new ConnectingFailedHandlerDelegate(e => OnConnectingFailed(e));
client.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(e => OnDisconnected(e));

    protected virtual void OnAppMessage(MqttApplicationMessageReceivedEventArgs e)
    {
    }

    protected virtual void OnConnected(MqttClientConnectedEventArgs e)
    {
    }

    protected virtual void OnConnectingFailed(ManagedProcessFailedEventArgs e)
    {
    }

    protected virtual void OnDisconnected(MqttClientDisconnectedEventArgs e)
    {
    }

HTH,
Jim

Hi,
basically some new namespaces were introduced. Visual Studio or Resharper should be able to import them properly.

For an example for handlers please read the Wiki. At the moment I have to time to put an upgrade guide together. Probably within the next days or weeks.

_SubscriptionResult.Failure_ is now _UnspecifiedError_. This comes from new MQTTv5 specification where this value is renamed to the new value. So I had to decide to rely on _Failure_ or move to _UnspecifiedError_. The strategy of this library is to provide a uniform API over MQTTv3.1 MQTTv3.1.1 and MQTTv5.0.0. So it becomes __UnspecifiedError_ now.

Best regards
Christian

Thank you :-)

Your answers helped me so far.

I鈥榣l leave this issue open as a upgrade guide would be very nice ;-)

Hi @chkr1011 ,

How can I connect multiple handlers on new 3.0.0 event async handlers?
Using UseApplicationMessageReceivedHandler replace old handler with the new one.

Temporarly I save the old one and I launch it inner new handler.. but it is not really async, it is a chain.

What are the new Async Handlers benefits over EventHandlers?
I can't find documentation on this pattern.

Thank'you

            var autoReset = new AutoResetEvent(false);

            var oldHandler = _ioTServer.ApplicationMessageReceivedHandler;

            _ioTServer.UseApplicationMessageReceivedHandler(async e => {

                if (oldHandler != null)
                    await oldHandler.HandleApplicationMessageReceivedAsync(e);

                if (e.ApplicationMessage.Topic == topic)
                {
                    Console.WriteLine($"RECEIVED {e.ApplicationMessage.Topic}");
                    autoReset.Set();
                }
            });

            // Wait for send confirmation
            var result = autoReset.WaitOne(SEND_TIMEOUT);
            _ioTServer.UseApplicationMessageReceivedHandler(oldHandler);

The reason is that event handlers are not fully compatible with async. So having them in the first place was wrong. The new approach is fully compatible with async. The new approach gives you 3 different ways on handling events.

  1. Implement the required interface of a handler in your own class. You can do whatever you want. You can access fields. Inject stuff etc.
  2. If you don't need that and your handler is basically a one-liner you can use the "Delegate" classes which accept a async function.
  3. If you don't have async code you can still use the "Delegate" class because it also supports a not async method (Action instead of Func).

This gives you some flexibility. If you want to call multiple handlers you have to implement this on your own (create a new class and implement the required interface). This also allows you to deal with special use cases like stopping the event handler chain if one call fails or move data from the first handler to another one. This was all impossible when using event handlers.

Ok, I understand.
So, I have to implement the interface and in my class I have to build the multiple subscription logic.
I think that was already possible without custom implementation but it's ok.

Thanks for the explanation.

How to use the new version about handlers @chkr1011?

For example:

````
IMqttServer mqttServer = new MqttFactory().CreateMqttServer();

mqttServer.ClientSubscribedTopicHandler = new MqttServerClientSubscribedHandlerDelegate(context =>
{

});
````

How to use mqttServer.ClientSubscribedTopicHandler not inline, but call a method separate?

You can set the handler properties to null or use Use...Handler(null).

@chkr1011, I think I explained what I meant by wrong.

This is the code

IMqttServer mqttServer = new MqttFactory().CreateMqttServer();

mqttServer.ClientSubscribedTopicHandler = new MqttServerClientSubscribedHandlerDelegate(context =>
{

});

I want to use something like this:

IMqttServer mqttServer = new MqttFactory().CreateMqttServer();

mqttServer.ClientSubscribedTopicHandler = Handler();

public void Handler(Args args)
{

}

This should work.

void Handler(MqttApplicationMessageReceivedEventArgs args)
{
         //...
}

client.UseApplicationMessageReceivedHandler(Handler);

Handler using as your examples work only in: Conected, Disconected and MessageReceived. And the Subscribed and Unsubscribed? How to use as your example?

I will try to summarize this and add it to the wiki.

@chkr1011 What's the point with the IMqttPacketSerializer and MqttPacketSerializer? Where did they go?

And how do you create a ManagedClient now? var client = new MqttFactory().CreateManagedMqttClient(); doesn't work in version 3.0.0. Check https://github.com/chkr1011/MQTTnet/issues/673, too.

By the way, the guide is here: https://github.com/chkr1011/MQTTnet/wiki/Upgrading-guide.
Feel free to add things that are missing by opening new issues.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

taroyutao picture taroyutao  路  4Comments

laarlinn picture laarlinn  路  7Comments

LADSoft picture LADSoft  路  4Comments

pournasserian picture pournasserian  路  7Comments

bilalmalik777 picture bilalmalik777  路  7Comments