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>(); }
客户端:引用包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"); } }
浙公网安备 33010602011771号