using Edge.Core.IndustryStandardInterface.NetworkController; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Text.Json; using System.Threading.Tasks; using static DeviceInfoToAliIotHubViaGateway.App; namespace DeviceInfoToAliIotHubViaGateway { /// /// helper for open and connect to a AliIotHub MqttServer. /// internal class AliIotHubMqttClientInitializer { private IMqttClientNetworkController mqttClient; //private static readonly AliIotHubMqttClientInitializer instance = new AliIotHubMqttClientInitializer(); public IMqttClientNetworkController MqttClient => this.mqttClient; //private ILogger logger = null; //public static AliIotHubMqttClientInitializer New(ILogger logger) //{ // return new AliIotHubMqttClientInitializer(logger); //} internal AliIotHubMqttClientInitializer(IMqttClientNetworkController mqttClient) { this.mqttClient = mqttClient; } //public static AliIotHubMqttClientInitializer Default => instance; /// /// 一型一密免预注册的设备动态注册方式,通过此次交互,可以获得设备的ProductKey、DeviceName、ClientID、DeviceToken,相当于在IOT上建立了此设备,再就可以像普通设备一样发起通讯了. /// /// /// /// 表示客户端ID,建议使用设备的MAC地址或SN码 /// /// /// /// public async Task DynamicRegDeviceWithoutPreRegAsync(string mqttServerUrl, int port, string mqttClientIdPrefix, string productKey, string productSecret, string dynamicDeviceName) { var rebootSucceed = await this.mqttClient.ResetAsync(); if (!rebootSucceed) { await Task.Delay(500); return null; } await Task.Delay(2000); //this.logger.LogInformation(" Querying Mqtt client status..."); var status = await this.mqttClient.QueryStatusAsync(); //this.logger.LogInformation(" Mqtt client Status is: " + status); if (status != NetworkState.NetworkConnected) return null; bool succeed = false; // looks like the sample in BC35g Mqtt protocol doc is not work via below command. //succeed = await this.mqttClient.ConfigNetwork(AliIotHub_ProductKey, // AliIotHub_DeviceName, AliIotHub_DeviceSecret); //if (!succeed) //{ // await Task.Delay(500); // return false; //} succeed = await this.mqttClient.OpenAsync(mqttServerUrl, port); if (!succeed) { await Task.Delay(500); await this.mqttClient.CloseAsync(); return null; } Random r = new Random(); int random = 199;// r.Next(1, 1000000); var toBeHashing = $"deviceName{dynamicDeviceName}productKey{productKey}random{random}"; var aliIotHubMqttPwd = Encoding.UTF8.GetBytes(toBeHashing).SignWithHMacSHA1(Encoding.UTF8.GetBytes(productSecret)); string aliIotHub_MqttComplexClientId = mqttClientIdPrefix + "|securemode=2,authType=regnwl,random=" + random + ",signmethod=hmacsha1|"; var aliIotHubMqttUserName = dynamicDeviceName + "&" + productKey; var onMsgReceivedTCS = new TaskCompletionSource(); EventHandler evtHandler = (s, a) => { if (a.Message.Topic == "/ext/regnwl") onMsgReceivedTCS.SetResult(Encoding.UTF8.GetString(a.Message.Message)); }; this.mqttClient.OnMessageReceived += evtHandler; succeed = await this.mqttClient.ConnectAsync(aliIotHub_MqttComplexClientId, aliIotHubMqttUserName, aliIotHubMqttPwd); if (!succeed) { await Task.Delay(500); await this.mqttClient.DisconnectAsync(); return null; } try { var ti = Task.WaitAny(new[] { Task.Delay(6000), onMsgReceivedTCS.Task }); if (ti == 0) return null; var dynamicRegistedGatewayDeviceInfo = JsonSerializer.Deserialize(onMsgReceivedTCS.Task.Result); return dynamicRegistedGatewayDeviceInfo; } finally { this.mqttClient.OnMessageReceived -= evtHandler; } } /// /// 用设备的ProductKey、DeviceName、ClientID、DeviceToken,像普通设备一样发起通讯. /// /// 网关设备 /// public async Task DynamicDeviceConnAsync(string mqttServerUrl, int port, DynamicDeviceInfo dynamicDeviceInfo) { var rebootSucceed = await this.mqttClient.ResetAsync(); if (!rebootSucceed) { await Task.Delay(500); return false; } await Task.Delay(2000); //this.logger.LogInformation(" Querying Mqtt client status..."); var status = await this.mqttClient.QueryStatusAsync(); //this.logger.LogInformation(" Mqtt client Status is: " + status); if (status != NetworkState.NetworkConnected) return false; bool succeed = false; // looks like the sample in BC35g Mqtt protocol doc is not work via below command. //succeed = await this.mqttClient.ConfigNetwork(AliIotHub_ProductKey, // AliIotHub_DeviceName, AliIotHub_DeviceSecret); //if (!succeed) //{ // await Task.Delay(500); // return false; //} succeed = await this.mqttClient.OpenAsync(mqttServerUrl, port); if (!succeed) { await Task.Delay(500); await this.mqttClient.CloseAsync(); return false; } var aliIotHubMqttPwd = dynamicDeviceInfo.deviceToken; string aliIotHub_MqttComplexClientId = dynamicDeviceInfo.clientId + "|securemode=-2,authType=connwl|"; var aliIotHubMqttUserName = dynamicDeviceInfo.deviceName + "&" + dynamicDeviceInfo.productKey; succeed = await this.mqttClient.ConnectAsync(aliIotHub_MqttComplexClientId, aliIotHubMqttUserName, aliIotHubMqttPwd); if (!succeed) { await Task.Delay(500); await this.mqttClient.DisconnectAsync(); return false; } return true; } } }