wxr
2020-06-08 b71dfb3ca100340005d56e1298292807da82322d
HDL_ON/DAL/Net/MqttCommon.cs
@@ -1,331 +1,198 @@
using System.Collections.Generic;
using System;
using MQTTnet.Client;
using System.Threading.Tasks;
using System.Text;
using System.Security.Cryptography;
using MQTTnet;
using MQTTnet.Client.Options;
using System.Net.Sockets;
using System.Threading.Tasks;
//using System.Net;
//using Newtonsoft.Json.Linq;
//using HDL_ON.DAL;
//using Newtonsoft.Json;
namespace HDL_ON.DAL.Net
{
    public static class MqttCommon
    {
        static string mqttEncryptKey = "";
        static string checkGatewayTopicBase64 = "";
        static RemoteMACInfo CurRemoteMACInfo = null;
        /// <summary>
        /// 手机标识
        /// MqttClient
        /// </summary>
        static Guid currentGuid = Guid.NewGuid();
        public static IMqttClient mqttClient_A;
        public static string mqttClientIP;
        public static string mqttGatewayMAC;
        static bool remoteIsConnected;
        /// <summary>
        /// 外网的MQTT是否正在连接
        /// </summary>
        static object isConnecting = false.ToString();
        /// <summary>
        /// 远程MqttClient
        /// </summary>
        public static IMqttClient RemoteMqttClient;
        static bool onConnection = false;
        static bool thisShowTip = true;
        public static async System.Threading.Tasks.Task Close(bool RemoveRemoteMqttClient = false)
        static MqttCommon()
        {
            try
            {
                if (RemoteMqttClient != null)
                {
                    //thisShowTip = true;
                    await RemoteMqttClient.DisconnectAsync();
                }
                if (RemoveRemoteMqttClient)
                {
                    RemoteMqttClient = null;
                }
                CommonPage.IsRemote = false;
            }
            catch { }
            InitMqtt();
        }
        static DateTime dateTime = DateTime.MinValue;
        /// <summary>
        /// 断开远程Mqtt的链接
        /// </summary>
        public static async Task DisConnectRemoteMqttClient(string s = "")
        {
            try
            {
                if (remoteIsConnected)
                {
                    remoteIsConnected = false;
                    System.Console.WriteLine($"Remote主动断开_{s}");
                    //await RemoteMqttClient.DisconnectAsync(new MQTTnet.Client.Disconnecting.MqttClientDisconnectOptions { }, CancellationToken.None);
                    await mqttClient_A.DisconnectAsync();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine($"Remote断开通讯连接出异常:{e.Message}");
            }
        }
        static bool isSubscribeSuccess;
        static async Task SubscribeTopics()
        {
            if (remoteIsConnected && !isSubscribeSuccess)
            {
                try
                {
                    var Topic1 = $"/BusGateWayToApp/{mqttGatewayMAC}/Common/Json";
                    try
                    {
                        await mqttClient_A.SubscribeAsync(Topic1);
                    }
                    catch (Exception ex)
                    {
                        await DisConnectRemoteMqttClient(ex.Message);
                        await StartMqtt();
                        if (remoteIsConnected)
                        {
                            await mqttClient_A.SubscribeAsync(Topic1);
                        }
                    }
                }
                catch { }
            }
        }
        static void InitMqtt()
        {
            new System.Threading.Thread(async () => {
                while (true)
                {
                    try
                    {
                        System.Threading.Thread.Sleep(1000);
                        //if (!CommonPage.IsRemote)
                        //    continue;
                        if (remoteIsConnected)
                            continue;
                        await StartMqtt();
                        await SubscribeTopics();
                    }
                    catch { }
                }
            })
            { IsBackground = true }.Start();
        }
        /// <summary>
        /// 启动远程Mqtt
        /// 启动A协议Mqtt
        /// </summary>
        public static async Task StartCloudMqtt()
        public static async Task StartMqtt()
        {
            /*
            try
            {
                Application.RunOnMainThread(() =>
                {
                    if (5 < (DateTime.Now - dateTime).TotalSeconds)
                    {
                        return;
                    }
                    dateTime = DateTime.Now;
                });
                if (!MainPage.LoginUser.IsLogin)
                {
                    isConnecting = false.ToString();
                if (remoteIsConnected)
                    return;
                }
                while (isConnecting.ToString() == true.ToString())
                if (onConnection)
                    return;
                onConnection = true;
                new System.Threading.Thread(async () =>
                {
                    if (5 < (DateTime.Now - dateTime).TotalSeconds)
                    {
                        break;
                    }
                    await System.Threading.Tasks.Task.Delay(500);
                }
                lock (isConnecting)
                {
                    if (isConnecting.ToString() == true.ToString())
                    {
                    if (remoteIsConnected)
                        return;
                    }
                    isConnecting = true.ToString();
                    if (RemoteMqttClient != null)
                    try
                    {
                        MainPage.Log($"RemoteMqttClient.IsConnected: {RemoteMqttClient.IsConnected}");
                    }
                    //if (RemoteMqttClient != null && RemoteMqttClient.IsConnected) {
                    //    return;
                    //}
                        if (mqttClient_A == null)
                        {
                            mqttClient_A = new MqttFactory().CreateMqttClient();
                            mqttClient_A.UseApplicationMessageReceivedHandler(async e =>
                            {
                                var aesDecryptTopic = e.ApplicationMessage.Topic;
                                var aesDecryptPayload = e.ApplicationMessage.Payload;
                                MainPage.Log(aesDecryptTopic);
                                MainPage.Log($"Des Topic={aesDecryptTopic}");
                            });
                    new System.Threading.Thread(async () =>
                    {
                            mqttClient_A.UseConnectedHandler(async (e) => {
                                MainPage.Log("mqtt connected !!");
                                onConnection = false;
                            });
                        }
                        try
                        {
                            //断开后重新链接需要重新登录获取连接的密码
                            var requestObj = new LoginObj() { Account = MainPage.LoginUser.AccountString.ToLower(), Password = MainPage.LoginUser.Password, Company = 1 };
                            var requestJson = Newtonsoft.Json.JsonConvert.SerializeObject(requestObj);
                            var tempResult = HttpServerRequest.RequestHttps("Login", requestJson, "");
                            if (tempResult == null)
                            int readCount = 0;
                            BusSocket.Stop();
                            System.Threading.Thread.Sleep(1000);
                            BusSocket.Start(6688);
                            System.Threading.Thread.Sleep(1000);
                            Control.ReadGatewayIPAddress();
                            while(true)
                            {
                                //----------
                                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());
                            //还有种情况是同一个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 (RemoteMqttClient == null)
                            {
                                var requestObj3 = new GatewayByRegionListObj() { RegionID = UserConfig.Instance.CurrentRegion.RegionID };
                                MainPage.Log("Remote mqtt get Region MAC : " + UserConfig.Instance.CurrentRegion.RegionID);
                                var requestJson3 = Newtonsoft.Json.JsonConvert.SerializeObject(requestObj3);
                                var revertObj3 = HttpServerRequest.RequestHttps("GatewayByRegionList", requestJson3, true);
                                if (revertObj3.DB_ResidenceData.residenceData.residecenInfo
                                if (!string.IsNullOrEmpty(mqttClientIP))
                                {
                                    var responseDataObj = Newtonsoft.Json.JsonConvert.DeserializeObject<List<GatewayRes>>(revertObj3.ResponseData.ToString());
                                    var gatewayList = responseDataObj;
                                    if (gatewayList != null && gatewayList.Count > 0)
                                    {
                                        UserConfig.Instance.CurrentRegion.MAC = gatewayList[0].MAC;
                                        UserConfig.Instance.SaveUserConfig();
                                        MainPage.Log("Remote mqtt get Region MAC : " + gatewayList[0].MAC);
                                    }
                                    break;
                                }
                                else if (readCount > 10)
                                {
                                    onConnection = false;
                                    return;
                                }
                                else
                                {
                                    MainPage.Log("Remote mqtt get Region MAC Erorr !!");
                                    Control.ReadGatewayIPAddress();
                                    System.Threading.Thread.Sleep(200);
                                }
                                //(2)创建Mqtt客户端
                                RemoteMqttClient = new MqttFactory().CreateMqttClient();
                                //(3)当[连接云端的Mqtt成功后]或者[以及后面App通过云端Mqtt转发数据给网关成功后],处理接收到云端数据包响应时在mqttServerClient_ApplicationMessageReceived这个方法处理
                                RemoteMqttClient.UseApplicationMessageReceivedHandler(async e =>
                                {
                                    if (isConnecting.ToString() == true.ToString())
                                        isConnecting = false.ToString();
                                    var aesDecryptTopic = e.ApplicationMessage.Topic;
                                    var aesDecryptPayload = e.ApplicationMessage.Payload;
                                    MainPage.Log(aesDecryptTopic);
                                    if (aesDecryptTopic == $"NotifyBusGateWayInfoChagne/{CurRemoteMACInfo.md5_mac_string}")
                                    {//网关上线,需要更新aeskey
                                     //----第二步:读取账号下面的网关列表
                                        var gatewayListUrl = @"https://developer.hdlcontrol.com/Center/Center/GetGatewayPagger"; //App、Buspro软件登录后获取网关列表 http 请求
                                        var gatewayListRequestPar = new RemoteRequestParameters() { Mac = CurRemoteMACInfo.mac, LoginAccessToken = mqttRequestPar.Token, RequestVersion = "RequestVersion1", RequestProtocolType = 0, RequestSource = 1 };
                                        var gatewayListRequestResult = HttpServerRequest.RequestHttps("", Newtonsoft.Json.JsonConvert.SerializeObject(gatewayListRequestPar), false, 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 == "YouIpAndPortNoRecord" || aesDecryptTopic == "DecryptFail")
                                    {// -->   你当前的IP及端口在云端不存在,请重新登录连接下!
                                        await Close(true);
                                        //await MqttCheckGateway ();
                                    }
                                    else if (aesDecryptTopic == @"/BeingSqueezedOffline")
                                    {
                                        try
                                        {
                                        }
                                        catch (Exception ex)
                                        {
                                            MainPage.Log(ex.Message);
                                        }
                                        finally
                                        {
                                        }
                                    }
                                    else
                                    {
                                        if (!string.IsNullOrEmpty(mqttEncryptKey))
                                        {
                                            aesDecryptTopic = Shared.Securitys.EncryptionService.AesDecryptTopic(e.ApplicationMessage.Topic, mqttEncryptKey);
                                            aesDecryptPayload = Shared.Securitys.EncryptionService.AesDecryptPayload(e.ApplicationMessage.Payload, mqttEncryptKey);
                                        }
                                        else
                                        {
                                            aesDecryptTopic = e.ApplicationMessage.Topic;
                                            aesDecryptPayload = e.ApplicationMessage.Payload;
                                        }
                                    }
                                    MainPage.Log($"Des Topic={aesDecryptTopic}");
                                    var packet = new Packet();
                                    packet.Bytes = aesDecryptPayload;
                                    packet.Manager();
                                });
                                RemoteMqttClient.UseDisconnectedHandler(e =>
                                {
                                    if (thisShowTip)
                                    {
                                        if (CommonPage.IsRemote)
                                        {
                                            //----------
                                        }
                                    }
                                    else
                                    {
                                        thisShowTip = true;
                                    }
                                });
                                RemoteMqttClient.UseConnectedHandler(async e =>
                                {
                                    if (CurRemoteMACInfo != null)
                                    {
                                        if (CurRemoteMACInfo.isValid == "InValid")
                                        {
                                            //----------
                                        }
                                        else
                                        {
                                            CommonPage.IsRemote = true;
                                            //----------
                                        }
                                    }
                                });
                            }
                            BusSocket.Stop();
                            System.Threading.Thread.Sleep(1000);
                            BusSocket.Start(6000);
                            System.Threading.Thread.Sleep(1000);
                            if (clientId == null || username == null || passwordRemote == null)
                            {
                                return;
                            }
                            if (tempResult == null)
                            {
                                //----------
                                return;
                            }
                            //--第一步:获取mqtt链接参数
                            var mqttInfoUrl = @"https://developer.hdlcontrol.com/Center/Center/GetConnMqttInfo";//获取连接远程云端Emq Mqtt 服务器连接信息
                            var mqttInfoRequestPar = new RemoteRequestParameters() { LoginAccessToken = mqttRequestPar.Token, RequestVersion = "RequestVersion1", RequestProtocolType = 0, RequestSource = 1 };
                            var mqttInfoRequestResult = HttpServerRequest.RequestHttps("", Newtonsoft.Json.JsonConvert.SerializeObject(mqttInfoRequestPar), false, mqttInfoUrl);
                            if (mqttInfoRequestResult != null && mqttInfoRequestResult.ResponseData != null)
                            {
                                try
                                {
                                    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 = @"https://developer.hdlcontrol.com/Center/Center/GetGatewayPagger"; //App、Buspro软件登录后获取网关列表 http 请求
                                        var gatewayListRequestPar = new RemoteRequestParameters() { LoginAccessToken = mqttRequestPar.Token, RequestVersion = "RequestVersion1", RequestProtocolType = 0, RequestSource = 1 };
                                        var gatewayListRequestResult = HttpServerRequest.RequestHttps("", Newtonsoft.Json.JsonConvert.SerializeObject(gatewayListRequestPar), false, gatewayListUrl);
                                        var gatewayListRequestResult_Obj = Newtonsoft.Json.JsonConvert.DeserializeObject<MqttRemoteInfo>(gatewayListRequestResult.ResponseData.ToString());
                                        //--找出是否存在匹配当前住宅的mac,存在再进行远程。
                                        CurRemoteMACInfo = gatewayListRequestResult_Obj.pageData.Find((obj) => obj.mac == UserConfig.Instance.CurrentRegion.MAC);
                                        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, 10))
                                                                .Build();
                                            await Close();
                                            await RemoteMqttClient.ConnectAsync(options1);
                                            await MqttRemoteSend(new byte[] { 0 }, 1);
                                            await MqttRemoteSend(new byte[] { 0 }, 2);
                                        }
                                    }
                                }
                                catch { }
                            }
                            var options = new MqttClientOptionsBuilder()//MQTT连接参数填充
                                .WithClientId(Guid.NewGuid().ToString().Substring(0, 5))//客户端ID
                                .WithTcpServer(mqttClientIP, 1883)//MQTTServerIP.Text, Int32.Parse(MQTTServerPort.Text.ToString()))//TCP服务端  1883  ,即MQTT服务端
                                .WithCredentials("", "")//"", "")//凭证  帐号 密码
                                .WithCommunicationTimeout(new TimeSpan(0, 0, 60)) //重连超时时间,默认5s
                                .WithKeepAlivePeriod(new TimeSpan(0, 0, 15)) //保持连接时间,默认5s,心跳包
                                .Build();
                            await mqttClient_A.ConnectAsync(options);
                            remoteIsConnected = true;
                        }
                        catch (Exception ex)
                        {
                            Application.RunOnMainThread(() =>
                            {
                                if (MqttCommon.RemoteMqttClient != null)
                                {
                                    MqttCommon.RemoteMqttClient.Dispose();
                                }
                                if (MqttCommon.RemoteMqttClient != null)
                                {
                                    MqttCommon.RemoteMqttClient = null;
                                }
                            });
                        }
                        finally
                        {
                            isConnecting = false.ToString();
                            //----------
                        }
                    })
                    { IsBackground = true }.Start();
                }
                        catch { }
                    }
                    catch (Exception ex)
                    {
                    }
                    finally
                    {
                        onConnection = false;
                    }
                })
                { IsBackground = true }.Start();
            }
            catch (Exception ex)
            {
                MainPage.Log("============>" + ex.Message);
            }
            finally
            {
                isConnecting = false.ToString();
            }
    */
        }
        /// <summary>
        /// 
@@ -333,64 +200,24 @@
        /// <param name="message">附加数据包</param>
        /// <param name="optionType">操作类型:0=网关控制;1=订阅网关数据;2=订阅网关上线数据</param>
        /// <returns></returns>
        public static async Task MqttRemoteSend(byte[] message, int optionType = 0)
        public static async Task MqttRemoteSend(byte[] message)
        {
            try
            {
                if (RemoteMqttClient == null || !RemoteMqttClient.IsConnected)
                if (mqttClient_A == null || !mqttClient_A.IsConnected)
                {
                    await StartCloudMqtt();
                    await StartMqtt();
                }
                if (!RemoteMqttClient.IsConnected)
                if (!mqttClient_A.IsConnected)
                {
                    return;
                }
                var topicName = "";//@"/" + MainPage.LoginUser.AccountString.ToLower() + @"/" + currentGuid;//+ @"/" + UserConfig.Instance.CurrentRegion.MAC.Replace(".", "")
                switch (optionType)
                {
                    case 0:
                        if (!string.IsNullOrEmpty(mqttEncryptKey))
                        {
                            topicName = $"/ClientToBusGateWay/{CurRemoteMACInfo.macMark}/Common/OldON";
                        }
                        else
                        {
                            topicName = $"/ClientToBusGateWay/{CurRemoteMACInfo.macMark}/Common/NewON";
                        }
                        //base64加密
                        var messageSend = Shared.Securitys.EncryptionService.AesEncryptPayload(message, mqttEncryptKey);
                        var m = new MqttApplicationMessage { Topic = topicName, Payload = messageSend, Retain = false, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce };
                        await RemoteMqttClient?.PublishAsync(m);
                        break;
                    case 1:
                        topicName = $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/Common/#";
                        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}";
                        await RemoteMqttClient?.SubscribeAsync(topicName);
                        break;
                }
                var topicName = $"/AppToBusGateWay/{mqttGatewayMAC}/Common/Json";
                var m = new MqttApplicationMessage { Topic = topicName, Payload = message, Retain = false, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce };
                await mqttClient_A?.PublishAsync(m);
            }
            catch (Exception e)
            {
                isConnecting = false.ToString();
            }
        }
    }
@@ -567,3 +394,5 @@
    }
}