MQTT协议

 

 数据上云,中转站

不管是不同局域网的移动端,还是设备,还是上位机,webapi都可以上云

区别http请求响应模式

谁订阅、发布给谁,相当于委托

5G网络做手术,大概率也是MQTT协议

 

MQTT更简单,OPCUA大一些,没有可比性,不冲突,解决的不一样

不一定是云端,也可以是本地服务器

协议:规定了数据字节的格式,使用时需要进一步实现这个过程,协议应用广泛--现有的通讯库,第三方库--实现的完整度更高

 

 

服务端,引用包MQTTnet   

    public partial class MainWindow : Window
    {
        private IMqttServer server;
        List<TopicItem> Topics = new List<TopicItem>();

        public MainWindow()
        {
            InitializeComponent();


            server = new MqttFactory().CreateMqttServer();
            server.ApplicationMessageReceivedHandler =
                new MqttApplicationMessageReceivedHandlerDelegate(new Action<MqttApplicationMessageReceivedEventArgs>(Server_ApplicationMessageReceived));//绑定消息接收事件
            server.ClientConnectedHandler =
                new MqttServerClientConnectedHandlerDelegate(new Action<MqttServerClientConnectedEventArgs>(Server_ClientConnected));//绑定客户端连接事件
            server.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(new Action<MqttServerClientDisconnectedEventArgs>(Server_ClientDisconnected));//绑定客户端断开事件
            server.ClientSubscribedTopicHandler = new MqttServerClientSubscribedHandlerDelegate(new Action<MqttServerClientSubscribedTopicEventArgs>(Server_ClientSubscribedTopic));//绑定客户端订阅主题事件
            server.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(new Action<MqttServerClientUnsubscribedTopicEventArgs>(Server_ClientUnsubscribedTopic));//绑定客户端退订主题事件
            server.StartedHandler = new MqttServerStartedHandlerDelegate(new Action<EventArgs>(Server_Started));//绑定服务端启动事件
            server.StoppedHandler = new MqttServerStoppedHandlerDelegate(new Action<EventArgs>(Server_Stopped));//绑定服务端停止事件
        }

        [Obsolete]
        private async void btnStart_Click(object sender, RoutedEventArgs e)
        {
            var optionBuilder = new MqttServerOptionsBuilder()
                .WithDefaultEndpointBoundIPAddress(System.Net.IPAddress.Parse(this.tbHostAddr.Text))
                .WithDefaultEndpointPort(int.Parse(this.tbHostPort.Text))
                .WithDefaultCommunicationTimeout(TimeSpan.FromMilliseconds(5000))
                .WithConnectionValidator(t =>
                {
                    string un = "", pwd = "";
                    this.Dispatcher.Invoke(() =>
                    {
                        un = this.tbUsername.Text;
                        pwd = this.tbPassword.Text;
                    });
                    if (t.Username != un || t.Password != pwd)
                    {
                        t.ReturnCode = MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
                    }
                    else
                        t.ReturnCode = MqttConnectReturnCode.ConnectionAccepted;
                });
            var option = optionBuilder.Build();

            //启动
            await server.StartAsync(option);
        }

        private async void btnStop_Click(object sender, RoutedEventArgs e)
        {
            if (server != null)
            {
                await server.StopAsync();
            }
        }


        private void Server_ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs e)
        {
            if (e.ApplicationMessage.Topic == "/environ/temp")
            {
                string str = System.Text.Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
                double tmp;
                bool isdouble = double.TryParse(str, out tmp);
                if (isdouble)
                {
                    string result = "";
                    if (tmp > 40)
                    {
                        result = "温度过高!";
                    }
                    else if (tmp < 10)
                    {
                        result = "温度过低!";
                    }
                    else
                    {
                        result = "温度正常!";
                    }
                    MqttApplicationMessage message = new MqttApplicationMessage()
                    {
                        Topic = e.ApplicationMessage.Topic,
                        Payload = Encoding.UTF8.GetBytes(result),
                        QualityOfServiceLevel = e.ApplicationMessage.QualityOfServiceLevel,
                        Retain = e.ApplicationMessage.Retain
                    };
                    server.PublishAsync(message);
                }
            }
            WriteLog(">>> 收到消息" + e.ApplicationMessage.ConvertPayloadToString() + ",来自客户端" + e.ClientId + ",主题为" + e.ApplicationMessage.Topic);
        }
        private void Server_ClientConnected(MqttServerClientConnectedEventArgs e)
        {
            this.Dispatcher.Invoke(() =>
            {
                lbClients.Items.Add(e.ClientId);
            });
            WriteLog(">>> 客户端" + e.ClientId + "连接");
        }
        private void Server_ClientDisconnected(MqttServerClientDisconnectedEventArgs e)
        {
            this.Dispatcher.Invoke(() =>
            {
                lbClients.Items.Remove(e.ClientId);
            });


            WriteLog(">>> 客户端" + e.ClientId + "断开");
        }
        private void Server_ClientSubscribedTopic(MqttServerClientSubscribedTopicEventArgs e)
        {
            this.Dispatcher.Invoke(() =>
            {
                var topic = Topics.FirstOrDefault(t => t.Topic == e.TopicFilter.Topic);
                if (topic == null)
                {
                    topic = new TopicItem { Topic = e.TopicFilter.Topic, Count = 0 };
                    Topics.Add(topic);
                }
                if (!topic.Clients.Exists(c => c == e.ClientId))
                {
                    topic.Clients.Add(e.ClientId);
                    topic.Count++;
                }

                this.lvTopic.Items.Clear();
                foreach (var item in this.Topics)
                {
                    this.lvTopic.Items.Add($"{item.Topic}:{item.Count}");
                }
            });

            WriteLog(">>> 客户端" + e.ClientId + "订阅主题" + e.TopicFilter.Topic);
        }

        private void Server_ClientUnsubscribedTopic(MqttServerClientUnsubscribedTopicEventArgs e)
        {
            this.Dispatcher.Invoke(() =>
            {
                var topic = Topics.FirstOrDefault(t => t.Topic == e.TopicFilter);
                if (topic != null)
                {
                    topic.Count--;
                    topic.Clients.Remove(e.ClientId);
                }

                this.lvTopic.Items.Clear();
                foreach (var item in this.Topics)
                {
                    this.lvTopic.Items.Add($"{item.Topic}:{item.Count}");
                }
            });
            WriteLog(">>> 客户端" + e.ClientId + "退订主题" + e.TopicFilter);
        }

        private void Server_Started(EventArgs e)
        {
            WriteLog(">>> 服务端已启动!");
        }
        private void Server_Stopped(EventArgs e)
        {
            WriteLog(">>> 服务端已停止!");
        }


        public void WriteLog(string message)
        {
            if (!(txtRich.CheckAccess()))
            {
                this.Dispatcher.Invoke(() =>
                    WriteLog(message)
                    );
                return;
            }
            string strTime = "[" + System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] ";
            txtRich.AppendText(strTime + message + "\r");

        }

        private void miClear_Click(object sender, RoutedEventArgs e)
        {
            txtRich.Document.Blocks.Clear();
        }
    }

    public class TopicItem
    {
        public string Topic { get; set; }
        public int Count { get; set; }
        public List<string> Clients { get; set; } = new List<string>();
    }
