using System; using MQTTnet.Client; using System.Threading.Tasks; using Shared; using MQTTnet; using System.Text; using HDL_ON.Entity; namespace HDL_ON.DAL.Net { public static class Mqtt_Cloud { static string mqttEncryptKey = ""; static string checkGatewayTopicBase64 = ""; static RemoteMACInfo CurRemoteMACInfo = null; /// /// 手机标识 /// static Guid currentGuid = Guid.NewGuid(); /// /// 外网的MQTT是否正在连接 /// /// /// 远程MqttClient /// /// /// 远程MqttClient /// public static IMqttClient RemoteMqttClient = new MqttFactory().CreateMqttClient(); static bool thisShowTip = true; //static string mqttRequestParToken=""; /// /// 推送标识 /// static string PushSignStr = System.DateTime.Now.Ticks.ToString(); /// /// 断开远程Mqtt的链接 /// public static async Task DisConnectRemoteMqttClient(string s = "") { try { if (remoteIsConnected) { remoteIsConnected = false; MainPage.Log($"Remote主动断开_{s}"); //await RemoteMqttClient.DisconnectAsync(new MQTTnet.Client.Disconnecting.MqttClientDisconnectOptions { }, CancellationToken.None); await RemoteMqttClient.DisconnectAsync(); } } catch (Exception e) { System.Console.WriteLine($"Remote断开通讯连接出异常:{e.Message}"); } } static DateTime dateTime = DateTime.MinValue; /// /// 外网的MQTT是否正在连接 /// static bool remoteMqttIsConnecting; static bool remoteIsConnected; static Mqtt_Cloud() { InitMqtt(); } public static bool IsInitMqtt = false; static void InitMqtt() { new System.Threading.Thread(async () => { while (true) { try { System.Threading.Thread.Sleep(1000); if (!MainPage.IsRemote) continue; await StartCloudMqtt(); await SubscribeTopics(); } catch { } } }) { IsBackground = true }.Start(); } static bool isSubscribeSuccess; static async Task SubscribeTopics() { if (remoteIsConnected && !isSubscribeSuccess) { try { var topicFilter1 = new TopicFilter { QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce, Topic = $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/NotifyBusGateWayInfoChange" }; var topicFilter2 = new TopicFilter { QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce, Topic = $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/Common/#" }; var topicFilter3 = new TopicFilter { QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce, Topic = $"/BusGateWayToClient/{CurRemoteMACInfo.clientId}/Push/NotifySqueeze" }; var result = await RemoteMqttClient.SubscribeAsync(new TopicFilter[] { topicFilter1, topicFilter2, topicFilter3 }); if (result.Items[0].ResultCode == MQTTnet.Client.Subscribing.MqttClientSubscribeResultCode.GrantedQoS2) { isSubscribeSuccess = true; } } catch { } } } /// /// 启动远程Mqtt /// public static async Task StartCloudMqtt() { //追加:没有远程连接的权限 if (remoteMqttIsConnecting || remoteIsConnected || !MainPage.LoginUser.IsLogin) { return; } await Task.Factory.StartNew(async () => { //try { lock (RemoteMqttClient) { //表示后面将进行连接 remoteMqttIsConnecting = true; #region 初始化远程Mqtt //(3)当[连接云端的Mqtt成功后]或者[以及后面App通过云端Mqtt转发数据给网关成功后],处理接收到云端数据包响应时在mqttServerClient_ApplicationMessageReceived这个方法处理 if (RemoteMqttClient.ApplicationMessageReceivedHandler == null) { RemoteMqttClient.UseApplicationMessageReceivedHandler((e) => { try { var topic = e.ApplicationMessage.Topic; //Console.WriteLine ("回复Topic={0}", topic); if (topic == $"/BusGateWayToClient/{CurRemoteMACInfo.clientId}/Push/NotifySqueeze") { var mMes = Encoding.UTF8.GetString(e.ApplicationMessage.Payload); //收到挤下线主题 ReceiveNotifySqueezeAsync(mMes); } else if (topic == $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/NotifyBusGateWayInfoChange") { //网关上线,需要更新aeskey //收到网关上线消息主题 //ReceiveNotifyBusGateWayInfoChange(); } else if (topic == $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/Common/CheckGateway") { var ss = Encoding.UTF8.GetString(e.ApplicationMessage.Payload); ReceiveCheckGateway(ss); } else { var packet = new Packet(); if (!string.IsNullOrEmpty(mqttEncryptKey)) { packet.Bytes = Shared.Securitys.EncryptionService.AesDecryptPayload(e.ApplicationMessage.Payload, mqttEncryptKey); } else { packet.Bytes = e.ApplicationMessage.Payload; } packet.Manager(); } } catch { } }); } if (RemoteMqttClient.DisconnectedHandler == null) { RemoteMqttClient.UseDisconnectedHandler(async (e) => { System.Console.WriteLine($"远程连接断开"); isSubscribeSuccess = false; await DisConnectRemoteMqttClient("StartRemoteMqtt.DisconnectedHandler"); if (MainPage.IsRemote) { Application.RunOnMainThread(() => { //远程连接成功 }); } }); } if (RemoteMqttClient.ConnectedHandler == null) { RemoteMqttClient.UseConnectedHandler(async (e) => { System.Console.WriteLine($"远程连接成功"); MainPage.IsRemote = true; Application.RunOnMainThread(() => { //远程连接成功 MainPage.IsRemote = true; }); //刷新状态 if (CurRemoteMACInfo != null) { if (CurRemoteMACInfo.isValid == "InValid") { //远程失败 MainPage.IsRemote = false; } else { MqttRemoteSend(new byte[] { 0 }, 3); } } }); } #endregion } try { //--第一步:获取mqtt链接参数 提交MAC 服务器自动判断是否为新网关,返回是否需要自动切换远程连接的服务器 var mqttInfoRequestPar = new RemoteRequestParameters() { PlatformStr = "ON", LoginAccessToken = MainPage.LoginUser.loginTokenString, RequestVersion = MainPage.VersionString, RequestProtocolType = 0, RequestSource = 1, HdlGatewayGatewayType = 0, PublishPayloadJsonStr = PushSignStr, Mac = HDL_ON.Entity.DB_ResidenceData.residenceData.residenceGatewayMAC, }; var jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(mqttInfoRequestPar); var mqttInfoRequestResult = new HDL_ON.DAL.Server.HttpServerRequest().RequestMqttInfo(jsonString); if (mqttInfoRequestResult != null && mqttInfoRequestResult.ResponseData != null) { try { var mqttInfoRequestResult_Obj = Newtonsoft.Json.JsonConvert.DeserializeObject(mqttInfoRequestResult.ResponseData.ToString()); if (mqttInfoRequestResult_Obj != null) { string url = mqttInfoRequestResult_Obj.connEmqDomainPort; string clientId = mqttInfoRequestResult_Obj.connEmqClientId; string username = mqttInfoRequestResult_Obj.connEmqUserName; string passwordRemote = mqttInfoRequestResult_Obj.connEmqPwd; if (mqttInfoRequestResult_Obj.AccountAllGateways != null && mqttInfoRequestResult_Obj.AccountAllGateways.Count > 0) { //----第二步找出是否存在匹配当前住宅的mac,存在再进行远程。 foreach (var curRegionMac in DB_ResidenceData.residenceData.residecenInfo.homeGateways) { CurRemoteMACInfo = mqttInfoRequestResult_Obj.AccountAllGateways.Find((obj) => obj.mac == curRegionMac.GatewayUniqueId); if (CurRemoteMACInfo != null) { break; } } if (CurRemoteMACInfo != null) { CurRemoteMACInfo.LoginAccessToken = MainPage.LoginUser.loginTokenString; CurRemoteMACInfo.clientId = clientId; mqttEncryptKey = CurRemoteMACInfo.isNewBusproGateway ? CurRemoteMACInfo.aesKey : ""; var options1 = new MQTTnet.Client.Options.MqttClientOptionsBuilder() .WithClientId(clientId) .WithTcpServer(url.Split(':')[1].Substring("//".Length), int.Parse(url.Split(':')[2])) .WithCredentials(username, passwordRemote) .WithCleanSession() .WithCommunicationTimeout(new TimeSpan(0, 0, 20)) .Build(); await DisConnectRemoteMqttClient("StartRemoteMqtt"); await RemoteMqttClient.ConnectAsync(options1); remoteIsConnected = true; IsDisConnectingWithSendCatch = false; } } } } catch { } } } catch (Exception e) { } finally { //最终要释放连接状态 remoteMqttIsConnecting = false; } }); } ///// ///// 收到网关上线消息 ///// //static void ReceiveNotifyBusGateWayInfoChange() //{ // var gatewayListUrl = @"https://developer.hdlcontrol.com/Center/Center/GetGatewayPagger"; //App、Buspro软件登录后获取网关列表 http 请求 // var gatewayListRequestPar = new RemoteRequestParameters() { Mac = CurRemoteMACInfo.mac, LoginAccessToken = MainPage.LoginUser.loginTokenString, RequestVersion = "RequestVersion1", RequestProtocolType = 0, RequestSource = 1 }; // var gatewayListRequestResult = MainPage.RequestHttps("", Newtonsoft.Json.JsonConvert.SerializeObject(gatewayListRequestPar), false, false, gatewayListUrl); // var gatewayListRequestResult_Obj = Newtonsoft.Json.JsonConvert.DeserializeObject(gatewayListRequestResult.ResponseData.ToString()); // if (gatewayListRequestResult_Obj != null && gatewayListRequestResult_Obj.pageData.Count > 0) // { // CurRemoteMACInfo.aesKey = gatewayListRequestResult_Obj.pageData[0].aesKey; // mqttEncryptKey = CurRemoteMACInfo.isNewBusproGateway ? CurRemoteMACInfo.aesKey : ""; // } //} /// /// 收到挤下线推送 /// static void ReceiveNotifySqueezeAsync(string mMes) { if (mMes == PushSignStr) return;//是自己的登录推送不处理 //断开远程连接 MainPage.IsRemote = false; if (!MainPage.LoginUser.IsLogin) { return; } MainPage.LoginUser.lastTime = DateTime.MinValue; MainPage.LoginUser.SaveUserInfo(); string oldRegionRootPath = FileUtils.CreateRegionBackup(DB_ResidenceData.residenceData.CurReginID.ToString()); new System.Threading.Thread(() => { try { var backuplist = FileUtils.ReadFiles(); FileUtils.DeleteRegionFiles(oldRegionRootPath); //移动文件 foreach (var fileName in backuplist) { System.IO.FileInfo fileInfo = new System.IO.FileInfo(FileUtils.RootPath + fileName); if (fileName == "headImage.png") { continue; } if (fileInfo.Exists) { fileInfo.MoveTo(oldRegionRootPath + fileName); MainPage.Log("move file : " + fileName); } } //删除本地文件 foreach (var fileName in backuplist) { if (fileName == "headImage.png") { continue; } FileUtils.DeleteFile(fileName); } } catch (Exception ex) { MainPage.Log(ex.Message); } finally { } }) { IsBackground = true }.Start(); //删除推送数据 DisConnectRemoteMqttClient("挤下线"); Application.RunOnMainThread(() => { MainPage.GoLoginPage(MainPage.LoginUser); }); } /// /// 收到CheckGateway主题 /// static void ReceiveCheckGateway(string mMes) { var obj = Newtonsoft.Json.JsonConvert.DeserializeObject(mMes); if (obj == null) { return; } switch (obj.StateCode) { case "HDLUdpDataForwardServerMqttClientNoOnLine": case "NoOnline": case "NetworkAnomaly"://不在线 Application.RunOnMainThread(() => { new HDL_ON.UI.PublicAssmebly().TipMsgAutoClose(Language.StringByID(StringId.RemoteFailedGatewayOffline), true); }); break; case "NoRecord"://MAC不正确 Application.RunOnMainThread(() => { new HDL_ON.UI.PublicAssmebly().TipMsgAutoClose(Language.StringByID(StringId.MACError), true); }); break; case "Success": break; default: Application.RunOnMainThread(() => { new HDL_ON.UI.PublicAssmebly().TipMsgAutoClose(Language.StringByID(StringId.LinkLoser), true); }); break; } } /// /// /// /// 附加数据包 /// 操作类型:0=网关控制;1=订阅网关数据;2=订阅网关上线数据 /// public static async Task MqttRemoteSend(byte[] message, int optionType = 0) { try { string topicName; switch (optionType) { case 0: topicName = $"/ClientToBusGateWay/{CurRemoteMACInfo.macMark}/Common/ON"; if (!string.IsNullOrEmpty(mqttEncryptKey)) { message = Shared.Securitys.EncryptionService.AesEncryptPayload(message, mqttEncryptKey); } await RemoteMqttClient.PublishAsync(new MqttApplicationMessage { Topic = topicName, Payload = message, Retain = false, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce }); break; case 3: topicName = $"/ClientToBusGateWay/{CurRemoteMACInfo.macMark}/Common/CheckGateway"; Console.WriteLine("CheckGateway"); await RemoteMqttClient.PublishAsync(new MqttApplicationMessage { Topic = topicName, Retain = false, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce }); break; } } catch (Exception e) { //System.Console.WriteLine ($"============>Mqtt MqttRemoteSend catch"); if (!IsDisConnectingWithSendCatch) { IsDisConnectingWithSendCatch = true; await DisConnectRemoteMqttClient("SendCatch"); } } } /// /// SendCatch 后执行一次断开操作 /// static bool IsDisConnectingWithSendCatch = false; } }