Xamarin.Forms using Mqtt

We can using of course mqtt in Xamarin.Form via dependency service / Xamarin.Forms.MessagingCenter, event or simply create a class instance. We are following the last option.

First step, we need to install the MQTTnet NuGet Package for the Solution. (So in each project.)

.NET Standard Library:

We need to create an MqttClientRepository class in the .NET Standard Library.

public class MqttClientRepository
    {
        Dictionary<string, TopicFilter> _topicFilter;

        private static IMqttClient client;

        public IMqttClient Create(string server, int? port, string userName, string password, List<string> topics)
        {
            _topicFilter = new Dictionary<string, TopicFilter>();

            foreach (var topic in topics)
            {
                TopicFilter topicFilter = new TopicFilter
                {
                    Topic = topic,
                    QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce
                };

                _topicFilter.Add(topic, topicFilter);
            }

            Task.Run(() => MqttClientRunAsync(server, port, userName, password)).Wait();

            return client;
        }

        private async Task MqttClientRunAsync(string server, int? port, string userName, string password)
        {
            try
            {
                var options = new MqttClientOptions
                {
                    ClientId = "YOURCLIENTID",
                    CleanSession = true,
                    ChannelOptions = new MqttClientTcpOptions
                    {
                        Server = server,
                        Port = port
                    },
                    Credentials = new MqttClientCredentials
                    {
                        Username = userName,
                        Password = Encoding.UTF8.GetBytes(password)
                    }
                };

                var factory = new MqttFactory();

                client = factory.CreateMqttClient();

                client.ConnectedHandler = new MqttConnectedHandler(_topicFilter, client);
                client.DisconnectedHandler = new MqttDisconnectedHandler(options, client);

                try
                {
                    await client.ConnectAsync(options);
                }
                catch //(Exception ex)
                {
                    
                }
            }
            catch //(Exception ex)
            {
                
            }
        }
    }

    public class MqttDisconnectedHandler : IMqttClientDisconnectedHandler
    {
        private IMqttClient _client;
        private MqttClientOptions _options;

        public MqttDisconnectedHandler(MqttClientOptions options, IMqttClient client)
        {
            _options = options;
            _client = client;
        }

        public async Task HandleDisconnectedAsync(MqttClientDisconnectedEventArgs eventArgs)
        {
            await Task.Delay(TimeSpan.FromSeconds(5));

            try
            {
                
            }
            catch
            {

            }
        }
    }

    public class MqttConnectedHandler : IMqttClientConnectedHandler
    {
        private IMqttClient _client;
        private Dictionary<string, TopicFilter> _topicFilter;

        public MqttConnectedHandler(Dictionary<string, TopicFilter> topicFilter, IMqttClient client)
        {
            _topicFilter = topicFilter;
            _client = client;
        }

        public async Task HandleConnectedAsync(MqttClientConnectedEventArgs eventArgs)
        {
            await _client.SubscribeAsync(_topicFilter.Values.ToArray());
        }
    }
}

Next step the platform specific implementations.

Android:

We need to create a MqttTaskService class in the Android Project.

public class MqttTaskService
    {
        private IMqttClient _mqttClient;
        private readonly string _sessionPayedTopic;

        public MqttTaskService()
        {
            _sessionPayedTopic = "YOUR TOPIC";

            _mqttClient = new MqttClientRepository().Create(
             "MqttServer",
             MqttPort IN INTEGER,
             "MqttUserName",
             "MqttPassword",
             new List<string> { _sessionPayedTopic });
            
            _mqttClient.ApplicationMessageReceivedHandler = new SubscribeCallback(_sessionPayedTopic);
        }

        public void UnSubscribe()
        {
            _mqttClient.ApplicationMessageReceivedHandler = null;
        }
    }

    public class SubscribeCallback : IMqttApplicationMessageReceivedHandler
    {
        private readonly string _sessionPayedTopic;

        public SubscribeCallback(string sessionPayedTopic)
        {
            _sessionPayedTopic = sessionPayedTopic;
        }

        public Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs e)
        {
            string message = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
            
            if (e.ApplicationMessage.Topic == _sessionPayedTopic)
            {
                
            }

            return Task.CompletedTask;
        }
    }

We need to create an instance in the Android project, maybe in the MainActivity at the end in the OnCreate function.

 MqttTaskService mqttTaskService = new MqttTaskService();

If we want to unsubscribe:

mqttTaskService.UnSubscribe(); call this

iOS

The same. We need to create a MqttTaskService class in the iOS Project.

public class MqttTaskService
    {
        private IMqttClient _mqttClient;
        private readonly string _sessionPayedTopic;

        public MqttTaskService()
        {
            _sessionPayedTopic = "YOUR TOPIC";

            _mqttClient = new MqttClientRepository().Create(
             "MqttServer",
             MqttPort IN INTEGER,
             "MqttUserName",
             "MqttPassword",
             new List<string> { _sessionPayedTopic });
            
            _mqttClient.ApplicationMessageReceivedHandler = new SubscribeCallback(_sessionPayedTopic);
        }

        public void UnSubscribe()
        {
            _mqttClient.ApplicationMessageReceivedHandler = null;
        }
    }

    public class SubscribeCallback : IMqttApplicationMessageReceivedHandler
    {
        private readonly string _sessionPayedTopic;

        public SubscribeCallback(string sessionPayedTopic)
        {
            _sessionPayedTopic = sessionPayedTopic;
        }

        public Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs e)
        {
            string message = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
            
            if (e.ApplicationMessage.Topic == _sessionPayedTopic)
            {
                
            }

            return Task.CompletedTask;
        }
    }

We need to create an instance in the iOS Project, maybe in the MainActivity at the end in the OnCreate function.

 MqttTaskService mqttTaskService = new MqttTaskService();

If we want to unsubscribe:

mqttTaskService.UnSubscribe(); call this

Okay, okay, we know if a message got, but how can we indicate to the .NET Standard Library? We have to create an event or through MessagingCenter. Use this, if you got a message in the various platform codes:

MessagingCenter.Send("SessionPayed", "SessionPayed", message);

And use this code in the .NET Standard Library, if you want to be notified, when a message got:

MessagingCenter.Subscribe<string, string>("SessionPayed", "SessionPayed", (sender, args) =>
            {
                Device.BeginInvokeOnMainThread(()=> 
                {
                    //You got a message from Mqtt, do something. 
                });
            });

Be wary, in the Subscribe section, your code will run in the background thred, so if you want to do some UI thing, you have to do in the main thread! (above)

23 thoughts on “Xamarin.Forms using Mqtt”

  1. I wish to show my gratitude for your generosity giving support to folks who absolutely need help with your question. Your very own dedication to getting the solution all around had been exceedingly insightful and have frequently helped most people like me to realize their ambitions. Your entire helpful hints and tips implies a great deal to me and far more to my fellow workers. Regards; from each one of us.

Leave a Reply

Your email address will not be published. Required fields are marked *