Crabtree/SmartHome/UI/SimpleControl/MqttCommon.cs
@@ -20,6 +20,7 @@
        static string mqttEncryptKey = "";
        static string checkGatewayTopicBase64 = "";
        static RemoteMACInfo CurRemoteMACInfo = null;
        static MqttInfo mMqttInfo = null;
        /// <summary>
        /// 手机标识
@@ -37,8 +38,77 @@
        /// </summary>
        public static IMqttClient RemoteMqttClient = new MqttFactory ().CreateMqttClient ();
        static bool thisShowTip = true;
        static string mqttRequestParToken="";
        //static bool thisShowTip = true;
        static string mqttRequestParToken = "";
        static MqttCommon ()
        {
            InitMqtt ();
        }
        /// <summary>
        /// 保活重连和重订阅 线程
        /// </summary>
        /// <returns></returns>
        public static async System.Threading.Tasks.Task InitMqtt ()
        {
            new System.Threading.Thread (async () => {
                while (true) {
                    System.Threading.Thread.Sleep (100);
                    if (!CommonPage.IsRemote) continue;
                    await StartCloudMqtt ();
                    await CheckingSubscribeTopics ();
                }
            }) { IsBackground = true }.Start ();
        }
        /// <summary>
        /// 是否订阅成功
        /// </summary>
        static bool isSubscribeTopicSuccess = false;
        /// <summary>
        /// 检查主题是否订阅失败
        /// </summary>
        /// <returns></returns>
        static async Task CheckingSubscribeTopics ()
        {
            if (!remoteIsConnected) {
                return;
            }
            try {
                if (!isSubscribeTopicSuccess) {
                    var topicFilterCommon = new TopicFilter () {
                        Topic = $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/Common/#",
                        QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce
                    };
                    //网关重新登录主题
                    var topicFilterGateWayInfoChange = new TopicFilter () {
                        Topic = $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/NotifyBusGateWayInfoChange",
                        QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce
                    };
                    //挤下线主题
                    var topicFilterNotifySqueeze = new TopicFilter () {
                        Topic = $"/BusGateWayToClient/{mMqttInfo.connEmqClientId}/Push/NotifySqueeze",
                        QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce
                    };
                    var topicFilters = new TopicFilter [] { topicFilterCommon, topicFilterGateWayInfoChange, topicFilterNotifySqueeze };
                    var result = await RemoteMqttClient.SubscribeAsync (topicFilters);
                    if (result.Items [0].ResultCode == MQTTnet.Client.Subscribing.MqttClientSubscribeResultCode.GrantedQoS2) {
                        isSubscribeTopicSuccess = true;
                    }
                }
            } catch (Exception e) {
            }
        }
        /// <summary>
        /// 断开远程Mqtt的链接
@@ -48,15 +118,25 @@
            try {
                if (remoteIsConnected) {
                    remoteIsConnected = false;
                    System.Console.WriteLine ($"Remote主动断开_{s}");
                    System.Console.WriteLine ($"============>MqttRemote主动断开_{s}");
                    //await RemoteMqttClient.DisconnectAsync(new MQTTnet.Client.Disconnecting.MqttClientDisconnectOptions { }, CancellationToken.None);
                    await RemoteMqttClient.DisconnectAsync ();
                }
            } catch (Exception e) {
                System.Console.WriteLine ($"Remote断开通讯连接出异常:{e.Message}");
                System.Console.WriteLine ($"============>MqttRemote断开通讯连接出异常:{e.Message}");
            }
        }
        static DateTime dateTime = DateTime.MinValue;
        /// <summary>
        /// 推送标识
        /// </summary>
        static string PushSignStr = System.DateTime.Now.Ticks.ToString ();
        /// <summary>
        /// 外网的MQTT是否正在连接
        /// </summary>
