JLChen
2020-02-24 ac39680a5ace5c02c63369014993fbfc959dbe5f
Crabtree/SmartHome/UI/SimpleControl/MqttCommon.cs
@@ -21,6 +21,7 @@
        static string checkGatewayTopicBase64 = "";
        static RemoteMACInfo CurRemoteMACInfo = null;
        static MqttInfo mMqttInfo = null;
        public static bool IsGatewayOnline = true;
        /// <summary>
        /// 手机标识
@@ -41,6 +42,83 @@
        //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 topicFilterNotifyGateWayOffline = new TopicFilter () {
                        Topic = $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/NotifyGateWayOffline",
                        QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce
                    };
                    var topicFilters = new TopicFilter [] { topicFilterCommon, topicFilterGateWayInfoChange, topicFilterNotifySqueeze, topicFilterNotifyGateWayOffline };
                    var result = await RemoteMqttClient.SubscribeAsync (topicFilters);
                    if (result.Items [0].ResultCode == MQTTnet.Client.Subscribing.MqttClientSubscribeResultCode.GrantedQoS2) {
                        isSubscribeTopicSuccess = true;
                    }
                }
            } catch (Exception e) {
            }
        }
        /// <summary>
        /// 断开远程Mqtt的链接
        /// </summary>
@@ -52,6 +130,10 @@
                    System.Console.WriteLine ($"============>MqttRemote主动断开_{s}");
                    //await RemoteMqttClient.DisconnectAsync(new MQTTnet.Client.Disconnecting.MqttClientDisconnectOptions { }, CancellationToken.None);
                    await RemoteMqttClient.DisconnectAsync ();
                    if (CommonPage.IsRemote) {
                        Utlis.ShowAppLinkStatus (AppLinkStatus.CloudUnlink);
                    }
                }
            } catch (Exception e) {
                System.Console.WriteLine ($"============>MqttRemote断开通讯连接出异常:{e.Message}");
@@ -79,29 +161,19 @@
        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) {
                System.Console.WriteLine ($"============>MqttremoteMqttIsConnecting:{remoteMqttIsConnecting}  remoteIsConnected:{remoteIsConnected} ");
            if (remoteMqttIsConnecting || remoteIsConnected) {
                return;
            }
            remoteMqttIsConnecting = true;
            await System.Threading.Tasks.Task.Factory.StartNew (async () => {
                try {
                    lock (RemoteMqttClient) {
                    //lock (RemoteMqttClient) {
                        //表示后面将进行连接
                        remoteMqttIsConnecting = true;
                        #region 初始化远程Mqtt
                        //(3)当[连接云端的Mqtt成功后]或者[以及后面App通过云端Mqtt转发数据给网关成功后],处理接收到云端数据包响应时在mqttServerClient_ApplicationMessageReceived这个方法处理
@@ -119,6 +191,8 @@
                                    //2020-01-11 修改订阅主题地址
                                    if (aesDecryptTopic == $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/NotifyBusGateWayInfoChange") {//网关上线,需要更新aeskey                                                                                                                     //----第二步:读取账号下面的网关列表
                                        await ReceiveNotifyBusGateWayInfoChange ();
                                    } else if (aesDecryptTopic == $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/NotifyGateWayOffline") {//网关掉线                                                                                                                    //----第二步:读取账号下面的网关列表
                                        ReceiveNotifyGateWayOffline ();
                                    } else if (aesDecryptTopic == $"/BusGateWayToClient/{mMqttInfo.connEmqClientId}/Push/NotifySqueeze") {//订阅挤下线问题
                                        await ReceiveNotifySqueezeAsync (aesDecryptPayload);
                                    }else if (aesDecryptTopic == $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/Common/CheckGateway") {
@@ -175,6 +249,7 @@
                        if (RemoteMqttClient.DisconnectedHandler == null) {
                            RemoteMqttClient.UseDisconnectedHandler (async (e) => {
                                System.Console.WriteLine ($"============>Mqtt远程连接断开");
                                isSubscribeTopicSuccess = false;
                                await DisConnectRemoteMqttClient ("StartRemoteMqtt.DisconnectedHandler");
                                //await StartRemoteMqtt();
                                //if (thisShowTip) {
@@ -190,29 +265,44 @@
                        }
                        if (RemoteMqttClient.ConnectedHandler == null) {
                            RemoteMqttClient.UseConnectedHandler (async (e) => {
                                IfNeedReadAllDeviceStatus = true;
                                Shared.SimpleControl.Phone.UserMiddle.ReadAllDeviceStatus ();
                                System.Console.WriteLine ($"============>Mqtt远程连接成功");
                                if (CommonPage.IsRemote) {
                                    Utlis.ShowAppLinkStatus (AppLinkStatus.CloudLink);
                                }
                                if (CurRemoteMACInfo != null) {
                                    if (CurRemoteMACInfo.isValid == "InValid") {
                                    IsGatewayOnline = CurRemoteMACInfo.isValid != "InValid";
                                    if (!IsGatewayOnline) {
                                        //网关不在线
                                        if (CommonPage.IsRemote) {
                                            Utlis.ShowAppLinkStatus (AppLinkStatus.CloudOffline);
                                        }
                                        MainPage.AddTip ("Remote failed,gateway offline");
                                        //Application.RunOnMainThread (() => {
                                        //    MainPage.Loading.Hide ();
                                        //});
                                    } else {
                                        //网关在线
                                        //重新一次所有设备状态
                                        IfNeedReadAllDeviceStatus = false;
                                        Shared.SimpleControl.Phone.UserMiddle.ReadAllDeviceStatus ();
                                        //
                                        MqttRemoteSend (new byte [] { 0 }, 3);
                                    }
                                    //if (CurRemoteMACInfo.isValid == "InValid") {
                                    //    MainPage.AddTip ("Remote failed,gateway offline");
                                    //} else {
                                    //    MqttRemoteSend (new byte [] { 0 }, 3);
                                    //}
                                }
                            });
                        }
                        #endregion
                    }
                    try {
                    //}
                        mqttRequestParToken = MainPage.LoginUser.LoginTokenString;
                        //--第一步:获取mqtt链接参数
@@ -271,11 +361,6 @@
                            }
                        }
                    } catch (Exception ex) {
                        Console.WriteLine (ex.Message);
                    }
                } catch (Exception ex) {
                    System.Console.WriteLine ($"============>Mqtt 远程连接通讯连接出异常:{ex.Message}");
                } finally {
@@ -310,22 +395,14 @@
                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);
                //await MqttRemoteSend (new byte [] { 0 }, 1);
                //await MqttRemoteSend (new byte [] { 0 }, 2);
                //await MqttRemoteSend (new byte [] { 0 }, 4);
            }
        }
        //public static async System.Threading.Tasks.Task InitMqtt () {
        //    while (true) {
        //        await StartCloudMqtt ();
        //        System.Threading.Thread.Sleep (100);
        //    }
        //}
        /// <summary>
        /// 
        /// </summary>
@@ -335,6 +412,11 @@
        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:
@@ -351,59 +433,14 @@
                    try {
                         RemoteMqttClient.PublishAsync (m);
                    } catch (Exception e) {
                        await DisConnectRemoteMqttClient (e.Message);
                        await StartCloudMqtt ();
                        if (remoteIsConnected) {
                            RemoteMqttClient.PublishAsync (m);
                        }
                        //await DisConnectRemoteMqttClient (e.Message);
                        //await StartCloudMqtt ();
                        //if (remoteIsConnected) {
                        //    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);
                        }
                    }
                    //}
                    break;
                case 3:
                    topicName = $"/ClientToBusGateWay/{CurRemoteMACInfo.macMark}/Common/CheckGateway";
@@ -411,29 +448,12 @@
                    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;
                case 4:
                    //2020-01-13 修改挤下线主题
                    topicName = $"/BusGateWayToClient/{mMqttInfo.connEmqClientId}/Push/NotifySqueeze";
                    //if (remoteIsConnected) {
                    try {
                        await RemoteMqttClient.SubscribeAsync (topicName);
                    } catch (Exception e) {
                        await DisConnectRemoteMqttClient (e.Message);
                        await StartCloudMqtt ();
                        if (remoteIsConnected) {
                            await RemoteMqttClient.SubscribeAsync (topicName);
                        }
                    }
                    //}
                    break;
                }
@@ -502,12 +522,33 @@
           
        }
        /// <summary>
        /// 是否需要读取一次所有设备状态
        /// </summary>
        static bool IfNeedReadAllDeviceStatus = true;
        /// <summary>
        /// 收到网关上线消息
        /// </summary>
        static async Task ReceiveNotifyBusGateWayInfoChange ()
        {
            System.Console.WriteLine ("============>Mqtt 网关上线");
            IsGatewayOnline = true;
            if (CommonPage.IsRemote) {
                if (MainPage.WiFiStatus != "CrabtreeAdd/CloudLink.png") {
                    Utlis.ShowAppLinkStatus (AppLinkStatus.CloudLink);
                }
//#if DEBUG
                MainPage.AddTip ("Gateway login online");
//#endif
                if (IfNeedReadAllDeviceStatus) {
                    IfNeedReadAllDeviceStatus = false;
                    Shared.SimpleControl.Phone.UserMiddle.ReadAllDeviceStatus ();
                }
            }
            //当前住宅不是分享来
            if (!UserConfig.Instance.CurrentRegion.IsOthreShare) {
@@ -527,6 +568,24 @@
            }
        }
        /// <summary>
        /// 收到网关掉线信息
        /// </summary>
        static void ReceiveNotifyGateWayOffline ()
        {
            System.Console.WriteLine ("============>Mqtt GateWayOffline");
            IsGatewayOnline = false;
            if (CommonPage.IsRemote) {
                Utlis.ShowAppLinkStatus (AppLinkStatus.CloudOffline);
                MainPage.AddTip ("Remote failed,gateway offline");
                //if (MainPage.WiFiStatus != "CrabtreeAdd/CloudUnlink.png") {
                //    Utlis.ShowAppLinkStatus (AppLinkStatus.CloudUnlink);
                //}
            }
        }
        /// <summary>
        /// 收到挤下线推送
@@ -549,11 +608,12 @@
            MainPage.LoginUser.LastTime = DateTime.Now.AddDays (-30);
            MainPage.LoginUser.SaveUserInfo ();
            DisConnectRemoteMqttClient ("LoginOut");
            DisConnectRemoteMqttClient ("挤下线");
            MainPage.ShowAlertOnMainThread (ErrorCode.LoginInAnotherDevice);
            Application.RunOnMainThread (() => {
                MainPage.WiFiStatus = "CrabtreeAdd/WiFi.png";
                UserMiddle.btnLinkStatus.UnSelectedImagePath = MainPage.WiFiStatus;
                new AccountLogin ().Show ();