View Code

 

 客户端:引用包MQTTnet.Extensions.ManagedClient

    public partial class MainWindow : Window
    {
        private IManagedMqttClient mqttClient;

        public MainWindow()
        {
            InitializeComponent();

            var factory = new MqttFactory();
            mqttClient = factory.CreateManagedMqttClient();

            mqttClient.UseDisconnectedHandler(ee =>
            {
                WriteLog(">>> 服务器断开连接");
            });
            mqttClient.UseApplicationMessageReceivedHandler(ee =>
            {
                WriteLog(">>> 收到消息");
                WriteLog($"+ Topic = {ee.ApplicationMessage.Topic}");
                try
                {
                    WriteLog($"+ Payload = {Encoding.UTF8.GetString(ee.ApplicationMessage.Payload)}");
                }
                catch { }
                WriteLog($"+ QoS = {ee.ApplicationMessage.QualityOfServiceLevel}");
                WriteLog($"+ Retain = {ee.ApplicationMessage.Retain}");
                WriteLog("");
            });

            mqttClient.UseConnectedHandler(ee =>
            {
                WriteLog(">>> 连接到服务");
            });
        }

        private async void btnStart_Click(object sender, RoutedEventArgs e)
        {
            var mqttClientOptions = new MqttClientOptionsBuilder()
                             .WithClientId(this.tbClientId.Text)
                             .WithTcpServer(this.tbHostAddr.Text, int.Parse(this.tbHostPort.Text))
                             .WithCredentials(this.tbUsername.Text, this.tbPassword.Text);

            var options = new ManagedMqttClientOptionsBuilder()
                        .WithAutoReconnectDelay(TimeSpan.FromSeconds(5))
                        .WithClientOptions(mqttClientOptions.Build())
                        .Build();

            await mqttClient.StartAsync(options);
        }

        private async void btnStop_Click(object sender, RoutedEventArgs e)
        {
            if (mqttClient != null)
            {
                if (mqttClient.IsStarted)
                    await mqttClient.StopAsync();
                mqttClient.Dispose();
            }
        }

        [Obsolete]
        private async void btnSubscribe_Click(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(this.tbTopic.Text))
            {
                WriteLog(">>> 请输入Topic");
                return;
            }

            await mqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic(this.tbTopic.Text).Build());

            WriteLog($">>> 订阅 {this.tbTopic.Text}");
        }

        private async void btnPublish_Click(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(this.tbPubTopic.Text))
            {
                WriteLog(">>> 请输入Topic");
                return;
            }
            var result = await mqttClient.PublishAsync(
                this.tbPubTopic.Text,
                this.tbContent.Text,
                MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce);
            WriteLog($">>> topic:{this.tbPubTopic.Text} payload:{this.tbContent.Text} {result.ReasonCode}");
        }




        public void WriteLog(string message)
        {
            if (!(txtRich.CheckAccess()))
            {
                this.Dispatcher.Invoke(() =>
                    WriteLog(message)
                    );
                return;
            }
            string strTime = "[" + System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] ";
            txtRich.AppendText(strTime + message + "\r");

        }
    }
View Code

 

posted on 2025-02-28 11:45  张彦山  阅读(38)  评论(0)    收藏  举报