WJC
2019-12-30 f1c3921b08bb22ac6f5db22d620e01d7e8e5c49f
ZigbeeApp/Shared/Phone/ZigBee/Device/ZbGateway.cs
@@ -3090,27 +3090,46 @@
        /// </summary>
        IMqttClient localMqttClient = new MqttFactory().CreateMqttClient();
        bool localMqttIsConnecting;
        public bool localIsConnected;
        /// <summary>
        /// 手机标识
        /// </summary>
        static Guid currentGuid = Guid.NewGuid();
        public async System.Threading.Tasks.Task SendAesKey()
        {
            if (PubKey != null)
            {
                IsEncry = false;
                var rsaString = ZigBee.Common.SecuritySet.RSAEncrypt(PubKey, Password);
                var resultVerityfy = await SendAesKeyAsync(rsaString);
                if (resultVerityfy == null)
                {
                    resultVerityfy = await SendAesKeyAsync(rsaString);
                }
                if (resultVerityfy != null && resultVerityfy.Result == 0)
                {
                    IsEncry = true;
                }
            }
        }
        public async System.Threading.Tasks.Task StartLocalMqtt(string brokerName)
        {
        {
            if (localMqttIsConnecting
                       || !Shared.Common.Config.Instance.IsLogin
                       || Shared.Common.Config.Instance.HomeId == ""
                       || localIsConnected)
            {
                return;
            }
            await System.Threading.Tasks.Task.Factory.StartNew(async () =>
            {
                try
                {
                    lock (localMqttClient)
                    {
                        if (localMqttIsConnecting
                        || !Shared.Common.Config.Instance.IsLogin
                        || Shared.Common.Config.Instance.HomeId == ""
                        || localMqttClient.IsConnected)
                        {
                            return;
                        }
                        //表示后面将进行连接
                        localMqttIsConnecting = true;
@@ -3129,10 +3148,11 @@
                        if (localMqttClient.DisconnectedHandler == null)
                        {
                            localMqttClient.UseDisconnectedHandler((e) =>
                            {
                                IsEncry = false;
                            localMqttClient.UseDisconnectedHandler(async (e) =>
                            {
                                DebugPrintLog($" 本地连接断开_网关IP:{brokerName}_网关是否加:{IsEncry}");
                                await DisConnectLocalMqttClient("StartLocalMqtt.DisconnectedHandler");
                                //await StartLocalMqtt("ReConnect");
                            });
                        }
                        if (localMqttClient.ConnectedHandler == null)
@@ -3141,33 +3161,44 @@
                            {
                                DebugPrintLog($" 本地连接成功_网关IP:{brokerName}_网关是否加:{IsEncry}_当前密码:{Password}");
                                IsRemote = false;
                                if (PubKey != null)
                                {
                                    var rsaString = ZigBee.Common.SecuritySet.RSAEncrypt(PubKey, Password);
                                    var resultVerityfy = await SendAesKeyAsync(rsaString);
                                    if (resultVerityfy == null)
                                    {
                                        resultVerityfy = await SendAesKeyAsync(rsaString);
                                    }
                                    if (resultVerityfy != null && resultVerityfy.Result == 0)
                                    {
                                        IsEncry = true;
                                    }
                                }
                                Shared.Phone.UserCenter.HdlGatewayLogic.Current.CheckGatewayByConnectChanged(Shared.Phone.UserCenter.GatewayConnectMode.WIFI);
                                System.Console.WriteLine($"当前是网关Wi-Fi在通讯_{System.DateTime.Now.ToString()}");
                            });
                        }
                    }
                    var options = new MQTTnet.Client.Options.MqttClientOptionsBuilder()
                                   .WithClientId(currentGuid.ToString())
               .WithTcpServer(brokerName, 1883)
               .WithKeepAlivePeriod(TimeSpan.FromSeconds(20))
               .WithCleanSession()
               .WithCredentials("", "")
               .Build();
                    await localMqttClient.ConnectAsync(options, CancellationToken.None);
                        }
                        var dateTime = DateTime.Now;
                        new System.Threading.Thread(async () =>
                        {
                            try
                            {
                                if (localMqttClient.Options == null)
                                {
                                    var options = new MQTTnet.Client.Options.MqttClientOptionsBuilder().WithClientId(currentGuid.ToString())
                       .WithTcpServer(brokerName, 1883)
                       .WithKeepAlivePeriod(TimeSpan.FromSeconds(20))
                       .WithCleanSession()
                        //.WithCommunicationTimeout(TimeSpan.FromSeconds(10))
                       .WithCredentials("", "")
                       .Build();
                                    await localMqttClient.ConnectAsync(options, CancellationToken.None);
                                }
                                else
                                {
                                    await DisConnectLocalMqttClient("StartLocalMqtt");
                                    await localMqttClient.ReconnectAsync();
                                }
                                localIsConnected = true;
                                await SendAesKey();
                            }
                            catch { }
                            dateTime = DateTime.MinValue;
                        })
                        { IsBackground = true }.Start();
                        while (dateTime != DateTime.MinValue)
                        {
                            System.Threading.Thread.Sleep(100);
                        }
                    }
                }
                catch (Exception ex)
                {
@@ -3279,6 +3310,7 @@
        /// 远程MqttClient
        /// </summary>
        public static IMqttClient RemoteMqttClient= new MqttFactory().CreateMqttClient();
        static bool remoteIsConnected;
        private int IsLogin = 0;
        [Newtonsoft.Json.JsonIgnore]
        static Action actionTemp;
@@ -3288,22 +3320,21 @@
        /// </summary>
        /// <returns>The start.</returns>
        /// <param name="brokerName">Broker name.</param>
        public static async System.Threading.Tasks.Task StartCloudMqtt()
        {
        public static async System.Threading.Tasks.Task StartRemoteMqtt()
        {
            if (remoteMqttIsConnecting
                       || !Shared.Common.Config.Instance.IsLogin
                       || Shared.Common.Config.Instance.HomeId == ""
                       || remoteIsConnected)
            {
                return;
            }
            await System.Threading.Tasks.Task.Factory.StartNew(async () =>
            {
                try
                {
                    lock (RemoteMqttClient)
                    {
                        if (remoteMqttIsConnecting
                        || !Shared.Common.Config.Instance.IsLogin
                        || Shared.Common.Config.Instance.HomeId == ""
                        || RemoteMqttClient.IsConnected)
                        {
                            return;
                        }
                        //表示后面将进行连接
                        remoteMqttIsConnecting = true;
@@ -3323,9 +3354,11 @@
                        if (RemoteMqttClient.DisconnectedHandler == null)
                        {
                            RemoteMqttClient.UseDisconnectedHandler((e) =>
                            RemoteMqttClient.UseDisconnectedHandler(async (e) =>
                            {
                                DebugPrintLog($"远程连接断开");
                                await DisConnectRemoteMqttClient("StartRemoteMqtt.DisconnectedHandler");
                                //await StartRemoteMqtt();
                            });
                        }
                        if (RemoteMqttClient.ConnectedHandler == null)
@@ -3378,21 +3411,35 @@
                    try
                    {
                        var jsonData = new Dictionary<string, object> { ["RequestVersion"] = "RequestVersion", ["RequestSource"] = 0, ["LoginAccessToken"] = Config.Instance.Token, ["RequestProtocolType"] = 0 };
                        var bytes = System.Text.Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(jsonData));
                        var result = await CommonPage.Instance.DoRequestZigbeeHttpsInterface("https://global.hdlcontrol.com/HangZhouHdlCloudApi/EmqMqtt/GetConnMqttInfo", bytes, Config.Instance.Token);
                        //{
                        //"ResponseVersion": "RequestVersion1",
                        //"StateCode": "Success",
                        //"ErrorInfo": null,
                        //"ResponseData": { < !--如下信息只能使用一次,即便你连接失败!-- >
                        //   "ConnEmqDomainPort": "tcp://developer.hdlcontrol.com:1883",
                        //  "ConnEmqClientId": "ZigbeeClientTcp_33094de8-34ba-4e38-93c2-ac8da16d0e68_Zigbee",
                        //  "ConnEmqUserName": "33094de8-34ba-4e38-93c2-ac8da16d0e68",
                        //  "ConnEmqPwd": "4a265b65-d6cc-4a"
                        //}
                        //}
                        byte[] result = null;
                        if (Config.Instance.Home.IsOthreShare == false)
                        {
                            //主人
                            var jsonData = new Dictionary<string, object>
                            {
                                ["RequestVersion"] = CommonPage.RequestVersion,
                                ["RequestSource"] = 0,
                                ["LoginAccessToken"] = Config.Instance.Token,
                                ["RequestProtocolType"] = 0
                            };
                            var bytes = System.Text.Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(jsonData));
                            result = await CommonPage.Instance.DoRequestZigbeeHttpsInterface("https://global.hdlcontrol.com/HangZhouHdlCloudApi/EmqMqtt/GetConnMqttInfo", bytes, Config.Instance.Token);
                        }
                        else
                        {
                            //分享的
                            var jsonData = new Dictionary<string, object>
                            {
                                ["RequestVersion"] = CommonPage.RequestVersion,
                                ["RequestSource"] = 0,
                                ["LoginAccessToken"] = Config.Instance.Token,
                                ["RequestProtocolType"] = 0,
                                ["MainUserDistributedMark"] = Config.Instance.Home.MainUserDistributedMark,
                                ["HomeId"] = Config.Instance.Home.Id
                            };
                            var bytes = System.Text.Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(jsonData));
                            result = await CommonPage.Instance.DoRequestZigbeeHttpsInterface("https://global.hdlcontrol.com/HangZhouHdlCloudApi/EmqMqtt/ShareMemberConnMqttInfo", bytes, Config.Instance.Token);
                        }
                        if (result != null)
                        {
                            var jobject = Newtonsoft.Json.Linq.JObject.Parse(Encoding.UTF8.GetString(result));
@@ -3406,18 +3453,20 @@
                                var connEmqDomainPorts = connEmqDomainPort.Replace("//", "").Split(':');
                                var domain = connEmqDomainPorts[1];
                                var port = connEmqDomainPorts[2];
                                var options = new MQTTnet.Client.Options.MqttClientOptionsBuilder()
                                    .WithClientId(connEmqClientId)
                .WithTcpServer(domain, int.Parse(port))
                .WithCredentials(connEmqUserName, connEmqPwd)
                .WithKeepAlivePeriod(TimeSpan.FromSeconds(20))
                .WithCleanSession()
                .Build();
                                await RemoteMqttClient.ConnectAsync(options);
                                var port = connEmqDomainPorts[2];
                                var options = new MQTTnet.Client.Options.MqttClientOptionsBuilder()
                               .WithClientId(connEmqClientId)
           .WithTcpServer(domain, int.Parse(port))
           .WithCredentials(connEmqUserName, connEmqPwd)
           .WithKeepAlivePeriod(TimeSpan.FromSeconds(20))
           .WithCleanSession()
           //.WithCommunicationTimeout(TimeSpan.FromSeconds(10))
           .Build();
                                await DisConnectRemoteMqttClient("StartRemoteMqtt");
                                await RemoteMqttClient.ConnectAsync(options, CancellationToken.None);
                                remoteIsConnected = true;
                            }
                        }
                    }
@@ -3438,28 +3487,40 @@
        /// <summary>
        /// 断开服务器连接
        /// </summary>
        public async System.Threading.Tasks.Task DisConnect(string s)
        public async System.Threading.Tasks.Task DisConnectLocalMqttClient(string s)
        {
            try
            {
                DebugPrintLog($"主动断开_{s}");
                if (localMqttClient.IsConnected == true)
                if (localIsConnected)
                {
                    await localMqttClient.DisconnectAsync();
                }
                    localIsConnected = false;
                    DebugPrintLog($"Local主动断开_{s}");
                    await localMqttClient.DisconnectAsync(new MQTTnet.Client.Disconnecting.MqttClientDisconnectOptions {  }, CancellationToken.None);
                }
            }
            catch (Exception ex)
            {
                DebugPrintLog($"断开通讯连接出异常:{ex.Message}");
                DebugPrintLog($"Local断开通讯连接出异常:{ex.Message}");
            }
        }
        /// <summary>
        /// 断开远程Mqtt的链接
        /// </summary>
        public static void DisRemoteMqttClientConnect()
        public static async System.Threading.Tasks.Task DisConnectRemoteMqttClient(string s="")
        {
            RemoteMqttClient.DisconnectAsync();
            try
            {
                if (remoteIsConnected)
                {
                    remoteIsConnected = false;
                    DebugPrintLog($"Remote主动断开_{s}");
                    await RemoteMqttClient.DisconnectAsync(new MQTTnet.Client.Disconnecting.MqttClientDisconnectOptions { }, CancellationToken.None);
                }
            }
            catch(Exception e) {
                DebugPrintLog($"Remote断开通讯连接出异常:{e.Message}");
            }
        }
        #endregion
@@ -3492,35 +3553,35 @@
        /// </summary>
        async System.Threading.Tasks.Task SendRemoteMsg(string topicName, byte[] message, bool retain = false)
        {
            if (this.getGatewayBaseInfo?.gwID == null || !GateWayBaseInfomations.ContainsKey(this.getGatewayBaseInfo?.gwID))
            {
                return;
            }
            var gateWayBaseInfomation = GateWayBaseInfomations[this.getGatewayBaseInfo?.gwID];
            ////(1)生成[用户名:密码]
            //var userNameAndPwdStr = string.Concat(Shared.Common.Config.Instance.Guid, RemoteOperatorConsts.CAP_NUMBER, Shared.Common.Config.Instance.MD5PWD);
            //DebugPrintLog($"userNameAndPwdStr:{userNameAndPwdStr} ");
            ////(2)将(1)转成Base64字符串,生成格式[Base64(用户名:密码)]
            //var userNameAndPwdStrBaseSexFour = Convert.ToBase64String(ZigBee.Common.CommonInfo.EncodingUTF8.GetBytes(userNameAndPwdStr));
            ////(3)将(2)继续生成格式[Base64(用户名:密码):Timestamp]
            //var userNameAndPwdStrBaseSexFourAndTimestamp = string.Concat(userNameAndPwdStrBaseSexFour, RemoteOperatorConsts.CAP_NUMBER, CurrentTimeStamp.ToString());
            ////[Zigbee.Buspro]App/id(帐号Id)/Base64(DES[Base64(用户名:密码):Timestamp ]/网关唯一Id/转发给网关的主题/XX/XX
            ////(4)生成上报主题,主题模式需要为  /ZigbeeApp/id(主子调试帐号Id)/Base64(DES[Base64(用户名:密码):Timestamp ]/网关唯一Id/topicName "000204022022"   GateWayId  000204022022
            //var reportTopic = string.Format("/{0}/{1}/{2}/{3}/{4}", RemoteOperatorConsts.ZIGBEE_APP_STARTS_WITH, Shared.Common.Config.Instance.Guid, userNameAndPwdStrBaseSexFourAndTimestamp, this.getGatewayBaseInfo?.gwID, topicName);
            ////文件流不用加密
            //var topicEncStr = ZigBee.Common.SecuritySet.AesEncrypt(System.Text.Encoding.UTF8.GetBytes(reportTopic), gateWayBaseInfomation.AesKey);
            //topicEncStr = topicEncStr.Replace("/", "[[$-MQTT_TILT_SYMBOL_REPLACE-$]]").Replace("+", "[[$-MQTT_PLUS_SYMBOL_REPLACE-$]]");
            //message = System.Text.Encoding.UTF8.GetBytes(SecuritySet.AesEncrypt(message, gateWayBaseInfomation.AesKey));
            message = SecuritySet.AesEncryptBytes(message, gateWayBaseInfomation.AesKey);
            var topicEncStr = $"/ClientToZigbeeGateWay/{gateWayBaseInfomation.MacMark}/Common/{topicName}";
            //(6)构建Mqtt需要发布的数据包,发布给云端的MqttBroker
            if (RemoteMqttClient.IsConnected)
            {
                await RemoteMqttClient.PublishAsync(new MqttApplicationMessage { Topic = topicEncStr, Payload = message, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce });
            try
            {
                if (this.getGatewayBaseInfo?.gwID == null || !GateWayBaseInfomations.ContainsKey(this.getGatewayBaseInfo?.gwID))
                {
                    return;
                }
                var gateWayBaseInfomation = GateWayBaseInfomations[this.getGatewayBaseInfo?.gwID];
                message = SecuritySet.AesEncryptBytes(message, gateWayBaseInfomation.AesKey);
                var topicEncStr = $"/ClientToZigbeeGateWay/{gateWayBaseInfomation.MacMark}/Common/{topicName}";
                //(6)构建Mqtt需要发布的数据包,发布给云端的MqttBroker
                if (remoteIsConnected)
                {
                    try
                    {
                        await RemoteMqttClient.PublishAsync(new MqttApplicationMessage { Topic = topicEncStr, Payload = message, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce });
                    }
                    catch (Exception e)
                    {
                        await DisConnectRemoteMqttClient(e.Message);
                        await StartRemoteMqtt();
                        if (remoteIsConnected)
                        {
                            await RemoteMqttClient.PublishAsync(new MqttApplicationMessage { Topic = topicEncStr, Payload = message, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce });
                        }
                    }
                }
            }
            catch
            {
            }
        }
@@ -3547,25 +3608,33 @@
                }
                else
                {
                    DebugPrintLog($"局域网——发送到网关的主题:{topic}_发送到网关的数据:{System.Text.Encoding.UTF8.GetString(message)}_当前网关{CurrentGateWayId}");
                    if (!localMqttClient.IsConnected)
                    {
                        await StartLocalMqtt(getGatewayBaseInfo.IpAddress);
                    }
                    DebugPrintLog($"局域网——发送到网关的主题:{topic}_发送到网关的数据:{System.Text.Encoding.UTF8.GetString(message)}_当前网关{CurrentGateWayId} 是否加密:{IsEncry}");
                    if (IsEncry)
                    {
                        //文件流不用加密
                        if (topic != "FileTransfer/SendFile")
                        {
                            topic = ZigBee.Common.SecuritySet.AesEncrypt(System.Text.Encoding.UTF8.GetBytes(topic), Password);
                            topic = topic.Replace("/", "[[$-MQTT_TILT_SYMBOL_REPLACE-$]]").Replace("+", "[[$-MQTT_PLUS_SYMBOL_REPLACE-$]]");
                            message = System.Text.Encoding.UTF8.GetBytes(SecuritySet.AesEncrypt(message, password));
                            DebugPrintLog($"局域网——发送到网关的主题(秘文):{topic}_当前秘钥{Password}_发送到网关的数据(秘文):{System.Text.Encoding.UTF8.GetString(message)}_当前网关{CurrentGateWayId}_{System.DateTime.Now.ToString()}");
                            message = SecuritySet.AesEncryptBytes(message, password);
                        }
                    }
                    await localMqttClient.PublishAsync(new MqttApplicationMessage { Topic = topic, Payload = message, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce, Retain = retain });
                    }
                    if (localIsConnected)
                    {
                        try
                        {
                            await localMqttClient.PublishAsync(new MqttApplicationMessage { Topic = topic, Payload = message, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce, Retain = retain });
                        }
                        catch(Exception e)
                        {
                            DebugPrintLog($"Local主动断开_{e.Message}");
                            await DisConnectLocalMqttClient(e.Message);
                            await StartLocalMqtt("ReConnect");
                            if (localIsConnected)
                            {
                                await localMqttClient.PublishAsync(new MqttApplicationMessage { Topic = topic, Payload = message, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce, Retain = retain });
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
@@ -3608,8 +3677,7 @@
        {
            try
            {
                var topic = e.ApplicationMessage.Topic.TrimStart('/');
                topic = topic.Replace("[[$-MQTT_TILT_SYMBOL_REPLACE-$]]", "/").Replace("[[$-MQTT_PLUS_SYMBOL_REPLACE-$]]", "+");
                var topic = e.ApplicationMessage.Topic.TrimStart('/');
                var payload = e.ApplicationMessage.Payload;
                var message = string.Empty;
@@ -3624,7 +3692,7 @@
                {
                    return;
                }
                if (topics[2]== "NotifyGateWayInfoChagne") {
                if (topics[2]== "NotifyGateWayInfoChange") {
                    initGateWayBaseInfomation();
                    return;
                }
@@ -3671,39 +3739,36 @@
        {
            try
            {
                var topic = e.ApplicationMessage.Topic;
                topic = topic.Replace("[[$-MQTT_TILT_SYMBOL_REPLACE-$]]", "/").Replace("[[$-MQTT_PLUS_SYMBOL_REPLACE-$]]", "+");
                var message = System.Text.Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
                var topic = e.ApplicationMessage.Topic;
                string payloadString = "";
                if (IsEncry)
                {
                    //主题
                    topic = Common.SecuritySet.AesDecrypt(System.Text.Encoding.UTF8.GetBytes(topic), Password);
                    //下载的字节流不需要解密
                    if (topic.Split('/')[0] + "/" + topic.Split('/')[1] == topic.Split('/')[0] + "/" + "FileTransfer")
                    {
                        if (topic.Split('/')[2] != "DownloadFile")
                        {
                            message = Common.SecuritySet.AesDecrypt(e.ApplicationMessage.Payload, Password);
                            payloadString = System.Text.Encoding.UTF8.GetString(Common.SecuritySet.AesDecryptBytes(e.ApplicationMessage.Payload, Password));
                        }
                    }
                    else if (topic == topic.Split('/')[0] + "/" + "SendAESKey_Respon") { }//回复主题是秘文,数据是明文
                    else
                    {
                        message = Common.SecuritySet.AesDecrypt(e.ApplicationMessage.Payload, Password);
                        payloadString = System.Text.Encoding.UTF8.GetString(Common.SecuritySet.AesDecryptBytes(e.ApplicationMessage.Payload, Password));
                    }
                }
#if DEBUG
                DebugPrintLog($"网关返回的主题:{topic}_网关返回的负载:{message}_{System.DateTime.Now.ToString()}");
#endif
                ReceiveMessage(topic, message, e.ApplicationMessage.Payload);
                else
                {
                    payloadString = System.Text.Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
                }
                DebugPrintLog($"网关返回的主题:{topic}_网关返回的负载:{payloadString}");
                ReceiveMessage(topic, payloadString, e.ApplicationMessage.Payload);
            }
            catch (Exception ex)
            {
#if DEBUG
                DebugPrintLog($"接收网关数据异常:{ex.Message}");
#endif
            }
        }