25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MainPage.xaml.cs 24 KiB

6 년 전
7 년 전
6 년 전
6 년 전
6 년 전
6 년 전
6 년 전
6 년 전
7 년 전
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.ObjectModel;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Windows.Security.Cryptography.Certificates;
  7. using Windows.UI.Core;
  8. using Windows.UI.Xaml;
  9. using MQTTnet.Client;
  10. using MQTTnet.Client.Connecting;
  11. using MQTTnet.Client.Disconnecting;
  12. using MQTTnet.Client.Options;
  13. using MQTTnet.Client.Receiving;
  14. using MQTTnet.Diagnostics;
  15. using MQTTnet.Exceptions;
  16. using MQTTnet.Extensions.ManagedClient;
  17. using MQTTnet.Extensions.Rpc;
  18. using MQTTnet.Formatter;
  19. using MQTTnet.Implementations;
  20. using MQTTnet.Protocol;
  21. using MQTTnet.Server;
  22. using MQTTnet.Server.Status;
  23. using MqttClientConnectedEventArgs = MQTTnet.Client.Connecting.MqttClientConnectedEventArgs;
  24. using MqttClientDisconnectedEventArgs = MQTTnet.Client.Disconnecting.MqttClientDisconnectedEventArgs;
  25. namespace MQTTnet.TestApp.UniversalWindows
  26. {
  27. public sealed partial class MainPage
  28. {
  29. private readonly ConcurrentQueue<MqttNetLogMessage> _traceMessages = new ConcurrentQueue<MqttNetLogMessage>();
  30. private readonly ObservableCollection<IMqttClientStatus> _sessions = new ObservableCollection<IMqttClientStatus>();
  31. private IMqttClient _mqttClient;
  32. private IManagedMqttClient _managedMqttClient;
  33. private IMqttServer _mqttServer;
  34. public MainPage()
  35. {
  36. InitializeComponent();
  37. ClientId.Text = Guid.NewGuid().ToString("D");
  38. MqttNetGlobalLogger.LogMessagePublished += OnTraceMessagePublished;
  39. }
  40. private async void OnTraceMessagePublished(object sender, MqttNetLogMessagePublishedEventArgs e)
  41. {
  42. _traceMessages.Enqueue(e.TraceMessage);
  43. await UpdateLogAsync();
  44. }
  45. private async Task UpdateLogAsync()
  46. {
  47. while (_traceMessages.Count > 100)
  48. {
  49. _traceMessages.TryDequeue(out _);
  50. }
  51. var logText = new StringBuilder();
  52. foreach (var traceMessage in _traceMessages)
  53. {
  54. logText.AppendFormat(
  55. "[{0:yyyy-MM-dd HH:mm:ss.fff}] [{1}] [{2}] [{3}] [{4}]{5}",
  56. traceMessage.Timestamp,
  57. traceMessage.Level,
  58. traceMessage.Source,
  59. traceMessage.ThreadId,
  60. traceMessage.Message,
  61. Environment.NewLine);
  62. if (traceMessage.Exception != null)
  63. {
  64. logText.AppendLine(traceMessage.Exception.ToString());
  65. }
  66. }
  67. await Trace.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
  68. {
  69. Trace.Text = logText.ToString();
  70. });
  71. }
  72. private async void Connect(object sender, RoutedEventArgs e)
  73. {
  74. var tlsOptions = new MqttClientTlsOptions
  75. {
  76. UseTls = UseTls.IsChecked == true,
  77. IgnoreCertificateChainErrors = true,
  78. IgnoreCertificateRevocationErrors = true,
  79. AllowUntrustedCertificates = true
  80. };
  81. var options = new MqttClientOptions
  82. {
  83. ClientId = ClientId.Text,
  84. ProtocolVersion = MqttProtocolVersion.V500
  85. };
  86. if (UseTcp.IsChecked == true)
  87. {
  88. options.ChannelOptions = new MqttClientTcpOptions
  89. {
  90. Server = Server.Text,
  91. Port = int.Parse(Port.Text),
  92. TlsOptions = tlsOptions
  93. };
  94. }
  95. if (UseWs.IsChecked == true)
  96. {
  97. options.ChannelOptions = new MqttClientWebSocketOptions
  98. {
  99. Uri = Server.Text,
  100. TlsOptions = tlsOptions
  101. };
  102. }
  103. if (options.ChannelOptions == null)
  104. {
  105. throw new InvalidOperationException();
  106. }
  107. options.Credentials = new MqttClientCredentials
  108. {
  109. Username = User.Text,
  110. Password = Password.Text
  111. };
  112. options.CleanSession = CleanSession.IsChecked == true;
  113. options.KeepAlivePeriod = TimeSpan.FromSeconds(double.Parse(KeepAliveInterval.Text));
  114. if (UseMqtt310.IsChecked == true)
  115. {
  116. options.ProtocolVersion = MqttProtocolVersion.V310;
  117. }
  118. else if (UseMqtt311.IsChecked == true)
  119. {
  120. options.ProtocolVersion = MqttProtocolVersion.V311;
  121. }
  122. else if (UseMqtt500.IsChecked == true)
  123. {
  124. options.ProtocolVersion = MqttProtocolVersion.V500;
  125. }
  126. try
  127. {
  128. if (_mqttClient != null)
  129. {
  130. await _mqttClient.DisconnectAsync();
  131. _mqttClient.UseApplicationMessageReceivedHandler(HandleReceivedApplicationMessage);
  132. _mqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(x => OnConnected(x));
  133. _mqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(x => OnDisconnected(x));
  134. }
  135. var factory = new MqttFactory();
  136. if (UseManagedClient.IsChecked == true)
  137. {
  138. _managedMqttClient = factory.CreateManagedMqttClient();
  139. _managedMqttClient.UseApplicationMessageReceivedHandler(HandleReceivedApplicationMessage);
  140. _managedMqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(x => OnConnected(x));
  141. _managedMqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(x => OnDisconnected(x));
  142. await _managedMqttClient.StartAsync(new ManagedMqttClientOptions
  143. {
  144. ClientOptions = options
  145. });
  146. }
  147. else
  148. {
  149. _mqttClient = factory.CreateMqttClient();
  150. _mqttClient.UseApplicationMessageReceivedHandler(HandleReceivedApplicationMessage);
  151. _mqttClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(x => OnConnected(x));
  152. _mqttClient.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(x => OnDisconnected(x));
  153. await _mqttClient.ConnectAsync(options);
  154. }
  155. }
  156. catch (Exception exception)
  157. {
  158. Trace.Text += exception + Environment.NewLine;
  159. }
  160. }
  161. private void OnDisconnected(MqttClientDisconnectedEventArgs e)
  162. {
  163. _traceMessages.Enqueue(new MqttNetLogMessage("", DateTime.Now, -1,
  164. "", MqttNetLogLevel.Info, "! DISCONNECTED EVENT FIRED", null));
  165. Task.Run(UpdateLogAsync);
  166. }
  167. private void OnConnected(MqttClientConnectedEventArgs e)
  168. {
  169. _traceMessages.Enqueue(new MqttNetLogMessage("", DateTime.Now, -1,
  170. "", MqttNetLogLevel.Info, "! CONNECTED EVENT FIRED", null));
  171. Task.Run(UpdateLogAsync);
  172. }
  173. private async Task HandleReceivedApplicationMessage(MqttApplicationMessageReceivedEventArgs eventArgs)
  174. {
  175. var item = $"Timestamp: {DateTime.Now:O} | Topic: {eventArgs.ApplicationMessage.Topic} | Payload: {Encoding.UTF8.GetString(eventArgs.ApplicationMessage.Payload)} | QoS: {eventArgs.ApplicationMessage.QualityOfServiceLevel}";
  176. await Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
  177. {
  178. if (AddReceivedMessagesToList.IsChecked == true)
  179. {
  180. ReceivedMessages.Items.Add(item);
  181. }
  182. });
  183. }
  184. private async void Publish(object sender, RoutedEventArgs e)
  185. {
  186. try
  187. {
  188. var qos = MqttQualityOfServiceLevel.AtMostOnce;
  189. if (QoS1.IsChecked == true)
  190. {
  191. qos = MqttQualityOfServiceLevel.AtLeastOnce;
  192. }
  193. if (QoS2.IsChecked == true)
  194. {
  195. qos = MqttQualityOfServiceLevel.ExactlyOnce;
  196. }
  197. var payload = new byte[0];
  198. if (PlainText.IsChecked == true)
  199. {
  200. payload = Encoding.UTF8.GetBytes(Payload.Text);
  201. }
  202. if (Base64.IsChecked == true)
  203. {
  204. payload = Convert.FromBase64String(Payload.Text);
  205. }
  206. var message = new MqttApplicationMessageBuilder()
  207. .WithContentType(ContentType.Text)
  208. .WithResponseTopic(ResponseTopic.Text)
  209. .WithTopic(Topic.Text)
  210. .WithPayload(payload)
  211. .WithQualityOfServiceLevel(qos)
  212. .WithRetainFlag(Retain.IsChecked == true)
  213. .Build();
  214. if (_mqttClient != null)
  215. {
  216. await _mqttClient.PublishAsync(message);
  217. }
  218. if (_managedMqttClient != null)
  219. {
  220. await _managedMqttClient.PublishAsync(message);
  221. }
  222. }
  223. catch (Exception exception)
  224. {
  225. Trace.Text += exception + Environment.NewLine;
  226. }
  227. }
  228. private async void Disconnect(object sender, RoutedEventArgs e)
  229. {
  230. try
  231. {
  232. if (_mqttClient != null)
  233. {
  234. await _mqttClient.DisconnectAsync();
  235. _mqttClient.Dispose();
  236. _mqttClient = null;
  237. }
  238. if (_managedMqttClient != null)
  239. {
  240. await _managedMqttClient.StopAsync();
  241. _managedMqttClient.Dispose();
  242. _managedMqttClient = null;
  243. }
  244. }
  245. catch (Exception exception)
  246. {
  247. Trace.Text += exception + Environment.NewLine;
  248. }
  249. }
  250. private void ClearLog(object sender, RoutedEventArgs e)
  251. {
  252. while (_traceMessages.Count > 0)
  253. {
  254. _traceMessages.TryDequeue(out _);
  255. }
  256. Trace.Text = string.Empty;
  257. }
  258. private async void Subscribe(object sender, RoutedEventArgs e)
  259. {
  260. try
  261. {
  262. var qos = MqttQualityOfServiceLevel.AtMostOnce;
  263. if (SubscribeQoS1.IsChecked == true)
  264. {
  265. qos = MqttQualityOfServiceLevel.AtLeastOnce;
  266. }
  267. if (SubscribeQoS2.IsChecked == true)
  268. {
  269. qos = MqttQualityOfServiceLevel.ExactlyOnce;
  270. }
  271. var topicFilter = new TopicFilter { Topic = SubscribeTopic.Text, QualityOfServiceLevel = qos };
  272. if (_mqttClient != null)
  273. {
  274. await _mqttClient.SubscribeAsync(topicFilter);
  275. }
  276. if (_managedMqttClient != null)
  277. {
  278. await _managedMqttClient.SubscribeAsync(topicFilter);
  279. }
  280. }
  281. catch (Exception exception)
  282. {
  283. Trace.Text += exception + Environment.NewLine;
  284. }
  285. }
  286. private async void Unsubscribe(object sender, RoutedEventArgs e)
  287. {
  288. try
  289. {
  290. if (_mqttClient != null)
  291. {
  292. await _mqttClient.UnsubscribeAsync(SubscribeTopic.Text);
  293. }
  294. if (_managedMqttClient != null)
  295. {
  296. await _managedMqttClient.UnsubscribeAsync(SubscribeTopic.Text);
  297. }
  298. }
  299. catch (Exception exception)
  300. {
  301. Trace.Text += exception + Environment.NewLine;
  302. }
  303. }
  304. // This code is for the Wiki at GitHub!
  305. // ReSharper disable once UnusedMember.Local
  306. private async void StartServer(object sender, RoutedEventArgs e)
  307. {
  308. if (_mqttServer != null)
  309. {
  310. return;
  311. }
  312. JsonServerStorage storage = null;
  313. if (ServerPersistRetainedMessages.IsChecked == true)
  314. {
  315. storage = new JsonServerStorage();
  316. if (ServerClearRetainedMessages.IsChecked == true)
  317. {
  318. storage.Clear();
  319. }
  320. }
  321. _mqttServer = new MqttFactory().CreateMqttServer();
  322. var options = new MqttServerOptions();
  323. options.DefaultEndpointOptions.Port = int.Parse(ServerPort.Text);
  324. options.Storage = storage;
  325. options.EnablePersistentSessions = ServerAllowPersistentSessions.IsChecked == true;
  326. await _mqttServer.StartAsync(options);
  327. }
  328. private async void StopServer(object sender, RoutedEventArgs e)
  329. {
  330. if (_mqttServer == null)
  331. {
  332. return;
  333. }
  334. await _mqttServer.StopAsync();
  335. _mqttServer = null;
  336. }
  337. private void ClearReceivedMessages(object sender, RoutedEventArgs e)
  338. {
  339. ReceivedMessages.Items.Clear();
  340. }
  341. private async void ExecuteRpc(object sender, RoutedEventArgs e)
  342. {
  343. var qos = MqttQualityOfServiceLevel.AtMostOnce;
  344. if (RpcQoS1.IsChecked == true)
  345. {
  346. qos = MqttQualityOfServiceLevel.AtLeastOnce;
  347. }
  348. if (RpcQoS2.IsChecked == true)
  349. {
  350. qos = MqttQualityOfServiceLevel.ExactlyOnce;
  351. }
  352. var payload = new byte[0];
  353. if (RpcText.IsChecked == true)
  354. {
  355. payload = Encoding.UTF8.GetBytes(RpcPayload.Text);
  356. }
  357. if (RpcBase64.IsChecked == true)
  358. {
  359. payload = Convert.FromBase64String(RpcPayload.Text);
  360. }
  361. try
  362. {
  363. var rpcClient = new MqttRpcClient(_mqttClient);
  364. var response = await rpcClient.ExecuteAsync(TimeSpan.FromSeconds(5), RpcMethod.Text, payload, qos);
  365. RpcResponses.Items.Add(RpcMethod.Text + " >>> " + Encoding.UTF8.GetString(response));
  366. }
  367. catch (MqttCommunicationTimedOutException)
  368. {
  369. RpcResponses.Items.Add(RpcMethod.Text + " >>> [TIMEOUT]");
  370. }
  371. catch (Exception exception)
  372. {
  373. RpcResponses.Items.Add(RpcMethod.Text + " >>> [EXCEPTION (" + exception.Message + ")]");
  374. }
  375. }
  376. private void ClearRpcResponses(object sender, RoutedEventArgs e)
  377. {
  378. RpcResponses.Items.Clear();
  379. }
  380. private void ClearSessions(object sender, RoutedEventArgs e)
  381. {
  382. _sessions.Clear();
  383. }
  384. private void RefreshSessions(object sender, RoutedEventArgs e)
  385. {
  386. if (_mqttServer == null)
  387. {
  388. return;
  389. }
  390. var sessions = _mqttServer.GetClientStatusAsync().GetAwaiter().GetResult();
  391. _sessions.Clear();
  392. foreach (var session in sessions)
  393. {
  394. _sessions.Add(session);
  395. }
  396. ListViewSessions.DataContext = _sessions;
  397. }
  398. #region Wiki Code
  399. private async Task WikiCode()
  400. {
  401. {
  402. // Write all trace messages to the console window.
  403. MqttNetGlobalLogger.LogMessagePublished += (s, e) =>
  404. {
  405. Console.WriteLine($">> [{e.TraceMessage.Timestamp:O}] [{e.TraceMessage.ThreadId}] [{e.TraceMessage.Source}] [{e.TraceMessage.Level}]: {e.TraceMessage.Message}");
  406. if (e.TraceMessage.Exception != null)
  407. {
  408. Console.WriteLine(e.TraceMessage.Exception);
  409. }
  410. };
  411. }
  412. {
  413. // Use a custom identifier for the trace messages.
  414. var clientOptions = new MqttClientOptionsBuilder()
  415. .Build();
  416. }
  417. {
  418. // Create a new MQTT client.
  419. var factory = new MqttFactory();
  420. var mqttClient = factory.CreateMqttClient();
  421. {
  422. // Create TCP based options using the builder.
  423. var options = new MqttClientOptionsBuilder()
  424. .WithClientId("Client1")
  425. .WithTcpServer("broker.hivemq.com")
  426. .WithCredentials("bud", "%spencer%")
  427. .WithTls()
  428. .WithCleanSession()
  429. .Build();
  430. await mqttClient.ConnectAsync(options);
  431. }
  432. {
  433. // Use TCP connection.
  434. var options = new MqttClientOptionsBuilder()
  435. .WithTcpServer("broker.hivemq.com", 1883) // Port is optional
  436. .Build();
  437. }
  438. {
  439. // Use secure TCP connection.
  440. var options = new MqttClientOptionsBuilder()
  441. .WithTcpServer("broker.hivemq.com")
  442. .WithTls()
  443. .Build();
  444. }
  445. {
  446. // Use WebSocket connection.
  447. var options = new MqttClientOptionsBuilder()
  448. .WithWebSocketServer("broker.hivemq.com:8000/mqtt")
  449. .Build();
  450. await mqttClient.ConnectAsync(options);
  451. }
  452. {
  453. // Create TCP based options manually
  454. var options = new MqttClientOptions
  455. {
  456. ClientId = "Client1",
  457. Credentials = new MqttClientCredentials
  458. {
  459. Username = "bud",
  460. Password = "%spencer%"
  461. },
  462. ChannelOptions = new MqttClientTcpOptions
  463. {
  464. Server = "broker.hivemq.org",
  465. TlsOptions = new MqttClientTlsOptions
  466. {
  467. UseTls = true
  468. }
  469. },
  470. };
  471. }
  472. {
  473. // Subscribe to a topic
  474. await mqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic("my/topic").Build());
  475. // Unsubscribe from a topic
  476. await mqttClient.UnsubscribeAsync("my/topic");
  477. // Publish an application message
  478. var applicationMessage = new MqttApplicationMessageBuilder()
  479. .WithTopic("A/B/C")
  480. .WithPayload("Hello World")
  481. .WithAtLeastOnceQoS()
  482. .Build();
  483. await mqttClient.PublishAsync(applicationMessage);
  484. }
  485. }
  486. // ----------------------------------
  487. {
  488. var options = new MqttServerOptions();
  489. options.ConnectionValidator = new MqttServerConnectionValidatorDelegate(c =>
  490. {
  491. if (c.ClientId.Length < 10)
  492. {
  493. c.ReturnCode = MqttConnectReturnCode.ConnectionRefusedIdentifierRejected;
  494. return;
  495. }
  496. if (c.Username != "mySecretUser")
  497. {
  498. c.ReturnCode = MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
  499. return;
  500. }
  501. if (c.Password != "mySecretPassword")
  502. {
  503. c.ReturnCode = MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
  504. return;
  505. }
  506. c.ReturnCode = MqttConnectReturnCode.ConnectionAccepted;
  507. });
  508. var factory = new MqttFactory();
  509. var mqttServer = factory.CreateMqttServer();
  510. await mqttServer.StartAsync(options);
  511. Console.WriteLine("Press any key to exit.");
  512. Console.ReadLine();
  513. await mqttServer.StopAsync();
  514. }
  515. // ----------------------------------
  516. // For UWP apps:
  517. MqttTcpChannel.CustomIgnorableServerCertificateErrorsResolver = o =>
  518. {
  519. if (o.Server == "server_with_revoked_cert")
  520. {
  521. return new[] { ChainValidationResult.Revoked };
  522. }
  523. return new ChainValidationResult[0];
  524. };
  525. {
  526. // Start a MQTT server.
  527. var mqttServer = new MqttFactory().CreateMqttServer();
  528. await mqttServer.StartAsync(new MqttServerOptions());
  529. Console.WriteLine("Press any key to exit.");
  530. Console.ReadLine();
  531. await mqttServer.StopAsync();
  532. }
  533. {
  534. // Configure MQTT server.
  535. var optionsBuilder = new MqttServerOptionsBuilder()
  536. .WithConnectionBacklog(100)
  537. .WithDefaultEndpointPort(1884);
  538. var options = new MqttServerOptions
  539. {
  540. };
  541. options.ConnectionValidator = new MqttServerConnectionValidatorDelegate(c =>
  542. {
  543. if (c.ClientId != "Highlander")
  544. {
  545. c.ReturnCode = MqttConnectReturnCode.ConnectionRefusedIdentifierRejected;
  546. return;
  547. }
  548. c.ReturnCode = MqttConnectReturnCode.ConnectionAccepted;
  549. });
  550. var mqttServer = new MqttFactory().CreateMqttServer();
  551. await mqttServer.StartAsync(optionsBuilder.Build());
  552. }
  553. {
  554. // Setup client validator.
  555. var options = new MqttServerOptions
  556. {
  557. ConnectionValidator = new MqttServerConnectionValidatorDelegate(c =>
  558. {
  559. if (c.ClientId.Length < 10)
  560. {
  561. c.ReturnCode = MqttConnectReturnCode.ConnectionRefusedIdentifierRejected;
  562. return;
  563. }
  564. if (c.Username != "mySecretUser")
  565. {
  566. c.ReturnCode = MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
  567. return;
  568. }
  569. if (c.Password != "mySecretPassword")
  570. {
  571. c.ReturnCode = MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
  572. return;
  573. }
  574. c.ReturnCode = MqttConnectReturnCode.ConnectionAccepted;
  575. })
  576. };
  577. }
  578. {
  579. // Create a new MQTT server.
  580. var mqttServer = new MqttFactory().CreateMqttServer();
  581. }
  582. {
  583. // Setup and start a managed MQTT client.
  584. var options = new ManagedMqttClientOptionsBuilder()
  585. .WithAutoReconnectDelay(TimeSpan.FromSeconds(5))
  586. .WithClientOptions(new MqttClientOptionsBuilder()
  587. .WithClientId("Client1")
  588. .WithTcpServer("broker.hivemq.com")
  589. .WithTls().Build())
  590. .Build();
  591. var mqttClient = new MqttFactory().CreateManagedMqttClient();
  592. await mqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic("my/topic").Build());
  593. await mqttClient.StartAsync(options);
  594. }
  595. }
  596. #endregion
  597. }
  598. }