@@ -68,301 +148,241 @@
        public static async System.Threading.Tasks.Task StartCloudMqtt ()
        {
                //Application.RunOnMainThread (() => {
                //    if (5 < (DateTime.Now - dateTime).TotalSeconds) {
                //        return;
                //    }
                //    //MainPage.Loading.Start (Language.StringByID (Shared.SimpleControl.R.MyInternationalizationString.Connecting));
                //    dateTime = DateTime.Now;
                //});
                if (!MainPage.LoginUser.IsLogin) {
                    return;
                }
                //追加:没有远程连接的权限
                if (remoteMqttIsConnecting
                   || remoteIsConnected) {
                    return;
                }
            if (!MainPage.LoginUser.IsLogin) {
                return;
            }
            //追加:没有远程连接的权限
            if (remoteMqttIsConnecting || remoteIsConnected) {
                return;
            }
                await System.Threading.Tasks.Task.Factory.StartNew (async () =>
                {
                    try {
                        lock (RemoteMqttClient) {
                            //表示后面将进行连接
                            remoteMqttIsConnecting = true;
            remoteMqttIsConnecting = true;
            await System.Threading.Tasks.Task.Factory.StartNew (async () => {
                try {
                    //lock (RemoteMqttClient) {
                        //表示后面将进行连接
                            #region 初始化远程Mqtt
                            //(3)当[连接云端的Mqtt成功后]或者[以及后面App通过云端Mqtt转发数据给网关成功后],处理接收到云端数据包响应时在mqttServerClient_ApplicationMessageReceived这个方法处理
                            if (RemoteMqttClient.ApplicationMessageReceivedHandler == null) {
                                RemoteMqttClient.UseApplicationMessageReceivedHandler ((e) => {
                                    try {
                                        if (!RemoteMqttClient.IsConnected || !CommonPage.IsRemote) {
                        #region 初始化远程Mqtt
                        //(3)当[连接云端的Mqtt成功后]或者[以及后面App通过云端Mqtt转发数据给网关成功后],处理接收到云端数据包响应时在mqttServerClient_ApplicationMessageReceived这个方法处理
                        if (RemoteMqttClient.ApplicationMessageReceivedHandler == null) {
                            RemoteMqttClient.UseApplicationMessageReceivedHandler (async (e) => {
                                try {
                                    if (!RemoteMqttClient.IsConnected || !CommonPage.IsRemote) {
                                        return;
                                    }
                                    var aesDecryptTopic = e.ApplicationMessage.Topic;
                                    var aesDecryptPayload = e.ApplicationMessage.Payload;
                                    //Console.WriteLine ("Topic={0}", aesDecryptTopic);
                                    //if (aesDecryptTopic == $"NotifyBusGateWayInfoChagne/{CurRemoteMACInfo.md5_mac_string}") {//网关上线,需要更新aeskey
                                    //2020-01-11 修改订阅主题地址
                                    if (aesDecryptTopic == $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/NotifyBusGateWayInfoChange") {//网关上线,需要更新aeskey                                                                                                                     //----第二步:读取账号下面的网关列表
                                        await ReceiveNotifyBusGateWayInfoChange ();
                                    } else if (aesDecryptTopic == $"/BusGateWayToClient/{mMqttInfo.connEmqClientId}/Push/NotifySqueeze") {//订阅挤下线问题
                                        await ReceiveNotifySqueezeAsync (aesDecryptPayload);
                                    }else if (aesDecryptTopic == $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/Common/CheckGateway") {
                                        MainPage.WiFiStatus = "CrabtreeAdd/CloudUnlink.png";
                                        // = $"/ClientToBusGateWay/{CurRemoteMACInfo.macMark}/Common/OldON";
                                        var ss = CommonPage.MyEncodingUTF8.GetString (aesDecryptPayload);
                                        var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponsePack> (ss);
                                        if (obj == null) {
                                            return;
                                        }
                                        var aesDecryptTopic = e.ApplicationMessage.Topic;
                                        var aesDecryptPayload = e.ApplicationMessage.Payload;
                                        //Console.WriteLine ("Topic={0}", aesDecryptTopic);
                                        //if (aesDecryptTopic == $"NotifyBusGateWayInfoChagne/{CurRemoteMACInfo.md5_mac_string}") {//网关上线,需要更新aeskey
                                        //2020-01-11 修改订阅主题地址
                                        if (aesDecryptTopic == $"BusGateWayToClient/{CurRemoteMACInfo.macMark}/NotifyBusGateWayInfoChange") {//网关上线,需要更新aeskey
                                            Console.WriteLine ("网关上线,需要更新aeskey");
                                            //----第二步:读取账号下面的网关列表
                                            var gatewayListUrl = $"{MainPage.RequestHttpsHostMqtt}/Center/Center/GetGatewayPagger"; //App、Buspro软件登录后获取网关列表 http 请求
                                            var gatewayListRequestPar = new RemoteRequestParameters () { Mac = CurRemoteMACInfo.mac, LoginAccessToken = mqttRequestParToken, RequestVersion = "RequestVersion1", RequestProtocolType = 0, RequestSource = 1 };
                                            var gatewayListRequestResult = MainPage.RequestHttps ("", Newtonsoft.Json.JsonConvert.SerializeObject (gatewayListRequestPar),gatewayListUrl);
                                            var gatewayListRequestResult_Obj = Newtonsoft.Json.JsonConvert.DeserializeObject<MqttRemoteInfo> (gatewayListRequestResult.ResponseData.ToString ());
                                            if (gatewayListRequestResult_Obj != null && gatewayListRequestResult_Obj.pageData.Count > 0) {
                                                CurRemoteMACInfo.aesKey = gatewayListRequestResult_Obj.pageData [0].aesKey;
                                                mqttEncryptKey = CurRemoteMACInfo.aesKey;
                                            }
                                        }
                                        if (aesDecryptTopic == $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/Common/CheckGateway") {
                                            MainPage.WiFiStatus = "CrabtreeAdd/CloudUnlink.png";
                                            // = $"/ClientToBusGateWay/{CurRemoteMACInfo.macMark}/Common/OldON";
                                            var ss = CommonPage.MyEncodingUTF8.GetString (aesDecryptPayload);
                                            var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponsePack> (ss);
                                            if (obj == null) {
                                                return;
                                            }
                                            switch (obj.StateCode) {
                                            case "HDLUdpDataForwardServerMqttClientNoOnLine":
                                            case "NoOnline":
                                            case "NetworkAnomaly"://不在线
                                                MainPage.AddTip ("Gateway offline");
                                                //Application.RunOnMainThread (() => {
                                                //    Shared.SimpleControl.Phone.UserMiddle.LinkStatusTip.BackgroundColor = SkinStyle.Current.DelColor;
                                                //});
                                                break;
                                            case "NoRecord"://MAC不正确
                                                MainPage.AddTip (Language.StringByID (Shared.SimpleControl.R.MyInternationalizationString.MACError));
                                                //Application.RunOnMainThread (() => {
                                                //    Shared.SimpleControl.Phone.UserMiddle.LinkStatusTip.BackgroundColor = SkinStyle.Current.DelColor;
                                                //});
                                                break;
                                            case "Success":
                                                MainPage.AddTip (UserConfig.Instance.CurrentRegion.Name + ":" + Language.StringByID (Shared.SimpleControl.R.MyInternationalizationString.LinkSuccess));
                                                MainPage.WiFiStatus = "CrabtreeAdd/CloudLink.png";
                                                break;
                                            default:
                                                MainPage.AddTip (Language.StringByID (Shared.SimpleControl.R.MyInternationalizationString.LinkLoser));
                                                //Application.RunOnMainThread (() => {
                                                //    Shared.SimpleControl.Phone.UserMiddle.LinkStatusTip.BackgroundColor = SkinStyle.Current.DelColor;
                                                //});
                                                break;
                                            }
                                            Application.RunOnMainThread (() => {
                                                UserMiddle.btnLinkStatus.UnSelectedImagePath = MainPage.WiFiStatus;
                                            });
                                        } else {
                                            if (!string.IsNullOrEmpty (mqttEncryptKey)) {
                                                aesDecryptPayload = Shared.Securitys.EncryptionService.AesDecryptPayload (e.ApplicationMessage.Payload, mqttEncryptKey);
                                            }
                                        }
                                        var packet = new Packet ();
                                        packet.Bytes = aesDecryptPayload;
                                        packet.Manager ();
                                    } catch { }
                                });
                            }
                            if (RemoteMqttClient.DisconnectedHandler == null) {
                                RemoteMqttClient.UseDisconnectedHandler (async (e) => {
                                    System.Console.WriteLine ($"远程连接断开");
                                    await DisConnectRemoteMqttClient ("StartRemoteMqtt.DisconnectedHandler");
                                    //await StartRemoteMqtt();
                                    if (thisShowTip) {
                                        if (CommonPage.IsRemote) {
                                            Application.RunOnMainThread (() => {
                                                MainPage.Loading.Hide ();
                                                //Shared.SimpleControl.Phone.UserMiddle.LinkStatusTip.BackgroundColor = SkinStyle.Current.DelColor;
                                            });
                                        }
                                    } else {
                                        thisShowTip = true;
                                    }
                                });
                            }
                            if (RemoteMqttClient.ConnectedHandler == null) {
                                RemoteMqttClient.UseConnectedHandler (async (e) => {
                                    //Shared.Application.RunOnMainThread (() => {
                                    //    Shared.SimpleControl.Phone.UserMiddle.LinkStatusTip.BackgroundColor = 0xAA69E64A;
                                    //});
                                    Shared.SimpleControl.Phone.UserMiddle.ReadAllDeviceStatus ();
                                    System.Console.WriteLine ($"远程连接成功");
                                    if (CommonPage.IsRemote) {
                                        Utlis.ShowAppLinkStatus (AppLinkStatus.CloudLink);
                                    }
                                    //MainPage.WiFiStatus = "CrabtreeAdd/CloudLink.png";
                                    //UserMiddle.btnLinkStatus.UnSelectedImagePath = MainPage.WiFiStatus;
                                    if (CurRemoteMACInfo != null) {
                                        if (CurRemoteMACInfo.isValid == "InValid") {
                                            MainPage.AddTip ("Remote failed,gateway offline");
                                            Application.RunOnMainThread (() => {
                                                MainPage.Loading.Hide ();
                                                //Shared.SimpleControl.Phone.UserMiddle.LinkStatusTip.BackgroundColor = SkinStyle.Current.DelColor;
                                            });
                                        } else {
                                            MqttRemoteSend (new byte [] { 0 }, 3);
                                        switch (obj.StateCode) {
                                        case "HDLUdpDataForwardServerMqttClientNoOnLine":
                                        case "NoOnline":
                                        case "NetworkAnomaly"://不在线
                                            MainPage.AddTip ("Gateway offline");
                                            //Application.RunOnMainThread (() => {
                                            //    MainPage.Loading.Hide ();
                                            //    Shared.SimpleControl.Phone.UserMiddle.LinkStatusTip.BackgroundColor = 0xAA69E64A;
                                            //    Shared.SimpleControl.Phone.UserMiddle.ReadAllDeviceStatus ();
                                            //    Shared.SimpleControl.Phone.UserMiddle.LinkStatusTip.BackgroundColor = SkinStyle.Current.DelColor;
                                            //});
                                            //MainPage.AddTip (UserConfig.Instance.CurrentRegion.RegionName + ":" + Language.StringByID (Shared.SimpleControl.R.MyInternationalizationString.LinkSuccess));
                                            break;
                                        case "NoRecord"://MAC不正确
                                            MainPage.AddTip (Language.StringByID (Shared.SimpleControl.R.MyInternationalizationString.MACError));
                                            //Application.RunOnMainThread (() => {
                                            //    Shared.SimpleControl.Phone.UserMiddle.LinkStatusTip.BackgroundColor = SkinStyle.Current.DelColor;
                                            //});
                                            break;
                                        case "Success":
                                            MainPage.AddTip (UserConfig.Instance.CurrentRegion.Name + ":" + Language.StringByID (Shared.SimpleControl.R.MyInternationalizationString.LinkSuccess));
                                            MainPage.WiFiStatus = "CrabtreeAdd/CloudLink.png";
                                            break;
                                        default:
                                            MainPage.AddTip (Language.StringByID (Shared.SimpleControl.R.MyInternationalizationString.LinkLoser));
                                            //Application.RunOnMainThread (() => {
                                            //    Shared.SimpleControl.Phone.UserMiddle.LinkStatusTip.BackgroundColor = SkinStyle.Current.DelColor;
                                            //});
                                            break;
                                        }
                                    }
                                });
                            }
                            #endregion
                        }
                        try {
                            try {
                                //断开后重新链接需要重新登录获取连接的密码
                                var requestObj = new LoginObj () { Account = MainPage.LoginUser.AccountString.ToLower (), Password = MainPage.LoginUser.Password };
                                var requestJson = Newtonsoft.Json.JsonConvert.SerializeObject (requestObj);
                                var tempResult = MainPage.RequestHttps (API.Login, requestJson);
                                if (tempResult == null) {
                                    Application.RunOnMainThread (() => {
                                        MainPage.Loading.Hide ();
                                        //Shared.SimpleControl.Phone.UserMiddle.LinkStatusTip.BackgroundColor = SkinStyle.Current.DelColor;
                                    });
                                    return;
                                }
                                var responsePack = tempResult.ResponseData;
                                var dictrionaryResult = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>> (tempResult.ResponseData.ToString ());
                                var mqttRequestPar = Newtonsoft.Json.JsonConvert.DeserializeObject<UserLoginRes> (tempResult.ResponseData.ToString ());
                                mqttRequestParToken = mqttRequestPar.Token;
                                //还有种情况是同一个ID 有多个设备用这个id连接(会导致中断)
                                //mqttEncryptKey = dictrionaryResult ["HdlOnMqttKey"]?.ToString ();
                                var url = dictrionaryResult ["ConnectMqttBrokerLoadSubDomain"]?.ToString ();
                                var clientId = dictrionaryResult ["ConnectMqttClientId"]?.ToString ();
                                var username = dictrionaryResult ["ConnectMqttBrokerUserName"]?.ToString ();
                                var passwordRemote = dictrionaryResult ["ConnectMqttBrokerPwd"]?.ToString ();
                                if (clientId == null || username == null || passwordRemote == null) {
                                    return;
                                }
                                var requestObj3 = new GetSingleHomeGatewayPaggerObj ();
                                requestObj3.ReqDto.LoginAccessToken = MainPage.LoginUser.LoginTokenString;
                                requestObj3.ReqDto.HomeId = UserConfig.Instance.CurrentRegion.Id;
                                requestObj3.ReqDto.PageSetting.Page = 1;
                                requestObj3.ReqDto.PageSetting.PageSize = 10;
                                string urlHead = MainPage.RequestHttpsHost;
                                if (requestObj3.IsOtherAccountCtrl) {
                                    urlHead = UserConfig.Instance.MasterAccountRequestBaseUrl;
                                    requestObj3.ReqDto.LoginAccessToken = UserConfig.Instance.MasterAccountToken;
                                }
                                //var requestObj3 = new GatewayByRegionListObj () { RegionID = UserConfig.Instance.CurrentRegion.Id };
                                var requestJson3 = Newtonsoft.Json.JsonConvert.SerializeObject (requestObj3);
                                var revertObj3 = MainPage.RequestHttps (API.GetSingleHomeGatewayPagger, requestJson3, urlHead);
                                if (revertObj3.StateCode.ToUpper() == "SUCCESS") {
                                    var infoResult = Newtonsoft.Json.JsonConvert.DeserializeObject<GetGatewayResult> (revertObj3.ResponseData.ToString ());
                                    //2020-01-11
                                    UserConfig.Instance.SetNowHomeGateways (infoResult.PageData);
                                } else {
                                    //提示错误
                                    //GetSingleHomeGatewayPagger
                                }
                                if (tempResult == null) {
                                    Application.RunOnMainThread (() => {
                                        MainPage.Loading.Hide ();
                                        //Shared.SimpleControl.Phone.UserMiddle.LinkStatusTip.BackgroundColor = SkinStyle.Current.DelColor;
                                    });
                                    return;
                                }
                                try {
                                    //--第一步:获取mqtt链接参数
                                    var mqttInfoUrl = $"{MainPage.RequestHttpsHostMqtt}/Center/Center/GetConnMqttInfo";//获取连接远程云端Emq Mqtt 服务器连接信息
                                    var mqttInfoRequestPar = new RemoteRequestParameters () { LoginAccessToken = mqttRequestParToken, RequestVersion = MainPage.RequestVersion, RequestProtocolType = 0, RequestSource = 1 };
                                    var mqttInfoRequestResult = MainPage.RequestHttps ("", Newtonsoft.Json.JsonConvert.SerializeObject (mqttInfoRequestPar), mqttInfoUrl);
                                    if (mqttInfoRequestResult != null && mqttInfoRequestResult.ResponseData != null) {
                                        var mqttInfoRequestResult_Obj = Newtonsoft.Json.JsonConvert.DeserializeObject<MqttInfo> (mqttInfoRequestResult.ResponseData.ToString ());
                                        if (mqttInfoRequestResult_Obj != null) {
                                            url = mqttInfoRequestResult_Obj.connEmqDomainPort;
                                            clientId = mqttInfoRequestResult_Obj.connEmqClientId;
                                            username = mqttInfoRequestResult_Obj.connEmqUserName;
                                            passwordRemote = mqttInfoRequestResult_Obj.connEmqPwd;
                                            //----第二步:读取账号下面的网关列表
                                            var gatewayListUrl = $"{MainPage.RequestHttpsHostMqtt}/Center/Center/GetGatewayPagger"; //App、Buspro软件登录后获取网关列表 http 请求
                                            var gatewayListRequestPar = new RemoteRequestParameters () { LoginAccessToken = mqttRequestParToken, RequestVersion = "RequestVersion1", RequestProtocolType = 0, RequestSource = 1 };
                                            var gatewayListRequestResult = MainPage.RequestHttps ("", Newtonsoft.Json.JsonConvert.SerializeObject (gatewayListRequestPar), gatewayListUrl);
                                            var gatewayListRequestResult_Obj = Newtonsoft.Json.JsonConvert.DeserializeObject<MqttRemoteInfo> (gatewayListRequestResult.ResponseData.ToString ());
                                            //--找出是否存在匹配当前住宅的mac,存在再进行远程。
                                            if (UserConfig.Instance.CheckHomeGateways ()) {
                                                CurRemoteMACInfo = gatewayListRequestResult_Obj.pageData.Find ((obj) => obj.mac == UserConfig.Instance.CurrentRegion.HomeGateways[0].GatewayUniqueId);
                                                CurRemoteMACInfo = gatewayListRequestResult_Obj.pageData [0];
                                                if (CurRemoteMACInfo != null) {
                                                    CurRemoteMACInfo.LoginAccessToken = mqttRequestPar.Token;
                                                    mqttEncryptKey = 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;
                                                    await MqttRemoteSend (new byte [] { 0 }, 1);
                                                    await MqttRemoteSend (new byte [] { 0 }, 2);
                                                }
                                            }
                                        Application.RunOnMainThread (() => {
                                            UserMiddle.btnLinkStatus.UnSelectedImagePath = MainPage.WiFiStatus;
                                        });
                                    } else {
                                        if (!string.IsNullOrEmpty (mqttEncryptKey)) {
                                            aesDecryptPayload = Shared.Securitys.EncryptionService.AesDecryptPayload (e.ApplicationMessage.Payload, mqttEncryptKey);
                                        }
                                    }
                                } catch (Exception ex) {
                                    Console.WriteLine (ex.Message);
                                }
                            } catch (Exception ex) {
                                System.Console.WriteLine ("============>" + ex.Message);
                                Application.RunOnMainThread (() => {
                                    //MainPage.Loading.Hide ();
                                    //isConnecting = false.ToString ();
                                    //Shared.SimpleControl.Phone.UserMiddle.LinkStatusTip.BackgroundColor = SkinStyle.Current.DelColor;
#if DEBUG
                                Alert a = new Alert (remoteMqttIsConnecting.ToString (), ex.Message, "Close");
                                a.Show ();
#endif
                                });
                            } finally {
                                Application.RunOnMainThread (() => {
                                    MainPage.Loading.Hide ();
                                });
                            }
                        } catch { } finally {
                            //最终要释放连接状态
                            remoteMqttIsConnecting = false;
                                    var packet = new Packet ();
                                    packet.IsLocal = false;
                                    packet.Bytes = aesDecryptPayload;
                                    packet.Manager ();
                                } catch { }
                            });
                        }
                    } catch (Exception ex) {
                        System.Console.WriteLine ($"远程连接通讯连接出异常:{ex.Message}");
                    }
                });
                        if (RemoteMqttClient.DisconnectedHandler == null) {
                            RemoteMqttClient.UseDisconnectedHandler (async (e) => {
                                System.Console.WriteLine ($"============>Mqtt远程连接断开");
                                isSubscribeTopicSuccess = false;
                                await DisConnectRemoteMqttClient ("StartRemoteMqtt.DisconnectedHandler");
                                //await StartRemoteMqtt();
                                //if (thisShowTip) {
                                //    if (CommonPage.IsRemote) {
                                //        Application.RunOnMainThread (() => {
                                //            MainPage.Loading.Hide ();
                                //        });
                                //    }
                                //} else {
                                //    thisShowTip = true;
                                //}
                            });
                        }
                        if (RemoteMqttClient.ConnectedHandler == null) {
                            RemoteMqttClient.UseConnectedHandler (async (e) => {
                                Shared.SimpleControl.Phone.UserMiddle.ReadAllDeviceStatus ();
                                System.Console.WriteLine ($"============>Mqtt远程连接成功");
                                if (CommonPage.IsRemote) {
                                    Utlis.ShowAppLinkStatus (AppLinkStatus.CloudLink);
                                }
                                if (CurRemoteMACInfo != null) {
                                    if (CurRemoteMACInfo.isValid == "InValid") {
                                        MainPage.AddTip ("Remote failed,gateway offline");
                                    } else {
                                        MqttRemoteSend (new byte [] { 0 }, 3);
                                    }
                                }
                            });
                        }
                        #endregion
                    //}
                        mqttRequestParToken = MainPage.LoginUser.LoginTokenString;
                        //--第一步:获取mqtt链接参数
                        var mqttInfoRequestResult = new ResponsePack () { StateCode = "" };
                        //--判断是当前是否分享的住宅
                        if (!UserConfig.Instance.CurrentRegion.IsOthreShare) {
                            var mqttInfoUrl = $"{MainPage.RequestHttpsHost}/EmqMqtt/GetConnMqttInfo";//获取连接远程云端Emq Mqtt 服务器连接信息
                            var mqttInfoRequestPar = new GetConnMqttInfoObj () {
                                LoginAccessToken = mqttRequestParToken,
                                PlatformStr = "L1",
                                PublishPayloadJsonStr = PushSignStr,
                            };
                            mqttInfoRequestResult = MainPage.RequestHttps ("", Newtonsoft.Json.JsonConvert.SerializeObject (mqttInfoRequestPar), mqttInfoUrl);
                            if (mqttInfoRequestResult != null && mqttInfoRequestResult.ResponseData != null) {
                                var mqttInfoRequestResult_info = Newtonsoft.Json.JsonConvert.DeserializeObject<MqttInfo> (mqttInfoRequestResult.ResponseData.ToString ());
                                if (mqttInfoRequestResult_info != null) {
                                    mMqttInfo = mqttInfoRequestResult_info;
                                    //----第二步:读取账号下面的网关列表
                                    var gatewayListUrl = $"{MainPage.RequestHttpsHostMqtt}/Center/Center/GetGatewayPagger"; //App、Buspro软件登录后获取网关列表 http 请求
                                    var gatewayListRequestPar = new RemoteRequestParameters () { LoginAccessToken = mqttRequestParToken, RequestVersion = "RequestVersion1", RequestProtocolType = 0, RequestSource = 1 };
                                    var gatewayListRequestResult = MainPage.RequestHttps ("", Newtonsoft.Json.JsonConvert.SerializeObject (gatewayListRequestPar), gatewayListUrl);
                                    var gatewayListRequestResult_Obj = Newtonsoft.Json.JsonConvert.DeserializeObject<MqttRemoteInfo> (gatewayListRequestResult.ResponseData.ToString ());
                                    //--找出是否存在匹配当前住宅的mac,存在再进行远程。
                                    if (UserConfig.Instance.CheckHomeGatewaysNotEmpty ()) {
                                        CurRemoteMACInfo = gatewayListRequestResult_Obj.pageData.Find ((obj) => obj.mac == UserConfig.Instance.CurrentRegion.HomeGateways [0].GatewayUniqueId);
                                        //CurRemoteMACInfo = gatewayListRequestResult_Obj.pageData [0];
                                        await MQTTConnectAsync ();
                                    } else {
                                        System.Console.WriteLine ("============>Mqtt 取消连接,当前住宅没绑定网关");
                                    }
                                }
                            }
                        } else {
                            //如果是分享过来的住宅 走下面流程
                            var mqttInfoRequestPar = new ShareMemberConnMqttInfoObj () {
                                LoginAccessToken = mqttRequestParToken,
                                PlatformStr = "L1",
                                PublishPayloadJsonStr = PushSignStr,
                                MainUserDistributedMark = UserConfig.Instance.CurrentRegion.MainUserDistributedMark,
                                HomeId = UserConfig.Instance.CurrentRegion.Id
                            };
                            mqttInfoRequestResult = MainPage.RequestHttps (API.ShareMemberConnMqttInfo, Newtonsoft.Json.JsonConvert.SerializeObject (mqttInfoRequestPar));
                            //--第一步:获取mqtt链接参数
                            if (mqttInfoRequestResult != null && mqttInfoRequestResult.ResponseData != null) {
                                var mqttInfoRequestResult_info = Newtonsoft.Json.JsonConvert.DeserializeObject<MqttInfo> (mqttInfoRequestResult.ResponseData.ToString ());
                                if (mqttInfoRequestResult_info != null) {
                                    mMqttInfo = mqttInfoRequestResult_info;
                                    //--第二步:获取当前住分享宅网关信息并连接MQTT
                                    await GetSingleHomeGatewayPaggerAndMQTTConnectAsync ();
                                }
                            }
                        }
                } catch (Exception ex) {
                    System.Console.WriteLine ($"============>Mqtt 远程连接通讯连接出异常:{ex.Message}");
                } finally {
                    //最终要释放连接状态
                    remoteMqttIsConnecting = false;
                }
            });
        }
        /// <summary>
        /// 连接MQTT
        /// </summary>
        static async Task MQTTConnectAsync ()
        {
            if (CurRemoteMACInfo != null && mMqttInfo != null) {
                var url = mMqttInfo.connEmqDomainPort;
                var clientId = mMqttInfo.connEmqClientId;
                var username = mMqttInfo.connEmqUserName;
                var passwordRemote = mMqttInfo.connEmqPwd;
                CurRemoteMACInfo.LoginAccessToken = MainPage.LoginUser.LoginTokenString;
                mqttEncryptKey = 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;
                //await MqttRemoteSend (new byte [] { 0 }, 1);
                //await MqttRemoteSend (new byte [] { 0 }, 2);
                //await MqttRemoteSend (new byte [] { 0 }, 4);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="message">附加数据包</param>
        /// <param name="optionType">操作类型:0=网关控制;1=订阅网关数据;2=订阅网关上线数据</param>
        /// <param name="optionType">操作类型:0=网关控制;1=订阅网关数据;2=订阅网关上线数据;3=订阅网关是否在线主题  4=订阅挤下线主题 </param>
        /// <returns></returns>
        public static async Task MqttRemoteSend (byte [] message, int optionType = 0)
        {
            try {
                if (!remoteIsConnected) {
                    System.Console.WriteLine ($"============>Mqtt 未连接 取消发送");
                    return;
                }
                var topicName = @"/" + MainPage.LoginUser.AccountString.ToLower () + @"/" + UserConfig.Instance.GatewayMAC.Replace (".", "") + @"/" + currentGuid;
                switch (optionType) {
                case 0:
@@ -376,82 +396,189 @@
                    //base64加密
                    var m = new MqttApplicationMessage { Topic = topicName, Payload = messageSend, Retain = false, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce };
                    //if (remoteIsConnected) {
                        try {
                            await RemoteMqttClient.PublishAsync (m);
                        } catch (Exception e) {
                            await DisConnectRemoteMqttClient (e.Message);
                            await StartCloudMqtt ();
                            if (remoteIsConnected) {
                                await RemoteMqttClient.PublishAsync (m);
                            }
                        }
                    //}
                    break;
                case 1:
                    topicName = $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/Common/#";
                    //if (remoteIsConnected) {
                        try {
                            await RemoteMqttClient.SubscribeAsync (topicName);
                        } catch (Exception e) {
                            await DisConnectRemoteMqttClient (e.Message);
                            await StartCloudMqtt ();
                            if (remoteIsConnected) {
                                await RemoteMqttClient.SubscribeAsync (topicName);
                            }
                        }
                   // }
                    break;
                case 2:
                    var macStr = CurRemoteMACInfo.mac.ToUpper ();
                    char [] cArrs = macStr.ToCharArray ();
                    Array.Reverse (cArrs);
                    var sss = string.Join (string.Empty, cArrs);
                    using (var provider = new MD5CryptoServiceProvider ()) {
                        byte [] buffer = provider.ComputeHash (Encoding.Default.GetBytes (sss));
                        StringBuilder builder = new StringBuilder ();
                        for (int i = 0; i < buffer.Length; i++) {
                            builder.Append (buffer [i].ToString ("x2"));
                        }
                        CurRemoteMACInfo.md5_mac_string = builder.ToString ().ToUpper ();
                    }
                    //topicName = $"/NotifyBusGateWayInfoChagne/{CurRemoteMACInfo.md5_mac_string}";
                    //2020-01-11 修改订阅主题地址
                    topicName = $"BusGateWayToClient/{CurRemoteMACInfo.macMark}/NotifyBusGateWayInfoChange";
                    //if (remoteIsConnected) {
                    try {
                            await RemoteMqttClient.SubscribeAsync (topicName);
                        } catch (Exception e) {
                            await DisConnectRemoteMqttClient (e.Message);
                            await StartCloudMqtt ();
                            if (remoteIsConnected) {
                                await RemoteMqttClient.SubscribeAsync (topicName);
                            }
                        }
                         RemoteMqttClient.PublishAsync (m);
                    } catch (Exception e) {
                        //await DisConnectRemoteMqttClient (e.Message);
                        //await StartCloudMqtt ();
                        //if (remoteIsConnected) {
                        //    RemoteMqttClient.PublishAsync (m);
                        //}
                    }
                    //}
                    break;
                case 3:
                    topicName = $"/ClientToBusGateWay/{CurRemoteMACInfo.macMark}/Common/CheckGateway";
                    var m1 = new MqttApplicationMessage { Topic = topicName, Retain = false, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce };
                    try {
                        Console.WriteLine ("CheckGateway");
                        await RemoteMqttClient.PublishAsync (m1);
                         RemoteMqttClient.PublishAsync (m1);
                    } catch (Exception e) {
                        Console.WriteLine ($"CheckGateway Fail:{e.Message}");
                        await DisConnectRemoteMqttClient (e.Message);
                        await StartCloudMqtt ();
                        //await DisConnectRemoteMqttClient (e.Message);
                        //await StartCloudMqtt ();
                    }
                    break;
                }
            } catch (Exception e) {
            }
        }
        /// <summary>
        /// 分享住宅 获取当前住宅网关信息并且连接MQTT 或者刷新
        /// 2020-01-11
        /// </summary>
        static async Task GetSingleHomeGatewayPaggerAndMQTTConnectAsync (bool bNeedConnect = true)
        {
            var requestObj3 = new GetSingleHomeGatewayPaggerObj ();
            requestObj3.ReqDto.LoginAccessToken = MainPage.LoginUser.LoginTokenString;
            requestObj3.ReqDto.HomeId = UserConfig.Instance.CurrentRegion.Id;
            requestObj3.ReqDto.PageSetting.Page = 1;
            requestObj3.ReqDto.PageSetting.PageSize = 10;
            string urlHead = MainPage.RequestHttpsHost;
            if (requestObj3.IsOtherAccountCtrl) {
                urlHead = UserConfig.Instance.MasterAccountRequestBaseUrl;
                requestObj3.ReqDto.LoginAccessToken = UserConfig.Instance.MasterAccountToken;
            }
            var requestJson3 = Newtonsoft.Json.JsonConvert.SerializeObject (requestObj3);
            var revertObj3 = MainPage.RequestHttps (API.GetSingleHomeGatewayPagger, requestJson3, urlHead);
            if (revertObj3.StateCode.ToUpper () == "SUCCESS") {
                var infoResult = Newtonsoft.Json.JsonConvert.DeserializeObject<GetGatewayResult> (revertObj3.ResponseData.ToString ());
                if (bNeedConnect) {
                    //2020-01-11
                    UserConfig.Instance.SetNowHomeGateways (infoResult.PageData);
                    //var gatewayListRequestResult_Obj = Newtonsoft.Json.JsonConvert.DeserializeObject<MqttRemoteInfo> (revertObj3.ResponseData.ToString ());
                    //--找出是否存在匹配当前住宅的mac,存在再进行远程。
                    if (UserConfig.Instance.CheckHomeGatewaysNotEmpty ()) {
                        var mGatewayRes = infoResult.PageData.Find ((obj) => obj.GatewayUniqueId == UserConfig.Instance.CurrentRegion.HomeGateways [0].GatewayUniqueId);
                        if (mGatewayRes != null) {
                            CurRemoteMACInfo = new RemoteMACInfo ();
                            CurRemoteMACInfo.aesKey = mGatewayRes.AesKey;
                            CurRemoteMACInfo.mac = mGatewayRes.GatewayUniqueId;
                            CurRemoteMACInfo.macMark = mGatewayRes.MacMark;
                            CurRemoteMACInfo.isValid = mGatewayRes.MqttOnlineStatus ? "Valid" : "InValid";
                            await MQTTConnectAsync ();
                        }
                    } else {
                        System.Console.WriteLine ("============>Mqtt 取消连接,当前住宅没绑定网关");
                    }
                } else {
                    var mGatewayRes = infoResult.PageData.Find ((obj) => obj.GatewayUniqueId == UserConfig.Instance.CurrentRegion.HomeGateways [0].GatewayUniqueId);
                    if (mGatewayRes != null) {
                        CurRemoteMACInfo.aesKey = mGatewayRes.AesKey;
                        mqttEncryptKey = CurRemoteMACInfo.aesKey;
                    }
                }
            }
        }
        /// <summary>
        /// 收到网关上线消息
        /// </summary>
        static async Task ReceiveNotifyBusGateWayInfoChange ()
        {
            //当前住宅不是分享来
            if (!UserConfig.Instance.CurrentRegion.IsOthreShare) {
                var gatewayListUrl = $"{MainPage.RequestHttpsHostMqtt}/Center/Center/GetGatewayPagger"; //App、Buspro软件登录后获取网关列表 http 请求
                var gatewayListRequestPar = new RemoteRequestParameters () { Mac = CurRemoteMACInfo.mac, LoginAccessToken = mqttRequestParToken, RequestVersion = "RequestVersion1", RequestProtocolType = 0, RequestSource = 1 };
                var gatewayListRequestResult = MainPage.RequestHttps ("", Newtonsoft.Json.JsonConvert.SerializeObject (gatewayListRequestPar), gatewayListUrl);
                var gatewayListRequestResult_Obj = Newtonsoft.Json.JsonConvert.DeserializeObject<MqttRemoteInfo> (gatewayListRequestResult.ResponseData.ToString ());
                if (gatewayListRequestResult_Obj != null && gatewayListRequestResult_Obj.pageData.Count > 0) {
                    var mData = gatewayListRequestResult_Obj.pageData.Find ((obj) => obj.mac == UserConfig.Instance.CurrentRegion.HomeGateways [0].GatewayUniqueId);
                    if (mData != null) {
                        CurRemoteMACInfo.aesKey = mData.aesKey;
                        mqttEncryptKey = CurRemoteMACInfo.aesKey;
                    }
                }
            } else {
                GetSingleHomeGatewayPaggerAndMQTTConnectAsync (false);
            }
        }
        /// <summary>
        /// 收到挤下线推送
        /// </summary>
        static async Task ReceiveNotifySqueezeAsync (byte [] mes)
        {
            Console.WriteLine ($"============>MqttNotifySqueeze: {ErrorCode.LoginInAnotherDevice}");
            var mMes = CommonPage.MyEncodingUTF8.GetString (mes);
            if (mMes == PushSignStr) return;//是自己的登录推送不处理
            CommonPage.IsRemote = false;
            //if (MainPage.IsOtherDevicesLogin) return;
            if (!MainPage.LoginUser.IsLogin) {
                return;
            }
            MainPage.LoginUser.LastTime = DateTime.Now.AddDays (-30);
            MainPage.LoginUser.SaveUserInfo ();
            DisConnectRemoteMqttClient ("挤下线");
            MainPage.ShowAlertOnMainThread (ErrorCode.LoginInAnotherDevice);
            Application.RunOnMainThread (() => {
                MainPage.WiFiStatus = "CrabtreeAdd/WiFi.png";
                UserMiddle.btnLinkStatus.UnSelectedImagePath = MainPage.WiFiStatus;
                new AccountLogin ().Show ();
            });
        }
    }
}
public class ShareMemberConnMqttInfoObj : GetConnMqttInfoObj
{
    /// <summary>
    /// 主人用户Id
    /// </summary>
    public string MainUserDistributedMark;
    /// <summary>
    /// 分享者住宅Id
    /// </summary>
    public string HomeId;
}
public class GetConnMqttInfoObj : BaseRequestObj
{
    /// <summary>
    /// HdlGatewayGatewayType 网关类型(0:一端口、1:BusproLinux 网关、2:Zigbee 网关、3:Knx网关)
    /// </summary>
    public int HdlGatewayGatewayType = 0;
    /// <summary>
    /// 设备类型字段
    /// </summary>
    public string PlatformStr = "";
    /// <summary>
    ///
    /// </summary>
    public string PublishPayloadJsonStr = "";
}
public class RemoteRequestParameters
@@ -461,8 +588,10 @@
    public string LoginAccessToken;
    public int RequestProtocolType;
    public string Mac = "";
    public string GroupName = "";
}
public class MqttRemoteInfo