You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

790 lines
27 KiB

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