基於MqttNet的二次封裝MQTT在.Net中的使用例項,附呼叫
阿新 • • 發佈:2022-03-29
最近需要處理一些協議連線和呼叫。
一開始想著是基於RabbitMq(我們本身就在用)來做Mqtt服務的轉發。
後面想著既然要用客戶端,那就順路封裝一個服務端吧,於是有了這篇文章。
先說環境
<TargetFramework>net6.0</TargetFramework> <ItemGroup> <PackageReference Include="MQTTnet" Version="3.1.2" /> </ItemGroup>
服務端呼叫示例
1 //var server = new MqttServer(s =>2 //{ 3 // s.ConnectionValidator = new MqttServerConnValidator { Port = 1884,}; 4 // //訊息回撥 5 // s.MessageReceived = s => 6 // { 7 // Console.WriteLine(s.Msg); 8 // }; 9 // //使用者連接回調 10 // s.ClientConnected = s => 11 // { 12 // Console.WriteLine(s.Msg); 13 // }; 14 // //使用者訂閱回撥15 // s.SubscribedTopic = s => 16 // { 17 // Console.WriteLine(s.Msg); 18 // }; 19 //}, true);//直接啟動
服務端程式碼
1 using MQTTnet; 2 using MQTTnet.Protocol; 3 using MQTTnet.Server; 4 using System.Text; 5 6 namespace MQTT 7 { 8 public class MqttServer 9 { 10 #regionMQTT ServerField Area 11 12 /// <summary> 13 /// Mqtt服務端 14 /// </summary> 15 private IMqttServer _mqttServer; 16 /// <summary> 17 /// MqttOptions 18 /// </summary> 19 private MqttServerOptions _options; 20 /// <summary> 21 /// Mqtt配置資訊 22 /// </summary> 23 private MqttServerConfig _mqttServerConfig; 24 25 #endregion 26 27 #region CTOR 28 29 /// <summary> 30 /// 呼叫示例 31 /// 32 /// var server = new MqttServer(s => 33 /// { 34 /// s.ConnectionValidator = new MqttServerConnValidator { Port = 1884,}; 35 /// //訊息回撥 36 /// s.MessageReceived = s => 37 /// { 38 /// Console.WriteLine(s.Msg); 39 /// }; 40 /// //使用者連接回調 41 /// s.ClientConnected = s => 42 /// { 43 /// Console.WriteLine(s.Msg); 44 /// }; 45 /// //使用者訂閱回撥 46 /// s.SubscribedTopic = s => 47 /// { 48 /// Console.WriteLine(s.Msg); 49 /// }; 50 /// }, true);//直接啟動 51 /// </summary> 52 public MqttServer() 53 { 54 Init(); 55 } 56 /// <summary> 57 /// MqttServer 58 /// 59 /// 呼叫示例 60 /// 61 /// var server = new MqttServer(s => 62 /// { 63 /// s.ConnectionValidator = new MqttServerConnValidator { Port = 1884,}; 64 /// //訊息回撥 65 /// s.MessageReceived = s => 66 /// { 67 /// Console.WriteLine(s.Msg); 68 /// }; 69 /// //使用者連接回調 70 /// s.ClientConnected = s => 71 /// { 72 /// Console.WriteLine(s.Msg); 73 /// }; 74 /// //使用者訂閱回撥 75 /// s.SubscribedTopic = s => 76 /// { 77 /// Console.WriteLine(s.Msg); 78 /// }; 79 /// }, true);//直接啟動 80 /// </summary> 81 /// <param name="mqConfig">配置回撥和引數</param> 82 /// <param name="autoStartMqtt">是否直接啟動mqtt服務</param> 83 public MqttServer(Action<MqttServerConfig> mqConfig, bool autoStartMqtt = false) 84 { 85 _mqttServerConfig = new MqttServerConfig(); 86 mqConfig(_mqttServerConfig); 87 Init(); 88 if (autoStartMqtt) 89 { 90 Start().Wait(); 91 } 92 } 93 94 #endregion 95 96 /// <summary> 97 /// 獲取例項 98 /// </summary> 99 /// <param name="mqConfig">MQTT配置</param> 100 /// <param name="autoStartMqtt">是否直接啟動</param> 101 /// <returns></returns> 102 public static MqttServer Instance(Action<MqttServerConfig> mqConfig, bool autoStartMqtt = false) 103 { 104 return new MqttServer(mqConfig, autoStartMqtt); 105 } 106 107 /// <summary> 108 /// 初始化MQTT 109 /// </summary> 110 private void Init() 111 { 112 try 113 { 114 #region Validator 115 116 if (_mqttServerConfig.ConnectionValidator != null) 117 { 118 //驗證客戶端資訊比如客戶Id、使用者名稱、密碼 119 _options = new MqttServerOptions 120 { 121 //連線驗證 122 ConnectionValidator = new MqttServerConnectionValidatorDelegate(p => 123 { 124 if (_mqttServerConfig.ConnectionValidator.ClientIds != null && 125 _mqttServerConfig.ConnectionValidator.ClientIds.Count > 0) 126 { 127 if (_mqttServerConfig.ConnectionValidator.ClientIds.First(s => s.Equals(p.ClientId)) is null) 128 { 129 p.ReasonCode = MqttConnectReasonCode.ClientIdentifierNotValid; 130 } 131 } 132 133 if (_mqttServerConfig.ConnectionValidator.Usernames != null && 134 _mqttServerConfig.ConnectionValidator.Passwords != null && 135 _mqttServerConfig.ConnectionValidator.Usernames.Count > 0 && 136 _mqttServerConfig.ConnectionValidator.Passwords.Count > 0) 137 { 138 if (_mqttServerConfig.ConnectionValidator.Usernames.First(s => s.Equals(p.Username)) is null || 139 _mqttServerConfig.ConnectionValidator.Usernames.First(s => s.Equals(p.Username)) is null) 140 { 141 p.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword; 142 } 143 } 144 145 }), 146 }; 147 if (_mqttServerConfig.ConnectionValidator.Port > 0) 148 { 149 //驗證客戶端埠和伺服器埠是否一致(不一致則不能連線到伺服器成功) 150 _options.DefaultEndpointOptions.Port = _mqttServerConfig.ConnectionValidator.Port; 151 } 152 } 153 else 154 { 155 _options = new MqttServerOptions(); 156 } 157 158 #endregion 159 160 #region Event Binding 161 162 //建立Mqtt伺服器 163 _mqttServer = new MqttFactory().CreateMqttServer(); 164 165 //開啟訂閱事件 166 _mqttServer.ClientSubscribedTopicHandler = new MqttServerClientSubscribedTopicHandlerDelegate(MqttNetServer_SubscribedTopic); 167 168 //取消訂閱事件 169 _mqttServer.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(MqttNetServer_UnSubscribedTopic); 170 171 //客戶端訊息事件 172 _mqttServer.UseApplicationMessageReceivedHandler(MqttServe_ApplicationMessageReceived); 173 174 //客戶端連線事件 175 _mqttServer.UseClientConnectedHandler(MqttNetServer_ClientConnected); 176 177 //客戶端斷開事件 178 _mqttServer.UseClientDisconnectedHandler(MqttNetServer_ClientDisConnected); 179 180 #endregion 181 182 } 183 catch (Exception e) 184 { 185 if (_mqttServerConfig.ExceptionCallBack is null) 186 { 187 throw e; 188 } 189 _mqttServerConfig.ExceptionCallBack(e); 190 } 191 192 } 193 194 /// <summary> 195 /// //啟動伺服器 196 /// </summary> 197 /// <returns></returns> 198 public async Task Start() 199 => await _mqttServer.StartAsync(_options); 200 201 /// <summary> 202 /// 停止服務 203 /// </summary> 204 /// <returns></returns> 205 public async Task Stop() 206 => await _mqttServer.StopAsync(); 207 208 #region 內部事件轉換處理 209 210 /// <summary> 211 /// //客戶訂閱 212 /// </summary> 213 /// <param name="e"></param> 214 private void MqttNetServer_SubscribedTopic(MqttServerClientSubscribedTopicEventArgs e) 215 { 216 if (_mqttServerConfig.SubscribedTopic != null) 217 { 218 _mqttServerConfig.SubscribedTopic(new MqttServerRecive 219 { 220 ClientId = e.ClientId,//客戶端Id 221 Topic = e.TopicFilter.Topic, 222 Msg = $"客戶端[{ e.ClientId}]已訂閱主題:{e.TopicFilter.Topic}" 223 }); 224 } 225 } 226 227 /// <summary> 228 /// //客戶取消訂閱 229 /// </summary> 230 /// <param name="e"></param> 231 private void MqttNetServer_UnSubscribedTopic(MqttServerClientUnsubscribedTopicEventArgs e) 232 { 233 if (_mqttServerConfig.UnSubscribedTopic != null) 234 { 235 _mqttServerConfig.UnSubscribedTopic(new MqttServerRecive 236 { 237 ClientId = e.ClientId,//客戶端Id 238 Topic = e.TopicFilter, 239 Msg = $"客戶端[{ e.ClientId}]已取消訂閱主題:{e.TopicFilter}" 240 }); 241 } 242 } 243 244 /// <summary> 245 /// //接收訊息 246 /// </summary> 247 /// <param name="e"></param> 248 private void MqttServe_ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs e) 249 { 250 var Payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload); 251 var Retain = e.ApplicationMessage.Retain; 252 if (_mqttServerConfig.MessageReceived != null) 253 { 254 _mqttServerConfig.MessageReceived(new MqttServerRecive 255 { 256 ClientId = e.ClientId,//客戶端Id 257 Topic = e.ApplicationMessage.Topic, 258 Payload = Payload, 259 Qos = e.ApplicationMessage.QualityOfServiceLevel, 260 Retain = e.ApplicationMessage.Retain, 261 Msg = $"客戶端[{e.ClientId}]>> 主題:[{e.ApplicationMessage.Topic}] " + 262 $"負載:[{Payload}] Qos:[{e.ApplicationMessage.QualityOfServiceLevel}] " + 263 $"保留:[{e.ApplicationMessage.Retain}]" 264 }); 265 } 266 } 267 268 /// <summary> 269 /// //客戶連線 270 /// </summary> 271 /// <param name="e"></param> 272 private void MqttNetServer_ClientConnected(MqttServerClientConnectedEventArgs e) 273 { 274 if (_mqttServerConfig.ClientConnected != null) 275 { 276 _mqttServerConfig.ClientConnected(new MqttServerRecive 277 { 278 ClientId = e.ClientId,//客戶端Id 279 Msg = $"客戶端[{ e.ClientId}]已連線" 280 }); 281 } 282 } 283 284 /// <summary> 285 /// //客戶連線斷開 286 /// </summary> 287 /// <param name="e"></param> 288 private void MqttNetServer_ClientDisConnected(MqttServerClientDisconnectedEventArgs e) 289 { 290 if (_mqttServerConfig.ClientDisConnected != null) 291 { 292 _mqttServerConfig.ClientDisConnected(new MqttServerRecive 293 { 294 ClientId = e.ClientId,//客戶端Id 295 Msg = $"客戶端[{ e.ClientId}]已斷開連線" 296 }); 297 } 298 } 299 300 #endregion 301 } 302 303 public class MqttServerConfig 304 { 305 /// <summary> 306 /// Mqtt驗證 307 /// </summary> 308 public MqttServerConnValidator ConnectionValidator = null; 309 /// <summary> 310 /// 客戶訂閱資訊提醒 311 /// </summary> 312 public Action<MqttServerRecive> SubscribedTopic = null; 313 /// <summary> 314 /// 客戶取消訂閱提醒 315 /// </summary> 316 public Action<MqttServerRecive> UnSubscribedTopic = null; 317 /// <summary> 318 /// 接收訊息 319 /// </summary> 320 public Action<MqttServerRecive> MessageReceived = null; 321 /// <summary> 322 /// 客戶連線提醒 323 /// </summary> 324 public Action<MqttServerRecive> ClientConnected = null; 325 /// <summary> 326 /// 客戶連線斷開提醒 327 /// </summary> 328 public Action<MqttServerRecive> ClientDisConnected = null; 329 /// <summary> 330 /// 異常資訊回撥(建議設定) 331 /// </summary> 332 public Action<Exception> ExceptionCallBack = null; 333 } 334 335 public class MqttServerConnValidator 336 { 337 /// <summary> 338 /// Connecte Client Id 339 /// </summary> 340 public IList<string> ClientIds { get; set; } 341 342 /// <summary> 343 /// Verify Username 344 /// </summary> 345 public IList<string> Usernames { get; set; } 346 347 /// <summary> 348 /// Verify Password 349 /// </summary> 350 public IList<string> Passwords { get; set; } 351 352 /// <summary> 353 /// Verify Port 354 /// </summary> 355 public int Port { get; set; } 356 } 357 358 public class MqttServerRecive 359 { 360 /// <summary> 361 /// 客戶端ID 362 /// </summary> 363 public string ClientId { get; set; } 364 /// <summary> 365 /// 主題 366 /// </summary> 367 public string Topic { get; set; } 368 /// <summary> 369 /// 負載/訊息 370 /// </summary> 371 public string Payload { get; set; } 372 /// <summary> 373 /// Qos 374 /// </summary> 375 public MqttQualityOfServiceLevel Qos { get; set; } 376 /// <summary> 377 /// 保留 378 /// </summary> 379 public bool Retain { get; set; } 380 /// <summary> 381 /// 訊息內容 382 /// </summary> 383 public string Msg { get; set; } 384 } 385 }
客戶端呼叫示例
1 //var client = new MqttClient(s => 2 //{ 3 // s.Port = 1883; 4 // s.ServerIp = "127.0.0.1"; 5 // s.UserName = "mqtt-test"; 6 // s.Password = "mqtt-test"; 7 // s.ReciveMsgCallback = s => 8 // { 9 // Console.WriteLine(s.Payload_UTF8); 10 // }; 11 //}, true); 12 //client.Subscribe("/iot/");
客戶端程式碼
1 using MQTTnet; 2 using MQTTnet.Client; 3 using MQTTnet.Client.Disconnecting; 4 using MQTTnet.Client.Options; 5 using MQTTnet.Protocol; 6 using System.Text; 7 8 namespace MQTT 9 { 10 public class MqttClient 11 { 12 #region Field Area 13 14 /// <summary> 15 /// Mqtt factory 16 /// </summary> 17 private MqttFactory _factory; 18 /// <summary> 19 /// Mqtt client 20 /// </summary> 21 private IMqttClient _mqttClient; 22 /// <summary> 23 /// Mqtt 配置資訊 24 /// </summary> 25 private MqttClientConfig _mqttClientConfig; 26 /// <summary> 27 /// Mqtt options 28 /// </summary> 29 private IMqttClientOptions _options; 30 31 #endregion 32 33 #region CTOR 34 35 /// <summary> 36 /// 預設啟動IP為127.0.0.1 埠為1883 37 /// </summary> 38 public MqttClient() 39 { 40 _mqttClientConfig = new MqttClientConfig 41 { 42 ServerIp = "127.0.0.1", 43 Port = 1883 44 }; 45 Init(); 46 } 47 /// <summary> 48 /// 呼叫示例 49 /// 50 /// //var client = new MqttClient(s => 51 /// { 52 /// s.Port = 1883; 53 /// s.ServerIp = "127.0.0.1"; 54 /// s.UserName = "mqtt-test"; 55 /// s.Password = "mqtt-test"; 56 /// s.ReciveMsgCallback = s => 57 /// { 58 /// Console.WriteLine(s.Payload_UTF8); 59 /// }; 60 /// }, true); 61 /// client.Subscribe("/TopicName/"); 62 /// </summary> 63 /// <param name="config">客戶端配置資訊</param> 64 /// <param name="autoStart">直接啟動</param> 65 public MqttClient(Action<MqttClientConfig> config, bool autoStart = false) 66 { 67 _mqttClientConfig = new MqttClientConfig(); 68 config(_mqttClientConfig); 69 Init(); 70 if (autoStart) 71 { 72 Start(); 73 } 74 } 75 76 #endregion 77 78 /// <summary> 79 /// 獲取MqttClient例項 80 /// 81 /// 呼叫示例 82 /// //var client = MqttClient.Instance(s => 83 /// { 84 /// s.Port = 1883; 85 /// s.ServerIp = "127.0.0.1"; 86 /// s.UserName = "mqtt-test"; 87 /// s.Password = "mqtt-test"; 88 /// s.ReciveMsgCallback = s => 89 /// { 90 /// Console.WriteLine(s.Payload_UTF8); 91 /// }; 92 /// }, true); 93 /// client.Subscribe("/TopicName/"); 94 /// </summary> 95 /// <param name="config">客戶端配置資訊</param> 96 /// <param name="autoStart">直接啟動</param> 97 /// <returns></returns> 98 public static MqttClient Instance(Action<MqttClientConfig> config, bool autoStart = false) 99 => new MqttClient(config, autoStart); 100 101 /// <summary> 102 /// 初始化註冊 103 /// </summary> 104 private void Init() 105 { 106 try 107 { 108 _factory = new MqttFactory(); 109 110 _mqttClient = _factory.CreateMqttClient(); 111 112 _options = new MqttClientOptionsBuilder() 113 .WithTcpServer(_mqttClientConfig.ServerIp, _mqttClientConfig.Port) 114 .WithCredentials(_mqttClientConfig.UserName, _mqttClientConfig.Password) 115 .WithClientId(_mqttClientConfig.ClientId) 116 .Build(); 117 118 //訊息回撥 119 _mqttClient.UseApplicationMessageReceivedHandler(ReciveMsg); 120 } 121 catch (Exception exp) 122 { 123 if (_mqttClientConfig.Exception is null) 124 { 125 throw exp; 126 } 127 _mqttClientConfig.Exception(exp); 128 } 129 } 130 131 #region 內部事件轉換處理 132 133 /// <summary> 134 /// 訊息接收回調 135 /// </summary> 136 /// <param name="e"></param> 137 /// <returns></returns> 138 private void ReciveMsg(MqttApplicationMessageReceivedEventArgs e) 139 { 140 if (_mqttClientConfig.ReciveMsgCallback != null) 141 { 142 _mqttClientConfig.ReciveMsgCallback(new MqttClientReciveMsg 143 { 144 Topic = e.ApplicationMessage.Topic, 145 Payload_UTF8 = Encoding.UTF8.GetString(e.ApplicationMessage.Payload), 146 Payload = e.ApplicationMessage.Payload, 147 Qos = e.ApplicationMessage.QualityOfServiceLevel, 148 Retain = e.ApplicationMessage.Retain, 149 }); 150 } 151 } 152 153 /// <summary> 154 /// 訂閱 155 /// </summary> 156 /// <param name="topicName"></param> 157 public async void Subscribe(string topicName) 158 { 159 topicName = topicName.Trim(); 160 if (string.IsNullOrEmpty(topicName)) 161 { 162 throw new Exception("訂閱主題不能為空!"); 163 } 164 165 if (!_mqttClient.IsConnected) 166 { 167 throw new Exception("MQTT客戶端尚未連線!請先啟動連線"); 168 } 169 await _mqttClient.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topicName).Build()); 170 } 171 172 /// <summary> 173 /// 取消訂閱 174 /// </summary> 175 /// <param name="topicName"></param> 176 public async void Unsubscribe(string topicName) 177 { 178 topicName = topicName.Trim(); 179 if (string.IsNullOrEmpty(topicName)) 180 { 181 throw new Exception("訂閱主題不能為空!"); 182 } 183 184 if (!_mqttClient.IsConnected) 185 { 186 throw new Exception("MQTT客戶端尚未連線!請先啟動連線"); 187 } 188 await _mqttClient.UnsubscribeAsync(topicName); 189 } 190 191 /// <summary> 192 /// 重連機制 193 /// </summary> 194 private void ReConnected() 195 { 196 if (_mqttClient.IsConnected) 197 { 198 return; 199 } 200 for (int i = 0; i < 10; i++) 201 { 202 //重連機制 203 _mqttClient.UseDisconnectedHandler(async e => 204 { 205 try 206 { 207 await Task.Delay(TimeSpan.FromSeconds(_mqttClientConfig.ReconneTime)); 208 await _mqttClient.ConnectAsync(_options); 209 return; 210 } 211 catch (Exception exp) 212 { 213 if (_mqttClientConfig.Exception is null) 214 { 215 throw exp; 216 } 217 _mqttClientConfig.Exception(exp); 218 } 219 }); 220 } 221 } 222 223 #endregion 224 225 #region 訊息傳送 226 227 /// <summary> 228 /// 傳送訊息,含有重連機制,如掉線會自動重連 229 /// </summary> 230 /// <param name="message"></param> 231 private async Task PublishAsync(string topicName, MqttApplicationMessageBuilder MessageBuilder, PublicQos qos = 0) 232 { 233 string topic = topicName.Trim(); 234 if (string.IsNullOrEmpty(topic)) 235 { 236 throw new Exception("主題不能為空!"); 237 } 238 ReConnected(); 239 240 MessageBuilder.WithTopic(topic).WithRetainFlag(); 241 if (qos == PublicQos.Qos_0) 242 { 243 MessageBuilder.WithAtLeastOnceQoS(); 244 } 245 else if (qos == PublicQos.Qos_1) 246 { 247 MessageBuilder.WithAtMostOnceQoS(); 248 } 249 else 250 { 251 MessageBuilder.WithExactlyOnceQoS(); 252 } 253 var Message = MessageBuilder.Build(); 254 try 255 { 256 await _mqttClient.PublishAsync(Message); 257 } 258 catch (Exception e) 259 { 260 if (_mqttClientConfig.Exception is null) 261 { 262 throw e; 263 } 264 _mqttClientConfig.Exception(e); 265 } 266 267 } 268 269 /// <summary> 270 /// 傳送訊息,含有重連機制,如掉線會自動重連 271 /// </summary> 272 /// <param name="message">文字訊息</param> 273 public async Task Publish(string topicName, string message, PublicQos qos = 0) 274 { 275 await PublishAsync(topicName, new MqttApplicationMessageBuilder() 276 .WithPayload(message), qos); 277 } 278 /// <summary> 279 /// 傳送訊息,含有重連機制,如掉線會自動重連 280 /// </summary> 281 /// <param name="message">訊息流</param> 282 public async void Publish(string topicName, Stream message, PublicQos qos = 0) 283 => await PublishAsync(topicName, new MqttApplicationMessageBuilder() 284 .WithPayload(message), qos); 285 286 /// <summary> 287 /// 傳送訊息,含有重連機制,如掉線會自動重連 288 /// </summary> 289 /// <param name="message">Byte訊息</param> 290 public async void Publish(string topicName, IEnumerable<byte> message, PublicQos qos = 0) 291 => await PublishAsync(topicName, new MqttApplicationMessageBuilder() 292 .WithPayload(message), qos); 293 294 /// <summary> 295 /// 傳送訊息,含有重連機制,如掉線會自動重連 296 /// </summary> 297 /// <param name="message">Byte訊息</param> 298 public async void Publish(string topicName, byte[] message, PublicQos qos = 0) 299 => await PublishAsync(topicName, new MqttApplicationMessageBuilder() 300 .WithPayload(message), qos); 301 302 #endregion 303 304 /// <summary> 305 /// 啟動服務 306 /// </summary> 307 /// <returns></returns> 308 public async Task Start() 309 => await _mqttClient.ConnectAsync(_options); 310 311 /// <summary> 312 /// 停止服務 313 /// </summary> 314 /// <returns></returns> 315 public async Task Stop() 316 => await _mqttClient.DisconnectAsync(new MqttClientDisconnectOptions { ReasonCode = MqttClientDisconnectReason.NormalDisconnection}, CancellationToken.None); 317 318 } 319 public class MqttClientConfig 320 { 321 private string _serverIp; 322 /// <summary> 323 /// 伺服器IP 324 /// </summary> 325 public string ServerIp 326 { 327 get => _serverIp; 328 set 329 { 330 if (string.IsNullOrEmpty(value.Trim())) 331 { 332 throw new ArgumentException("ServerIp can't be null or empty!"); 333 } 334 _serverIp = value; 335 } 336 } 337 private int _port; 338 /// <summary> 339 /// 伺服器埠 340 /// </summary> 341 public int Port 342 { 343 get => _port; 344 set 345 { 346 if (value <= 0) 347 { 348 throw new ArgumentException("Port can't below the zero!"); 349 } 350 _port = value; 351 } 352 } 353 354 /// <summary> 355 /// 使用者名稱 356 /// </summary> 357 public string UserName { get; set; } 358 /// <summary> 359 /// 密碼 360 /// </summary> 361 public string Password { get; set; } 362 363 private string _clientId; 364 /// <summary> 365 /// 唯一使用者ID,預設使用Guid 366 /// </summary> 367 public string ClientId 368 { 369 get 370 { 371 _clientId = _clientId ?? Guid.NewGuid().ToString(); 372 return _clientId; 373 } 374 set => _clientId = value; 375 } 376 /// <summary> 377 /// 客戶端掉線重連時間,單位/s,預設5s 378 /// </summary> 379 public double ReconneTime { get; set; } = 5; 380 /// <summary> 381 /// 異常回調,預設為空,為空拋異常 382 /// </summary> 383 public Action<Exception> Exception = null; 384 385 /// <summary> 386 /// 接收訊息回撥,預設不接收 387 /// </summary> 388 public Action<MqttClientReciveMsg> ReciveMsgCallback = null; 389 } 390 public class MqttClientReciveMsg 391 { 392 /// <summary> 393 /// 主題 394 /// </summary> 395 public string Topic { get; set; } 396 /// <summary> 397 /// UTF-8格式下的 負載/訊息 398 /// </summary> 399 public string Payload_UTF8 { get; set; } 400 /// <summary> 401 /// 原始 負載/訊息 402 /// </summary> 403 public byte[] Payload { get; set; } 404 /// <summary> 405 /// Qos 406 /// </summary> 407 public MqttQualityOfServiceLevel Qos { get; set; } 408 /// <summary> 409 /// 保留 410 /// </summary> 411 public bool Retain { get; set; } 412 } 413 public enum PublicQos 414 { 415 /// <summary> 416 /// //At most once,至多一次 417 /// </summary> 418 Qos_0, 419 /// <summary> 420 /// //At least once,至少一次 421 /// </summary> 422 Qos_1, 423 /// <summary> 424 /// //QoS2,Exactly once 425 /// </summary> 426 Qos_2, 427 } 428 }MQTT Client
所有的支援類都在裡面,隨用隨跑。