MqttClientInitializer.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. using Edge.Core.IndustryStandardInterface.NetworkController;
  2. using Microsoft.Extensions.Logging;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Security.Cryptography;
  7. using System.Text;
  8. using System.Text.Json;
  9. using System.Threading.Tasks;
  10. using static DeviceInfoToAliIotHubViaGateway.App;
  11. namespace DeviceInfoToAliIotHubViaGateway
  12. {
  13. /// <summary>
  14. /// helper for open and connect to a AliIotHub MqttServer.
  15. /// </summary>
  16. internal class AliIotHubMqttClientInitializer
  17. {
  18. private IMqttClientNetworkController mqttClient;
  19. //private static readonly AliIotHubMqttClientInitializer instance = new AliIotHubMqttClientInitializer();
  20. public IMqttClientNetworkController MqttClient => this.mqttClient;
  21. //private ILogger logger = null;
  22. //public static AliIotHubMqttClientInitializer New(ILogger logger)
  23. //{
  24. // return new AliIotHubMqttClientInitializer(logger);
  25. //}
  26. internal AliIotHubMqttClientInitializer(IMqttClientNetworkController mqttClient)
  27. {
  28. this.mqttClient = mqttClient;
  29. }
  30. //public static AliIotHubMqttClientInitializer Default => instance;
  31. /// <summary>
  32. /// 一型一密免预注册的设备动态注册方式,通过此次交互,可以获得设备的ProductKey、DeviceName、ClientID、DeviceToken,相当于在IOT上建立了此设备,再就可以像普通设备一样发起通讯了.
  33. /// </summary>
  34. /// <param name="mqttServerUrl"></param>
  35. /// <param name="port"></param>
  36. /// <param name="mqttClientIdPrefix">表示客户端ID,建议使用设备的MAC地址或SN码</param>
  37. /// <param name="productKey"></param>
  38. /// <param name="productSecret"></param>
  39. /// <param name="dynamicDeviceName"></param>
  40. /// <returns></returns>
  41. public async Task<DynamicDeviceInfo> DynamicRegDeviceWithoutPreRegAsync(string mqttServerUrl, int port,
  42. string mqttClientIdPrefix, string productKey, string productSecret, string dynamicDeviceName)
  43. {
  44. var rebootSucceed = await this.mqttClient.ResetAsync();
  45. if (!rebootSucceed)
  46. {
  47. await Task.Delay(500);
  48. return null;
  49. }
  50. await Task.Delay(2000);
  51. //this.logger.LogInformation(" Querying Mqtt client status...");
  52. var status = await this.mqttClient.QueryStatusAsync();
  53. //this.logger.LogInformation(" Mqtt client Status is: " + status);
  54. if (status != NetworkState.NetworkConnected)
  55. return null;
  56. bool succeed = false;
  57. // looks like the sample in BC35g Mqtt protocol doc is not work via below command.
  58. //succeed = await this.mqttClient.ConfigNetwork(AliIotHub_ProductKey,
  59. // AliIotHub_DeviceName, AliIotHub_DeviceSecret);
  60. //if (!succeed)
  61. //{
  62. // await Task.Delay(500);
  63. // return false;
  64. //}
  65. succeed = await this.mqttClient.OpenAsync(mqttServerUrl, port);
  66. if (!succeed)
  67. {
  68. await Task.Delay(500);
  69. await this.mqttClient.CloseAsync();
  70. return null;
  71. }
  72. Random r = new Random();
  73. int random = 199;// r.Next(1, 1000000);
  74. var toBeHashing = $"deviceName{dynamicDeviceName}productKey{productKey}random{random}";
  75. var aliIotHubMqttPwd = Encoding.UTF8.GetBytes(toBeHashing).SignWithHMacSHA1(Encoding.UTF8.GetBytes(productSecret));
  76. string aliIotHub_MqttComplexClientId = mqttClientIdPrefix + "|securemode=2,authType=regnwl,random=" + random + ",signmethod=hmacsha1|";
  77. var aliIotHubMqttUserName = dynamicDeviceName + "&" + productKey;
  78. var onMsgReceivedTCS = new TaskCompletionSource<string>();
  79. EventHandler<OnMqttMessageReceivedEventArg> evtHandler = (s, a) =>
  80. {
  81. if (a.Message.Topic == "/ext/regnwl")
  82. onMsgReceivedTCS.SetResult(Encoding.UTF8.GetString(a.Message.Message));
  83. };
  84. this.mqttClient.OnMessageReceived += evtHandler;
  85. succeed = await this.mqttClient.ConnectAsync(aliIotHub_MqttComplexClientId, aliIotHubMqttUserName, aliIotHubMqttPwd);
  86. if (!succeed)
  87. {
  88. await Task.Delay(500);
  89. await this.mqttClient.DisconnectAsync();
  90. return null;
  91. }
  92. try
  93. {
  94. var ti = Task.WaitAny(new[] { Task.Delay(6000), onMsgReceivedTCS.Task });
  95. if (ti == 0)
  96. return null;
  97. var dynamicRegistedGatewayDeviceInfo = JsonSerializer.Deserialize<DynamicDeviceInfo>(onMsgReceivedTCS.Task.Result);
  98. return dynamicRegistedGatewayDeviceInfo;
  99. }
  100. finally
  101. {
  102. this.mqttClient.OnMessageReceived -= evtHandler;
  103. }
  104. }
  105. /// <summary>
  106. /// 用设备的ProductKey、DeviceName、ClientID、DeviceToken,像普通设备一样发起通讯.
  107. /// </summary>
  108. /// <param name="dynamicDeviceInfo">网关设备</param>
  109. /// <returns></returns>
  110. public async Task<bool> DynamicDeviceConnAsync(string mqttServerUrl, int port, DynamicDeviceInfo dynamicDeviceInfo)
  111. {
  112. var rebootSucceed = await this.mqttClient.ResetAsync();
  113. if (!rebootSucceed)
  114. {
  115. await Task.Delay(500);
  116. return false;
  117. }
  118. await Task.Delay(2000);
  119. //this.logger.LogInformation(" Querying Mqtt client status...");
  120. var status = await this.mqttClient.QueryStatusAsync();
  121. //this.logger.LogInformation(" Mqtt client Status is: " + status);
  122. if (status != NetworkState.NetworkConnected)
  123. return false;
  124. bool succeed = false;
  125. // looks like the sample in BC35g Mqtt protocol doc is not work via below command.
  126. //succeed = await this.mqttClient.ConfigNetwork(AliIotHub_ProductKey,
  127. // AliIotHub_DeviceName, AliIotHub_DeviceSecret);
  128. //if (!succeed)
  129. //{
  130. // await Task.Delay(500);
  131. // return false;
  132. //}
  133. succeed = await this.mqttClient.OpenAsync(mqttServerUrl, port);
  134. if (!succeed)
  135. {
  136. await Task.Delay(500);
  137. await this.mqttClient.CloseAsync();
  138. return false;
  139. }
  140. var aliIotHubMqttPwd = dynamicDeviceInfo.deviceToken;
  141. string aliIotHub_MqttComplexClientId = dynamicDeviceInfo.clientId + "|securemode=-2,authType=connwl|";
  142. var aliIotHubMqttUserName = dynamicDeviceInfo.deviceName + "&" + dynamicDeviceInfo.productKey;
  143. succeed = await this.mqttClient.ConnectAsync(aliIotHub_MqttComplexClientId, aliIotHubMqttUserName, aliIotHubMqttPwd);
  144. if (!succeed)
  145. {
  146. await Task.Delay(500);
  147. await this.mqttClient.DisconnectAsync();
  148. return false;
  149. }
  150. return true;
  151. }
  152. }
  153. }