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.
 
 
 
 

386 line
12 KiB

  1. using System;
  2. using System.Text;
  3. using System.Threading.Tasks;
  4. using Windows.Security.Cryptography.Certificates;
  5. using Windows.UI.Core;
  6. using Windows.UI.Xaml;
  7. using Microsoft.Extensions.DependencyInjection;
  8. using MQTTnet.Core;
  9. using MQTTnet.Core.Client;
  10. using MQTTnet.Core.Diagnostics;
  11. using MQTTnet.Core.Protocol;
  12. using MQTTnet.Core.Server;
  13. using MQTTnet.Implementations;
  14. namespace MQTTnet.TestApp.UniversalWindows
  15. {
  16. public sealed partial class MainPage
  17. {
  18. private IMqttClient _mqttClient;
  19. private IMqttServer _mqttServer;
  20. public MainPage()
  21. {
  22. InitializeComponent();
  23. MqttNetTrace.TraceMessagePublished += OnTraceMessagePublished;
  24. }
  25. private async void OnTraceMessagePublished(object sender, MqttNetTraceMessagePublishedEventArgs e)
  26. {
  27. await Trace.Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
  28. {
  29. var text = $"[{e.TraceMessage.Timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{e.TraceMessage.Level}] [{e.TraceMessage.Source}] [{e.TraceMessage.ThreadId}] [{e.TraceMessage.Message}]{Environment.NewLine}";
  30. if (e.TraceMessage.Exception != null)
  31. {
  32. text += $"{e.TraceMessage.Exception}{Environment.NewLine}";
  33. }
  34. Trace.Text += text;
  35. });
  36. }
  37. private async void Connect(object sender, RoutedEventArgs e)
  38. {
  39. var tlsOptions = new MqttClientTlsOptions
  40. {
  41. UseTls = UseTls.IsChecked == true,
  42. IgnoreCertificateChainErrors = true,
  43. IgnoreCertificateRevocationErrors = true,
  44. AllowUntrustedCertificates = true
  45. };
  46. var options = new MqttClientOptions { ClientId = ClientId.Text };
  47. if (UseTcp.IsChecked == true)
  48. {
  49. options.ChannelOptions = new MqttClientTcpOptions
  50. {
  51. Server = Server.Text,
  52. TlsOptions = tlsOptions
  53. };
  54. }
  55. if (UseWs.IsChecked == true)
  56. {
  57. options.ChannelOptions = new MqttClientWebSocketOptions
  58. {
  59. Uri = Server.Text,
  60. TlsOptions = tlsOptions
  61. };
  62. }
  63. if (options.ChannelOptions == null)
  64. {
  65. throw new InvalidOperationException();
  66. }
  67. options.Credentials = new MqttClientCredentials
  68. {
  69. Username = User.Text,
  70. Password = Password.Text
  71. };
  72. options.CleanSession = CleanSession.IsChecked == true;
  73. try
  74. {
  75. if (_mqttClient != null)
  76. {
  77. await _mqttClient.DisconnectAsync();
  78. _mqttClient.ApplicationMessageReceived -= OnApplicationMessageReceived;
  79. }
  80. var factory = new MqttFactory();
  81. _mqttClient = factory.CreateMqttClient();
  82. _mqttClient.ApplicationMessageReceived += OnApplicationMessageReceived;
  83. await _mqttClient.ConnectAsync(options);
  84. }
  85. catch (Exception exception)
  86. {
  87. Trace.Text += exception + Environment.NewLine;
  88. }
  89. }
  90. private async void OnApplicationMessageReceived(object sender, MqttApplicationMessageReceivedEventArgs eventArgs)
  91. {
  92. var item = $"Timestamp: {DateTime.Now:O} | Topic: {eventArgs.ApplicationMessage.Topic} | Payload: {Encoding.UTF8.GetString(eventArgs.ApplicationMessage.Payload)} | QoS: {eventArgs.ApplicationMessage.QualityOfServiceLevel}";
  93. await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
  94. {
  95. ReceivedMessages.Items.Add(item);
  96. });
  97. }
  98. private async void Publish(object sender, RoutedEventArgs e)
  99. {
  100. if (_mqttClient == null)
  101. {
  102. return;
  103. }
  104. try
  105. {
  106. var qos = MqttQualityOfServiceLevel.AtMostOnce;
  107. if (QoS1.IsChecked == true)
  108. {
  109. qos = MqttQualityOfServiceLevel.AtLeastOnce;
  110. }
  111. if (QoS2.IsChecked == true)
  112. {
  113. qos = MqttQualityOfServiceLevel.ExactlyOnce;
  114. }
  115. var payload = new byte[0];
  116. if (Text.IsChecked == true)
  117. {
  118. payload = Encoding.UTF8.GetBytes(Payload.Text);
  119. }
  120. if (Base64.IsChecked == true)
  121. {
  122. payload = Convert.FromBase64String(Payload.Text);
  123. }
  124. var message = new MqttApplicationMessageBuilder()
  125. .WithTopic(Topic.Text)
  126. .WithPayload(payload)
  127. .WithQualityOfServiceLevel(qos)
  128. .WithRetainFlag(Retain.IsChecked == true)
  129. .Build();
  130. await _mqttClient.PublishAsync(message);
  131. }
  132. catch (Exception exception)
  133. {
  134. Trace.Text += exception + Environment.NewLine;
  135. }
  136. }
  137. private async void Disconnect(object sender, RoutedEventArgs e)
  138. {
  139. try
  140. {
  141. await _mqttClient.DisconnectAsync();
  142. }
  143. catch (Exception exception)
  144. {
  145. Trace.Text += exception + Environment.NewLine;
  146. }
  147. }
  148. private void Clear(object sender, RoutedEventArgs e)
  149. {
  150. Trace.Text = string.Empty;
  151. }
  152. private async void Subscribe(object sender, RoutedEventArgs e)
  153. {
  154. if (_mqttClient == null)
  155. {
  156. return;
  157. }
  158. try
  159. {
  160. var qos = MqttQualityOfServiceLevel.AtMostOnce;
  161. if (SubscribeQoS1.IsChecked == true)
  162. {
  163. qos = MqttQualityOfServiceLevel.AtLeastOnce;
  164. }
  165. if (SubscribeQoS2.IsChecked == true)
  166. {
  167. qos = MqttQualityOfServiceLevel.ExactlyOnce;
  168. }
  169. await _mqttClient.SubscribeAsync(new TopicFilter(SubscribeTopic.Text, qos));
  170. }
  171. catch (Exception exception)
  172. {
  173. Trace.Text += exception + Environment.NewLine;
  174. }
  175. }
  176. private async void Unsubscribe(object sender, RoutedEventArgs e)
  177. {
  178. if (_mqttClient == null)
  179. {
  180. return;
  181. }
  182. try
  183. {
  184. await _mqttClient.UnsubscribeAsync(SubscribeTopic.Text);
  185. }
  186. catch (Exception exception)
  187. {
  188. Trace.Text += exception + Environment.NewLine;
  189. }
  190. }
  191. // This code is for the Wiki at GitHub!
  192. // ReSharper disable once UnusedMember.Local
  193. private async Task WikiCode()
  194. {
  195. {
  196. // Create a new MQTT client
  197. var services = new ServiceCollection()
  198. .AddMqttClient()
  199. .BuildServiceProvider();
  200. var factory = new MqttFactory(services);
  201. var client = factory.CreateMqttClient();
  202. {
  203. // Create TCP based options using the builder
  204. var options = new MqttClientOptionsBuilder()
  205. .WithClientId("Client1")
  206. .WithTcpServer("broker.hivemq.com")
  207. .WithCredentials("bud", "%spencer%")
  208. .WithTls()
  209. .WithCleanSession()
  210. .Build();
  211. await client.ConnectAsync(options);
  212. }
  213. {
  214. // Create TCP based options manually
  215. var options = new MqttClientOptions
  216. {
  217. ClientId = "Client1",
  218. Credentials = new MqttClientCredentials
  219. {
  220. Username = "bud",
  221. Password = "%spencer%"
  222. },
  223. ChannelOptions = new MqttClientTcpOptions
  224. {
  225. Server = "broker.hivemq.org",
  226. TlsOptions = new MqttClientTlsOptions
  227. {
  228. UseTls = true
  229. }
  230. },
  231. };
  232. }
  233. {
  234. // Subscribe to a topic
  235. await client.SubscribeAsync(new TopicFilterBuilder().WithTopic("my/topic").Build());
  236. // Unsubscribe from a topic
  237. await client.UnsubscribeAsync("my/topic");
  238. // Publish an application message
  239. var applicationMessage = new MqttApplicationMessageBuilder()
  240. .WithTopic("A/B/C")
  241. .WithPayload("Hello World")
  242. .WithAtLeastOnceQoS()
  243. .Build();
  244. await client.PublishAsync(applicationMessage);
  245. }
  246. }
  247. // ----------------------------------
  248. {
  249. var services = new ServiceCollection()
  250. .AddMqttServer(options =>
  251. {
  252. options.ConnectionValidator = c =>
  253. {
  254. if (c.ClientId.Length < 10)
  255. {
  256. return MqttConnectReturnCode.ConnectionRefusedIdentifierRejected;
  257. }
  258. if (c.Username != "mySecretUser")
  259. {
  260. return MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
  261. }
  262. if (c.Password != "mySecretPassword")
  263. {
  264. return MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
  265. }
  266. return MqttConnectReturnCode.ConnectionAccepted;
  267. };
  268. })
  269. .BuildServiceProvider();
  270. var factory = new MqttFactory(services);
  271. var mqttServer = factory.CreateMqttServer();
  272. await mqttServer.StartAsync();
  273. Console.WriteLine("Press any key to exit.");
  274. Console.ReadLine();
  275. await mqttServer.StopAsync();
  276. }
  277. // ----------------------------------
  278. // For UWP apps:
  279. MqttTcpChannel.CustomIgnorableServerCertificateErrorsResolver = o =>
  280. {
  281. if (o.Server == "server_with_revoked_cert")
  282. {
  283. return new[] { ChainValidationResult.Revoked };
  284. }
  285. return new ChainValidationResult[0];
  286. };
  287. }
  288. private async void StartServer(object sender, RoutedEventArgs e)
  289. {
  290. if (_mqttServer != null)
  291. {
  292. return;
  293. }
  294. JsonServerStorage storage = null;
  295. if (ServerPersistRetainedMessages.IsChecked == true)
  296. {
  297. storage = new JsonServerStorage();
  298. if (ServerClearRetainedMessages.IsChecked == true)
  299. {
  300. storage.Clear();
  301. }
  302. }
  303. _mqttServer = new MqttFactory().CreateMqttServer(o =>
  304. {
  305. o.DefaultEndpointOptions.Port = int.Parse(ServerPort.Text);
  306. o.Storage = storage;
  307. });
  308. await _mqttServer.StartAsync();
  309. }
  310. private async void StopServer(object sender, RoutedEventArgs e)
  311. {
  312. if (_mqttServer == null)
  313. {
  314. return;
  315. }
  316. await _mqttServer.StopAsync();
  317. _mqttServer = null;
  318. }
  319. private void ClearReceivedMessages(object sender, RoutedEventArgs e)
  320. {
  321. ReceivedMessages.Items.Clear();
  322. }
  323. }
  324. }