| | |
| | | /// </summary> |
| | | [System.Serializable] |
| | | public class ZbGateway : ZbGatewayData |
| | | { |
| | | {
|
| | | #region 一堆变量 |
| | | /// <summary> |
| | | /// 主网关 |
| | | /// </summary> |
| | | /// <value>The main gate way.</value> |
| | | [Newtonsoft.Json.JsonIgnore] |
| | | public static ZbGateway MainGateWay |
| | | { |
| | | get |
| | | {
|
| | | { |
| | | ZbGateway mainWay = null; |
| | | for (int i = 0; i < GateWayList.Count; i++)
|
| | | {
|
| | | if (GateWayList[i].HomeId == Config.Instance.HomeId)
|
| | | {
|
| | | //2020.07.16变更:别管那么多,如果住宅ID一样,先确定就是它了(不然有时候经常返回null,有可能是刷新不到)
|
| | | mainWay = GateWayList[i];
|
| | | if (mainWay.IsMainGateWay == true)
|
| | | {
|
| | | //然后如果它确实是主网关,直接break
|
| | | break;
|
| | | }
|
| | | }
|
| | | }
|
| | | for (int i = 0; i < GateWayList.Count; i++) |
| | | { |
| | | if (GateWayList[i].HomeId == Config.Instance.HomeId) |
| | | { |
| | | //2020.07.16变更:别管那么多,如果住宅ID一样,先确定就是它了(不然有时候经常返回null,有可能是刷新不到) |
| | | mainWay = GateWayList[i]; |
| | | if (mainWay.IsMainGateWay == true) |
| | | { |
| | | //然后如果它确实是主网关,直接break |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | return mainWay; |
| | | } |
| | | } |
| | |
| | | /// <summary> |
| | | /// 是否使用远程连接模式 |
| | | /// </summary> |
| | | /// <value><c>true</c> if is remote; otherwise, <c>false</c>.</value> |
| | | public static bool IsRemote; |
| | | |
| | | /// <summary>
|
| | | /// 是否拥有远程连接的权限
|
| | | /// </summary> |
| | | [Newtonsoft.Json.JsonIgnore] |
| | | public static bool AllowRemoteCtrl = true; |
| | | public static bool IsRemote; |
| | | |
| | | /// <summary> |
| | | /// 网关保存路径 |
| | |
| | | } |
| | | return password; |
| | | } |
| | | } |
| | | }
|
| | |
|
| | | /// <summary> |
| | | /// 网关远程连接的一个标识ID,获取到了就不再改变 |
| | | /// </summary> |
| | | [Newtonsoft.Json.JsonIgnore] |
| | | private static string RemoteClientId = new Random().Next(10, 99).ToString(); |
| | | |
| | | /// <summary> |
| | | /// 网关是否加密 |
| | |
| | | |
| | | return data; |
| | | }); |
| | | }
|
| | | } |
| | | #endregion |
| | | |
| | | #region 读取协调器MAC地址. |
| | |
| | | { |
| | | //账号ID |
| | | string accountId = string.Empty; |
| | | if (homeId != string.Empty)
|
| | | if (homeId != string.Empty) |
| | | {
|
| | | if (Shared.Phone.UserCenter.UserCenterResourse.UserInfo.AuthorityNo == 1)
|
| | | {
|
| | | //主账号
|
| | | accountId = Config.Instance.Guid;
|
| | | }
|
| | | else
|
| | | {
|
| | | accountId = Config.Instance.Home.MainUserDistributedMark;
|
| | | }
|
| | | accountId = Config.Instance.Guid; |
| | | } |
| | | var jObject = new JObject { { "Cluster_ID", 0 }, { "Command", 82 } }; |
| | | var data = new JObject { { "HomeId", homeId }, { "AccountId", accountId } }; |
| | |
| | | /// </summary> |
| | | public async System.Threading.Tasks.Task<Panel.PanelSwitchLevelInfo> ClientDataPassthroughBytesAsync(string deviceAddr, int devicePoint, long dataLength, byte[] passData) |
| | | { |
| | | var myDevice = Shared.Common.LocalDevice.Current.GetDevice(deviceAddr, devicePoint); |
| | | var myDevice = Shared.Phone.HdlDeviceCommonLogic.Current.GetDevice(deviceAddr, devicePoint); |
| | | |
| | | Panel.PanelSwitchLevelInfo result = null; |
| | | |
| | |
| | | } |
| | | }
|
| | | #endregion |
| | | |
| | | #region 通讯连接 |
| | |
|
| | | #region 本地通讯连接 |
| | | /// <summary>
|
| | | /// 本地连接是否连接成功
|
| | | /// </summary> |
| | | [Newtonsoft.Json.JsonIgnore] |
| | | public bool LocalIsConnected; |
| | | /// <summary> |
| | | /// 局域网的MQTT |
| | | /// </summary> |
| | | IMqttClient localMqttClient = new MqttFactory().CreateMqttClient(); |
| | | bool localMqttIsConnecting; |
| | | [Newtonsoft.Json.JsonIgnore] |
| | | public bool localIsConnected; |
| | | /// <summary> |
| | | /// 手机标识 |
| | | private IMqttClient localMqttClient = new MqttFactory().CreateMqttClient(); |
| | | /// <summary>
|
| | | /// 本地mqtt是否正在连接中
|
| | | /// </summary> |
| | | static Guid currentGuid = Guid.NewGuid(); |
| | | private bool localMqttIsConnecting; |
| | | /// <summary> |
| | | /// 本地连接的一个客户端ID(app启动之后就不变了) |
| | | /// </summary> |
| | | private static Guid LocalConnectGuid = Guid.NewGuid(); |
| | | |
| | | public async 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 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 Task StartLocalMqtt(string brokerName) |
| | | {
|
| | | if (localMqttIsConnecting
|
| | | || Shared.Common.Config.Instance.HomeId == ""
|
| | | || localIsConnected)
|
| | | {
|
| | | return;
|
| | | { |
| | | if (localMqttIsConnecting |
| | | || Shared.Common.Config.Instance.HomeId == "" |
| | | || LocalIsConnected) |
| | | { |
| | | return; |
| | | } |
| | | await System.Threading.Tasks.Task.Factory.StartNew(async () => |
| | | await Task.Factory.StartNew(async () => |
| | | { |
| | | try |
| | | { |
| | |
| | | if (localMqttClient.DisconnectedHandler == null) |
| | | { |
| | | localMqttClient.UseDisconnectedHandler(async (e) => |
| | | {
|
| | | { |
| | | DebugPrintLog($" 本地连接断开_网关IP:{brokerName}_网关是否加:{IsEncry}"); |
| | | await DisConnectLocalMqttClient("StartLocalMqtt.DisconnectedHandler"); |
| | | //await StartLocalMqtt("ReConnect"); |
| | |
| | | } |
| | | if (localMqttClient.ConnectedHandler == null) |
| | | { |
| | | localMqttClient.UseConnectedHandler(async (e) =>
|
| | | {
|
| | | DebugPrintLog($" 本地连接成功_网关IP:{brokerName}_网关是否加:{IsEncry}_当前密码:{Password}");
|
| | | IsRemote = false;
|
| | | //Log写入(调试用)
|
| | | if (Shared.Phone.UserCenter.UserCenterResourse.HideOption.WriteSendAndReceveDataToFile == 1)
|
| | | {
|
| | | Shared.Phone.UserCenter.HdlLogLogic.Current.WriteLog(2, "本地连接成功");
|
| | | }
|
| | | localMqttClient.UseConnectedHandler(async (e) => |
| | | { |
| | | DebugPrintLog($" 本地连接成功_网关IP:{brokerName}_网关是否加:{IsEncry}_当前密码:{Password}"); |
| | | IsRemote = false; |
| | | //Log写入(调试用) |
| | | if (Shared.Phone.HdlUserCenterResourse.HideOption.WriteSendAndReceveDataToFile == 1) |
| | | { |
| | | Shared.Phone.HdlLogLogic.Current.WriteLog(2, "本地连接成功"); |
| | | } |
| | | }); |
| | | }
|
| | |
|
| | | var dateTime = DateTime.Now;
|
| | |
|
| | | new System.Threading.Thread(async () =>
|
| | | {
|
| | | try
|
| | | {
|
| | | if (localMqttClient.Options == null)
|
| | | {
|
| | | var options = new MQTTnet.Client.Options.MqttClientOptionsBuilder()//MQTT连接参数填充
|
| | | .WithClientId(currentGuid.ToString())//客户端ID
|
| | | .WithTcpServer(brokerName, 1883)//TCP服务端 1883 ,即MQTT服务端
|
| | | .WithCredentials("", "")//"", "")//凭证 帐号 密码
|
| | | .WithCommunicationTimeout(new TimeSpan(0, 0, 60)) //重连超时时间,默认5s
|
| | | .WithKeepAlivePeriod(new TimeSpan(0, 0, 15)) //保持连接时间,默认5s,心跳包
|
| | | .Build();//
|
| | | await localMqttClient.ConnectAsync(options);
|
| | | }
|
| | | 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);
|
| | | }
|
| | | }
|
| | | } |
| | | |
| | | var dateTime = DateTime.Now; |
| | | |
| | | new System.Threading.Thread(async () => |
| | | { |
| | | try |
| | | { |
| | | if (localMqttClient.Options == null) |
| | | { |
| | | var options = new MQTTnet.Client.Options.MqttClientOptionsBuilder()//MQTT连接参数填充 |
| | | .WithClientId(LocalConnectGuid.ToString())//客户端ID |
| | | .WithTcpServer(brokerName, 1883)//TCP服务端 1883 ,即MQTT服务端 |
| | | .WithCredentials("", "")//"", "")//凭证 帐号 密码 |
| | | .WithCommunicationTimeout(new TimeSpan(0, 0, 60)) //重连超时时间,默认5s |
| | | .WithKeepAlivePeriod(new TimeSpan(0, 0, 15)) //保持连接时间,默认5s,心跳包 |
| | | .Build();// |
| | | await localMqttClient.ConnectAsync(options); |
| | | } |
| | | 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) |
| | | {
|
| | | //Log写入(调试用)
|
| | | if (Shared.Phone.UserCenter.UserCenterResourse.HideOption.WriteSendAndReceveDataToFile == 1)
|
| | | {
|
| | | Shared.Phone.UserCenter.HdlLogLogic.Current.WriteLog(2, "本地连接异常:\r\n" + ex.Message);
|
| | | { |
| | | //Log写入(调试用) |
| | | if (Shared.Phone.HdlUserCenterResourse.HideOption.WriteSendAndReceveDataToFile == 1) |
| | | { |
| | | Shared.Phone.HdlLogLogic.Current.WriteLog(2, "本地连接异常:\r\n" + ex.Message); |
| | | } |
| | | DebugPrintLog($"局域网通讯连接出异常:{ex.Message}"); |
| | | } |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 当前有帐号下所有的网关列表及信息 |
| | | /// </summary> |
| | | public static Dictionary<string, Shared.Phone.UserCenter.GatewayResult> GateWayBaseInfomations = new Dictionary<string, Shared.Phone.UserCenter.GatewayResult> { }; |
| | | /// <summary> |
| | | /// 获取当前帐号所有的网关信息 |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | static async Task initGateWayBaseInfomation() |
| | | {
|
| | | if (AllowRemoteCtrl == false)
|
| | | {
|
| | | //没有远程连接的权限
|
| | | return;
|
| | | }
|
| | | string loginToken = Config.Instance.Token;
|
| | | if (Config.Instance.Home.IsOthreShare == true)
|
| | | {
|
| | | //获取成员的特殊Token
|
| | | var pra = new
|
| | | {
|
| | | CommonPage.RequestVersion,
|
| | | LoginAccessToken = Config.Instance.Token,
|
| | | MainAccountId = Config.Instance.Home.MainUserDistributedMark,
|
| | | SharedHid = Config.Instance.Home.Id
|
| | | };
|
| | | var resultData = Shared.Phone.UserCenter.UserCenterLogic.GetByteResponseDataByRequestHttps("App/GetSharedHomeApiControl", false, pra, new List<string> { "NotCheck" });
|
| | | if (resultData == null)
|
| | | {
|
| | | return;
|
| | | }
|
| | | var revertObj = Newtonsoft.Json.JsonConvert.DeserializeObject<Shared.Common.ResponseEntity.ResponsePack>(Encoding.UTF8.GetString(resultData));
|
| | | //分享链接
|
| | | var info = Newtonsoft.Json.JsonConvert.DeserializeObject<Shared.Phone.UserCenter.MemberAdministratorResult>(revertObj.ResponseData.ToString());
|
| | | loginToken = info.RequestToken;
|
| | | }
|
| | |
|
| | | try |
| | | { |
| | | //设置访问接口的参数
|
| | | var pra2 = new Shared.Phone.UserCenter.GetGatewayPra();
|
| | | pra2.IsOtherAccountCtrl = Config.Instance.Home.IsOthreShare;
|
| | | pra2.ReqDto.PageSetting.Page = 1;
|
| | | pra2.ReqDto.PageSetting.PageSize = 20;
|
| | | pra2.ReqDto.LoginAccessToken = loginToken; |
| | | var bytes = System.Text.Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(pra2)); |
| | | |
| | | var result = CommonPage.Instance.DoRequestZigbeeHttpsInterface("https://global.hdlcontrol.com/HangZhouHdlCloudApi/App/GetSingleHomeGatewayPagger", bytes, loginToken);
|
| | | if (result != null)
|
| | | {
|
| | | var jobject = Newtonsoft.Json.Linq.JObject.Parse(Encoding.UTF8.GetString(result));
|
| | |
|
| | | var statuCode = jobject["StateCode"].ToString();
|
| | | if (statuCode != "Success")
|
| | | {
|
| | | //序列化对象
|
| | | var requestJson = Newtonsoft.Json.JsonConvert.SerializeObject(pra2);
|
| | | //Log出力
|
| | | string errorMsg = "接口访问失败★:App/GetSingleHomeGatewayPagger " + statuCode + "\r\n";
|
| | | errorMsg += "参数:\r\n" + requestJson;
|
| | | Shared.Phone.UserCenter.HdlLogLogic.Current.WriteLog(-1, errorMsg);
|
| | | return;
|
| | | }
|
| | |
|
| | | var responseData = jobject["ResponseData"];
|
| | | if (responseData != null)
|
| | | {
|
| | | if (responseData["PageData"] != null)
|
| | | {
|
| | | var list = JArray.Parse(responseData["PageData"].ToString());
|
| | | foreach (var v in list)
|
| | | {
|
| | | GateWayBaseInfomations[v["GatewayUniqueId"].ToString()] = new Shared.Phone.UserCenter.GatewayResult { AesKey = v["AesKey"].ToString(), MacMark = v["MacMark"].ToString(), MqttOnlineStatus = bool.Parse(v["MqttOnlineStatus"].ToString()) };
|
| | | //if (RemoteMqttClient.IsConnected)
|
| | | {
|
| | | await RemoteMqttClient.SubscribeAsync($"/ZigbeeGateWayToClient/{v["MacMark"].ToString()}/#", MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce);
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | | } |
| | | } |
| | | catch (Exception ex)
|
| | | { |
| | | Shared.Phone.UserCenter.HdlLogLogic.Current.WriteLog(ex); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 外网的MQTT是否正在连接 |
| | | /// </summary> |
| | | static bool remoteMqttIsConnecting; |
| | | |
| | | /// <summary> |
| | | /// 远程MqttClient |
| | | /// </summary> |
| | | public static IMqttClient RemoteMqttClient = new MqttFactory().CreateMqttClient(); |
| | | static bool remoteIsConnected; |
| | | |
| | | /// <summary>
|
| | | /// 远程开始连接的时间点
|
| | | /// </summary> |
| | | private static DateTime RemoteConnectTime = DateTime.Now; |
| | | /// <summary> |
| | | /// 启动远程Mqtt |
| | | /// </summary> |
| | | /// <returns>The start.</returns> |
| | | /// <param name="brokerName">Broker name.</param> |
| | | public static async Task StartRemoteMqtt() |
| | | {
|
| | | //追加:没有远程连接的权限
|
| | | if (AllowRemoteCtrl == false
|
| | | || Shared.Common.Config.Instance.HomeId == ""
|
| | | || remoteIsConnected)
|
| | | {
|
| | | return;
|
| | | } |
| | | //如果远程还在连接中 |
| | | if (remoteMqttIsConnecting == true)
|
| | | {
|
| | | //如果这个变量一直处于连接中的状态,但是已经过去了10秒了,还是true的话,说明这里是有点问题的,需要重新创建
|
| | | if ((DateTime.Now - RemoteConnectTime).TotalMilliseconds < 10 * 1000)
|
| | | {
|
| | | return;
|
| | | }
|
| | | } |
| | | //记录起这次远程连接的时间点 |
| | | RemoteConnectTime = DateTime.Now; |
| | | |
| | | await Task.Factory.StartNew(async () => |
| | | { |
| | | try |
| | | { |
| | | lock (RemoteMqttClient) |
| | | { |
| | | //表示后面将进行连接 |
| | | remoteMqttIsConnecting = true; |
| | | |
| | | #region 初始化远程Mqtt |
| | | //(3)当[连接云端的Mqtt成功后]或者[以及后面App通过云端Mqtt转发数据给网关成功后],处理接收到云端数据包响应时在mqttServerClient_ApplicationMessageReceived这个方法处理 |
| | | if (RemoteMqttClient.ApplicationMessageReceivedHandler == null) |
| | | { |
| | | RemoteMqttClient.UseApplicationMessageReceivedHandler((e) => |
| | | {
|
| | | //这里是特殊的主题
|
| | | if (e.ApplicationMessage.Topic == "/ZigbeeGateWayToClient/" + Config.Instance.ConnEmqClientId + "/Push/NotifySqueeze"//踢人下线
|
| | | || e.ApplicationMessage.Topic == "/ZigbeeGateWayToClient/" + Config.Instance.Guid + "/Push/Deleted"//分享删除
|
| | | || e.ApplicationMessage.Topic == "/ZigbeeGateWayToClient/" + Config.Instance.Guid + "/Push/DeletedShareData"//分享删除
|
| | | || e.ApplicationMessage.Topic == "/ZigbeeGateWayToClient/" + Config.Instance.Guid + "/Push/Update"//成员权限变更
|
| | | || e.ApplicationMessage.Topic == "/ZigbeeGateWayToClient/" + Config.Instance.Home.Id + "_" + Config.Instance.Guid + "/PrimaryUserDelYou")//子账号被删除
|
| | | {
|
| | | mqttRemoteClient_MqttMsgPublishReceived(e);
|
| | | return;
|
| | | }
|
| | | if (!RemoteMqttClient.IsConnected || !IsRemote)
|
| | | {
|
| | | return;
|
| | | } |
| | | mqttRemoteClient_MqttMsgPublishReceived(e); |
| | | }); |
| | | } |
| | | |
| | | if (RemoteMqttClient.DisconnectedHandler == null) |
| | | { |
| | | RemoteMqttClient.UseDisconnectedHandler(async (e) => |
| | | { |
| | | DebugPrintLog($"远程连接断开"); |
| | | await DisConnectRemoteMqttClient("StartRemoteMqtt.DisconnectedHandler"); |
| | | //await StartRemoteMqtt(); |
| | | }); |
| | | } |
| | | if (RemoteMqttClient.ConnectedHandler == null) |
| | | { |
| | | RemoteMqttClient.UseConnectedHandler(async (e) =>
|
| | | {
|
| | | DebugPrintLog($"远程连接成功");
|
| | |
|
| | | if (Config.Instance.Home.IsOthreShare == true)
|
| | | {
|
| | | //订阅一个成员被删除的主题
|
| | | string myGuid = Config.Instance.Guid;
|
| | | await RemoteMqttClient.SubscribeAsync("/ZigbeeGateWayToClient/" + myGuid + "/Push/Deleted");
|
| | | //订阅一个分享数据已经变更的主题
|
| | | await RemoteMqttClient.SubscribeAsync("/ZigbeeGateWayToClient/" + myGuid + "/Push/DeletedShareData");
|
| | | //订阅一个子账号被删除的主题
|
| | | await RemoteMqttClient.SubscribeAsync("/ZigbeeGateWayToClient/" + Config.Instance.Home.Id + "_" + myGuid + "/PrimaryUserDelYou");
|
| | | //订阅一个成员权限已经变更的主题
|
| | | await RemoteMqttClient.SubscribeAsync("/ZigbeeGateWayToClient/" + myGuid + "/Push/Update");
|
| | | }
|
| | | //订阅一个挤下线的主题
|
| | | await RemoteMqttClient.SubscribeAsync("/ZigbeeGateWayToClient/" + Config.Instance.ConnEmqClientId + "/Push/NotifySqueeze");
|
| | |
|
| | | //如果这个函数卡久了的话,会接收到云端推送的挤下线主题,不知道为什么
|
| | | new Thread(async () =>
|
| | | {
|
| | | await initGateWayBaseInfomation();
|
| | |
|
| | | //没有主网关时主动读取,获取主网关信息
|
| | | var gateWayList = GateWayList.FindAll(obj => obj.HomeId == Shared.Common.Config.Instance.HomeId);
|
| | | if (gateWayList.Find(obj => obj.IsMainGateWay == true) == null)
|
| | | {
|
| | | if (gateWayList.Count == 1)
|
| | | {
|
| | | gateWayList[0].IsMainGateWay = true;
|
| | | }
|
| | | else
|
| | | {
|
| | | for (int i = 0; i < gateWayList.Count; i++)
|
| | | {
|
| | | var gateWay = gateWayList[i];
|
| | | var info = await gateWay.GetZbGwInfoAsync();
|
| | | if (info == null || info.getGwData == null)
|
| | | {
|
| | | continue;
|
| | | }
|
| | | if (info.getGwData.IsDominant == 1)
|
| | | {
|
| | | for (int j = 0; j < gateWayList.Count; j++)
|
| | | {
|
| | | if (gateWayList[i].GwId == info.getGwData.GwId)
|
| | | {
|
| | | gateWayList[i].IsMainGateWay = true;
|
| | | }
|
| | | else
|
| | | {
|
| | | gateWayList[i].IsMainGateWay = false;
|
| | | }
|
| | | }
|
| | | break;
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | | })
|
| | | { IsBackground = true }.Start();
|
| | | |
| | | }); |
| | | } |
| | | #endregion |
| | | } |
| | | |
| | | try |
| | | {
|
| | | 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,
|
| | | ["PlatformStr"] = "h",//这两个值如果不设置,则云端不发布主题
|
| | | ["PublishPayloadJsonStr"] = "1"
|
| | | };
|
| | | var bytes = System.Text.Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(jsonData));
|
| | | result = 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,
|
| | | ["PlatformStr"] = "h",//这两个值如果不设置,则云端不发布主题
|
| | | ["PublishPayloadJsonStr"] = "1"
|
| | | };
|
| | | var bytes = System.Text.Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(jsonData));
|
| | | result = 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)); |
| | | if (jobject["StateCode"].ToString() == "NotAllowRemoteCtrl")
|
| | | {
|
| | | //没有远程连接的权限
|
| | | AllowRemoteCtrl = false;
|
| | | return;
|
| | | } |
| | | |
| | | var responseData = jobject["ResponseData"]; |
| | | if (responseData != null) |
| | | { |
| | | var connEmqDomainPort = responseData["ConnEmqDomainPort"]?.ToString(); |
| | | var connEmqClientId = responseData["ConnEmqClientId"]?.ToString(); |
| | | var connEmqUserName = responseData["ConnEmqUserName"]?.ToString(); |
| | | var connEmqPwd = responseData["ConnEmqPwd"]?.ToString(); |
| | | //记录起当前的客户端ID |
| | | Config.Instance.ConnEmqClientId = connEmqClientId; |
| | | |
| | | 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()
|
| | | //.WithCommunicationTimeout(TimeSpan.FromSeconds(10))
|
| | | .Build();
|
| | | await DisConnectRemoteMqttClient("StartRemoteMqtt");
|
| | | await RemoteMqttClient.ConnectAsync(options, CancellationToken.None);
|
| | |
|
| | | remoteIsConnected = true; |
| | | } |
| | | } |
| | | } |
| | | catch { } |
| | | finally |
| | | { |
| | | //最终要释放连接状态 |
| | | remoteMqttIsConnecting = false;
|
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | DebugPrintLog($"远程连接通讯连接出异常:{ex.Message}"); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 断开服务器连接 |
| | | /// </summary> |
| | | public async Task DisConnectLocalMqttClient(string s) |
| | | { |
| | | try |
| | | { |
| | | if (localIsConnected)
|
| | | {
|
| | | localIsConnected = false;
|
| | | //这个东西也要弄
|
| | | localMqttIsConnecting = false;
|
| | | DebugPrintLog($"Local主动断开_{s}");
|
| | | //await localMqttClient.DisconnectAsync(new MQTTnet.Client.Disconnecting.MqttClientDisconnectOptions { }, CancellationToken.None);
|
| | | await localMqttClient.DisconnectAsync();
|
| | | }
|
| | | if (LocalIsConnected) |
| | | { |
| | | LocalIsConnected = false; |
| | | //这个东西也要弄 |
| | | localMqttIsConnecting = false; |
| | | DebugPrintLog($"Local主动断开_{s}"); |
| | | //await localMqttClient.DisconnectAsync(new MQTTnet.Client.Disconnecting.MqttClientDisconnectOptions { }, CancellationToken.None); |
| | | await localMqttClient.DisconnectAsync(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | DebugPrintLog($"Local断开通讯连接出异常:{ex.Message}"); |
| | | } |
| | | }
|
| | |
|
| | | } |
| | | |
| | | /// <summary> |
| | | /// 强制断开本地的网关连接 |
| | | /// </summary> |
| | | public async Task CloseLocalConnectionOnForce() |
| | | { |
| | | try |
| | | {
|
| | | await localMqttClient.DisconnectAsync();
|
| | | { |
| | | await localMqttClient.DisconnectAsync(); |
| | | } |
| | | catch { } |
| | | finally |
| | | {
|
| | | localIsConnected = false;
|
| | | //这个东西也要弄
|
| | | localMqttIsConnecting = false;
|
| | | { |
| | | LocalIsConnected = false; |
| | | //这个东西也要弄 |
| | | localMqttIsConnecting = false; |
| | | } |
| | | } |
| | | |
| | | /// <summary>
|
| | | /// 断开远程Mqtt的链接
|
| | |
|
| | | #endregion |
| | |
|
| | | #region 远程通讯连接 |
| | |
|
| | | /// <summary> |
| | | /// 当前有帐号下所有的云端网关列表及信息 |
| | | /// </summary> |
| | | public static async Task DisConnectRemoteMqttClient(string s = "")
|
| | | {
|
| | | try
|
| | | {
|
| | | if (remoteIsConnected)
|
| | | {
|
| | | remoteIsConnected = false;
|
| | | //这个东西也要弄
|
| | | remoteMqttIsConnecting = false;
|
| | | DebugPrintLog($"Remote主动断开_{s}");
|
| | | //await RemoteMqttClient.DisconnectAsync(new MQTTnet.Client.Disconnecting.MqttClientDisconnectOptions { }, CancellationToken.None);
|
| | | await RemoteMqttClient.DisconnectAsync();
|
| | | }
|
| | | }
|
| | | catch (Exception e)
|
| | | { |
| | | DebugPrintLog($"Remote断开通讯连接出异常:{e.Message}");
|
| | | }
|
| | | } |
| | | |
| | | public static Dictionary<string, Shared.Phone.GatewayResult> DicGatewayBaseInfo = new Dictionary<string, Shared.Phone.GatewayResult> { };
|
| | | /// <summary> |
| | | /// 外网的MQTT是否正在连接 |
| | | /// </summary> |
| | | private static bool remoteMqttIsConnecting; |
| | | /// <summary> |
| | | /// 远程MqttClient |
| | | /// </summary> |
| | | public static IMqttClient RemoteMqttClient = new MqttFactory().CreateMqttClient(); |
| | | /// <summary>
|
| | | /// 强制断开远程Mqtt的链接
|
| | | /// </summary>
|
| | | /// <returns></returns> |
| | | public static async Task CloseRemoteConnectionOnForce()
|
| | | {
|
| | | /// 远程连接是否完成
|
| | | /// </summary> |
| | | private static bool remoteIsConnected; |
| | | /// <summary> |
| | | /// 远程开始连接的时间点 |
| | | /// </summary> |
| | | private static DateTime RemoteConnectTime = DateTime.Now; |
| | | |
| | | /// <summary> |
| | | /// 启动远程Mqtt |
| | | /// </summary> |
| | | public static async Task StartRemoteMqtt() |
| | | { |
| | | //追加:没有远程连接的权限 |
| | | if (Config.Instance.Home.IsRemoteControl == false |
| | | || Config.Instance.Home.Id == "" |
| | | || remoteIsConnected) |
| | | { |
| | | return; |
| | | } |
| | | //如果远程还在连接中 |
| | | if (remoteMqttIsConnecting == true) |
| | | { |
| | | //如果这个变量一直处于连接中的状态,但是已经过去了10秒了,还是true的话,说明这里是有点问题的,需要重新创建 |
| | | if ((DateTime.Now - RemoteConnectTime).TotalMilliseconds < 10 * 1000) |
| | | { |
| | | return; |
| | | } |
| | | } |
| | | //记录起这次远程连接的时间点 |
| | | RemoteConnectTime = DateTime.Now;
|
| | |
|
| | | //初始化远程mqtt事件
|
| | | InitRemoteMqttEvent();
|
| | |
|
| | | try
|
| | | {
|
| | | await RemoteMqttClient.DisconnectAsync();
|
| | | //获取远程mqtt链接信息
|
| | | var pra = new { attachClientId = RemoteClientId, homeType = "ZIGBEE" };
|
| | | var result = Shared.Phone.HdlHttpLogic.Current.RequestResponseFromZigbeeHttps("home-wisdom/mqtt/getRemoteInfo", RestSharp.Method.POST, pra);
|
| | | if (result != null && result.Code == Shared.Phone.HttpMessageEnum.A成功)
|
| | | {
|
| | | var jobject = JObject.Parse(result.Data.ToString());
|
| | |
|
| | | var connEmqClientId = jobject["clientId"]?.ToString();
|
| | | var connEmqUserName = jobject["userName"]?.ToString();
|
| | | var connEmqPwd = jobject["passWord"]?.ToString();
|
| | | //记录起当前的客户端ID
|
| | | Config.Instance.ConnEmqClientId = connEmqClientId;
|
| | |
|
| | | var connEmqDomainPorts = jobject["url"].ToString().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 DisConnectRemoteMqttClient("StartRemoteMqtt");
|
| | | await RemoteMqttClient.ConnectAsync(options, CancellationToken.None);
|
| | |
|
| | | remoteIsConnected = true;
|
| | | }
|
| | | }
|
| | | catch { }
|
| | | finally
|
| | | {
|
| | | remoteIsConnected = false;
|
| | | //这个东西也要弄
|
| | | //最终要释放连接状态
|
| | | remoteMqttIsConnecting = false;
|
| | | } |
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// 初始化远程mqtt事件
|
| | | /// </summary>
|
| | | private static void InitRemoteMqttEvent()
|
| | | {
|
| | | lock (RemoteMqttClient)
|
| | | {
|
| | | //表示后面将进行连接
|
| | | remoteMqttIsConnecting = true;
|
| | |
|
| | | //(3)当[连接云端的Mqtt成功后]或者[以及后面App通过云端Mqtt转发数据给网关成功后],处理接收到云端数据包响应时在mqttServerClient_ApplicationMessageReceived这个方法处理
|
| | | if (RemoteMqttClient.ApplicationMessageReceivedHandler == null)
|
| | | {
|
| | | RemoteMqttClient.UseApplicationMessageReceivedHandler((e) =>
|
| | | {
|
| | | //这里是特殊的主题
|
| | | if (e.ApplicationMessage.Topic == "/ZigbeeGateWayToClient/" + Config.Instance.ConnEmqClientId + "/Push/NotifySqueeze"//踢人下线
|
| | | || e.ApplicationMessage.Topic == "/ZigbeeGateWayToClient/" + Config.Instance.Guid + "/Push/Deleted"//分享删除
|
| | | || e.ApplicationMessage.Topic == "/ZigbeeGateWayToClient/" + Config.Instance.Guid + "/Push/DeletedShareData"//分享删除
|
| | | || e.ApplicationMessage.Topic == "/ZigbeeGateWayToClient/" + Config.Instance.Guid + "/Push/Update"//成员权限变更
|
| | | || e.ApplicationMessage.Topic == "/ZigbeeGateWayToClient/" + Config.Instance.Home.Id + "_" + Config.Instance.Guid + "/PrimaryUserDelYou")//子账号被删除
|
| | | {
|
| | | mqttRemoteClient_MqttMsgPublishReceived(e);
|
| | | return;
|
| | | }
|
| | | if (!RemoteMqttClient.IsConnected || !IsRemote)
|
| | | {
|
| | | return;
|
| | | }
|
| | | mqttRemoteClient_MqttMsgPublishReceived(e);
|
| | | });
|
| | | }
|
| | |
|
| | | if (RemoteMqttClient.DisconnectedHandler == null)
|
| | | {
|
| | | RemoteMqttClient.UseDisconnectedHandler(async (e) =>
|
| | | {
|
| | | DebugPrintLog($"远程连接断开");
|
| | | await DisConnectRemoteMqttClient("StartRemoteMqtt.DisconnectedHandler");
|
| | | });
|
| | | }
|
| | |
|
| | | if (RemoteMqttClient.ConnectedHandler == null)
|
| | | {
|
| | | RemoteMqttClient.UseConnectedHandler(async (e) =>
|
| | | {
|
| | | DebugPrintLog($"远程连接成功");
|
| | |
|
| | | if (Config.Instance.Home.IsOtherShare == true)
|
| | | {
|
| | | //订阅一个成员被删除的主题
|
| | | string myGuid = Config.Instance.Guid;
|
| | | await RemoteMqttClient.SubscribeAsync("/ZigbeeGateWayToClient/" + myGuid + "/Push/Deleted");
|
| | | //订阅一个分享数据已经变更的主题
|
| | | await RemoteMqttClient.SubscribeAsync("/ZigbeeGateWayToClient/" + myGuid + "/Push/DeletedShareData");
|
| | | //订阅一个子账号被删除的主题
|
| | | await RemoteMqttClient.SubscribeAsync("/ZigbeeGateWayToClient/" + Config.Instance.Home.Id + "_" + myGuid + "/PrimaryUserDelYou");
|
| | | //订阅一个成员权限已经变更的主题
|
| | | await RemoteMqttClient.SubscribeAsync("/ZigbeeGateWayToClient/" + myGuid + "/Push/Update");
|
| | | }
|
| | | //订阅一个挤下线的主题
|
| | | await RemoteMqttClient.SubscribeAsync("/ZigbeeGateWayToClient/" + Config.Instance.ConnEmqClientId + "/Push/NotifySqueeze");
|
| | |
|
| | | //如果这个函数卡久了的话,会接收到云端推送的挤下线主题,不知道为什么
|
| | | new System.Threading.Thread(async () =>
|
| | | {
|
| | | await InitGateWayBaseInfomation();
|
| | |
|
| | | //没有主网关时主动读取,获取主网关信息
|
| | | var gateWayList = GateWayList.FindAll(obj => obj.HomeId == Shared.Common.Config.Instance.HomeId);
|
| | | if (gateWayList.Find(obj => obj.IsMainGateWay == true) == null)
|
| | | {
|
| | | if (gateWayList.Count == 1)
|
| | | {
|
| | | gateWayList[0].IsMainGateWay = true;
|
| | | }
|
| | | else
|
| | | {
|
| | | for (int i = 0; i < gateWayList.Count; i++)
|
| | | {
|
| | | var gateWay = gateWayList[i];
|
| | | var info = await gateWay.GetZbGwInfoAsync();
|
| | | if (info == null || info.getGwData == null)
|
| | | {
|
| | | continue;
|
| | | }
|
| | | if (info.getGwData.IsDominant == 1)
|
| | | {
|
| | | for (int j = 0; j < gateWayList.Count; j++)
|
| | | {
|
| | | if (gateWayList[i].GwId == info.getGwData.GwId)
|
| | | {
|
| | | gateWayList[i].IsMainGateWay = true;
|
| | | }
|
| | | else
|
| | | {
|
| | | gateWayList[i].IsMainGateWay = false;
|
| | | }
|
| | | }
|
| | | break;
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | | })
|
| | | { IsBackground = true }.Start();
|
| | | });
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | /// <summary> |
| | | /// 初始化当前帐号所有的云端网关信息 |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | private static async Task InitGateWayBaseInfomation() |
| | | { |
| | | if (Config.Instance.Home.IsRemoteControl == false) |
| | | { |
| | | //没有远程连接的权限 |
| | | return; |
| | | } |
| | | //获取云端网关信息 |
| | | var listGatewayInfo = Shared.Phone.HdlGatewayLogic.Current.GetGateWayListFromDataBase(Config.Instance.Home.Id); |
| | | if (listGatewayInfo == null) { return; } |
| | | |
| | | foreach (var info in listGatewayInfo.Values)
|
| | | {
|
| | | try
|
| | | {
|
| | | //有可能云端是这么处理:如果没有远程权限,则不给AesKey
|
| | | if (string.IsNullOrEmpty(info.AesKey) == true) { continue; }
|
| | | //保存缓存
|
| | | DicGatewayBaseInfo[info.Mac] = info;
|
| | | //我也不知道这个是干嘛的
|
| | | await RemoteMqttClient.SubscribeAsync($"/ZigbeeGateWayToClient/" + info.Id + "/#", MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce);
|
| | | }
|
| | | catch (Exception ex)
|
| | | {
|
| | | Shared.Phone.HdlLogLogic.Current.WriteLog(ex);
|
| | | }
|
| | | } |
| | | }
|
| | |
|
| | | /// <summary> |
| | | /// 断开远程Mqtt的链接 |
| | | /// </summary> |
| | | public static async Task DisConnectRemoteMqttClient(string s = "") |
| | | { |
| | | try |
| | | { |
| | | if (remoteIsConnected) |
| | | { |
| | | remoteIsConnected = false; |
| | | //这个东西也要弄 |
| | | remoteMqttIsConnecting = false; |
| | | DebugPrintLog($"Remote主动断开_{s}"); |
| | | //await RemoteMqttClient.DisconnectAsync(new MQTTnet.Client.Disconnecting.MqttClientDisconnectOptions { }, CancellationToken.None); |
| | | await RemoteMqttClient.DisconnectAsync(); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | DebugPrintLog($"Remote断开通讯连接出异常:{e.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 强制断开远程Mqtt的链接 |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | public static async Task CloseRemoteConnectionOnForce() |
| | | { |
| | | try |
| | | { |
| | | await RemoteMqttClient?.DisconnectAsync(); |
| | | } |
| | | catch { } |
| | | finally |
| | | { |
| | | remoteIsConnected = false; |
| | | //这个东西也要弄 |
| | | remoteMqttIsConnecting = false; |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | |
|
| | | #region 数据发送 |
| | | |
| | |
|
| | | /// <summary> |
| | | /// 发送消息到服务器 |
| | | /// </summary> |
| | |
| | | /// </summary> |
| | | async System.Threading.Tasks.Task SendRemoteMsg(string topicName, byte[] message, bool retain = false) |
| | | { |
| | | try
|
| | | {
|
| | | if (this.GwId == string.Empty || !GateWayBaseInfomations.ContainsKey(this.GwId))
|
| | | {
|
| | | return;
|
| | | }
|
| | | var gateWayBaseInfomation = GateWayBaseInfomations[this.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 });
|
| | | }
|
| | | }
|
| | | try |
| | | { |
| | | if (this.GwId == string.Empty || !DicGatewayBaseInfo.ContainsKey(this.GwId)) |
| | | { |
| | | return; |
| | | } |
| | | }
|
| | | catch
|
| | | {
|
| | | var gateWayBaseInfomation = DicGatewayBaseInfo[this.GwId]; |
| | | message = SecuritySet.AesEncryptBytes(message, gateWayBaseInfomation.AesKey); |
| | | var topicEncStr = $"/ClientToZigbeeGateWay/{gateWayBaseInfomation.Id}/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 |
| | | { |
| | | } |
| | | } |
| | | |
| | |
| | | if (Shared.Common.Config.Instance.HomeId == "") |
| | | { |
| | | return; |
| | | }
|
| | |
|
| | | //Log写入(调试用)
|
| | | if (Shared.Phone.UserCenter.UserCenterResourse.HideOption.WriteSendAndReceveDataToFile == 1)
|
| | | {
|
| | | string text = "远程发送:";
|
| | | if (IsRemote == false) { text = "本地发送:"; }
|
| | | text += topic + "\r\n";
|
| | | text += Encoding.UTF8.GetString(message) + "\r\n";
|
| | | Shared.Phone.UserCenter.HdlLogLogic.Current.WriteLog(2, text);
|
| | | } |
| | | |
| | | //Log写入(调试用) |
| | | if (Shared.Phone.HdlUserCenterResourse.HideOption.WriteSendAndReceveDataToFile == 1) |
| | | { |
| | | string text = "远程发送:"; |
| | | if (IsRemote == false) { text = "本地发送:"; } |
| | | text += topic + "\r\n"; |
| | | text += Encoding.UTF8.GetString(message) + "\r\n"; |
| | | Shared.Phone.HdlLogLogic.Current.WriteLog(2, text); |
| | | } |
| | | |
| | | if (IsRemote) |
| | |
| | | } |
| | | else |
| | | { |
| | | DebugPrintLog($"局域网——发送到网关的主题:{topic}_发送到网关的数据:{System.Text.Encoding.UTF8.GetString(message)}_是否加密:{IsEncry}");
|
| | |
|
| | | DebugPrintLog($"局域网——发送到网关的主题:{topic}_发送到网关的数据:{System.Text.Encoding.UTF8.GetString(message)}_是否加密:{IsEncry}"); |
| | | |
| | | if (IsEncry) |
| | | { |
| | | //文件流不用加密 |
| | |
| | | { |
| | | message = SecuritySet.AesEncryptBytes(message, password); |
| | | } |
| | | }
|
| | | if (localIsConnected) |
| | | {
|
| | | try
|
| | | {
|
| | | await localMqttClient.PublishAsync(new MqttApplicationMessage { Topic = topic, Payload = message, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce, Retain = retain });
|
| | | }
|
| | | catch (Exception e)
|
| | | } |
| | | if (LocalIsConnected) |
| | | { |
| | | try |
| | | { |
| | | DebugPrintLog($"Local主动断开_{e.Message}");
|
| | | 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)
|
| | | {
|
| | | DebugPrintLog($"局域网——二次发送到网关的主题:{topic}_发送到网关的数据:{System.Text.Encoding.UTF8.GetString(message)}_是否加密:{IsEncry}");
|
| | | await localMqttClient.PublishAsync(new MqttApplicationMessage { Topic = topic, Payload = message, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce, Retain = retain });
|
| | | }
|
| | | //Log写入(调试用)
|
| | | if (Shared.Phone.UserCenter.UserCenterResourse.HideOption.WriteSendAndReceveDataToFile == 1)
|
| | | {
|
| | | Shared.Phone.UserCenter.HdlLogLogic.Current.WriteLog(2, "本地连接异常断开");
|
| | | await StartLocalMqtt("ReConnect"); |
| | | if (LocalIsConnected) |
| | | { |
| | | DebugPrintLog($"局域网——二次发送到网关的主题:{topic}_发送到网关的数据:{System.Text.Encoding.UTF8.GetString(message)}_是否加密:{IsEncry}"); |
| | | await localMqttClient.PublishAsync(new MqttApplicationMessage { Topic = topic, Payload = message, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce, Retain = retain }); |
| | | } |
| | | }
|
| | | }
|
| | | //Log写入(调试用) |
| | | if (Shared.Phone.HdlUserCenterResourse.HideOption.WriteSendAndReceveDataToFile == 1) |
| | | { |
| | | Shared.Phone.HdlLogLogic.Current.WriteLog(2, "本地连接异常断开"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | |
| | | public async System.Threading.Tasks.Task Send(string topic, string message, bool retain = false) |
| | | { |
| | | if (string.IsNullOrEmpty(message)) |
| | | {
|
| | | { |
| | | return; |
| | | } |
| | | await Send(topic, System.Text.Encoding.UTF8.GetBytes(message), retain); |
| | | }
|
| | |
|
| | | } |
| | | |
| | | /// <summary> |
| | | /// 强制指定使用本地局域网发送消息到服务器 |
| | | /// </summary> |
| | |
| | | if (Shared.Common.Config.Instance.HomeId == "") |
| | | { |
| | | return; |
| | | }
|
| | |
|
| | | DebugPrintLog($"局域网——发送到网关的主题:{topic}_发送到网关的数据:{System.Text.Encoding.UTF8.GetString(message)}_是否加密:{IsEncry}");
|
| | |
|
| | | if (IsEncry)
|
| | | {
|
| | | //文件流不用加密
|
| | | if (topic != "FileTransfer/SendFile")
|
| | | {
|
| | | message = SecuritySet.AesEncryptBytes(message, password);
|
| | | }
|
| | | }
|
| | | 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)
|
| | | {
|
| | | DebugPrintLog($"局域网——二次发送到网关的主题:{topic}_发送到网关的数据:{System.Text.Encoding.UTF8.GetString(message)}_是否加密:{IsEncry}");
|
| | | await localMqttClient.PublishAsync(new MqttApplicationMessage { Topic = topic, Payload = message, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce, Retain = retain });
|
| | | }
|
| | | }
|
| | | } |
| | | |
| | | DebugPrintLog($"局域网——发送到网关的主题:{topic}_发送到网关的数据:{System.Text.Encoding.UTF8.GetString(message)}_是否加密:{IsEncry}"); |
| | | |
| | | if (IsEncry) |
| | | { |
| | | //文件流不用加密 |
| | | if (topic != "FileTransfer/SendFile") |
| | | { |
| | | message = SecuritySet.AesEncryptBytes(message, password); |
| | | } |
| | | } |
| | | 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) |
| | | { |
| | | DebugPrintLog($"局域网——二次发送到网关的主题:{topic}_发送到网关的数据:{System.Text.Encoding.UTF8.GetString(message)}_是否加密:{IsEncry}"); |
| | | await localMqttClient.PublishAsync(new MqttApplicationMessage { Topic = topic, Payload = message, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce, Retain = retain }); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | |
| | | } |
| | | if (topics[2] == "NotifyGateWayInfoChange") |
| | | { |
| | | initGateWayBaseInfomation(); |
| | | InitGateWayBaseInfomation(); |
| | | return; |
| | | } |
| | | if (topics[2] == "Common") |
| | |
| | | } |
| | | else |
| | | { |
| | | foreach (var key in GateWayBaseInfomations.Keys) |
| | | foreach (var key in DicGatewayBaseInfo.Keys) |
| | | { |
| | | var value = GateWayBaseInfomations[key]; |
| | | if (value.MacMark == macMark) |
| | | var value = DicGatewayBaseInfo[key]; |
| | | if (value.Id == macMark) |
| | | { |
| | | topic = $"{key}/{topic}"; |
| | | message = System.Text.Encoding.UTF8.GetString(ZigBee.Common.SecuritySet.AesDecryptBytes(e.ApplicationMessage.Payload, value.AesKey)); |
| | |
| | | payloadString = System.Text.Encoding.UTF8.GetString(Common.SecuritySet.AesDecryptBytes(e.ApplicationMessage.Payload, Password)); |
| | | } |
| | | } |
| | | else
|
| | | {
|
| | | payloadString = System.Text.Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
|
| | | else |
| | | { |
| | | payloadString = System.Text.Encoding.UTF8.GetString(e.ApplicationMessage.Payload); |
| | | } |
| | | DebugPrintLog($"网关返回的主题:{topic}_网关返回的负载:{payloadString}"); |
| | | ReceiveMessage(topic, payloadString, e.ApplicationMessage.Payload); |
| | |
| | | epoint = topic.Split('/')[3]; |
| | | cluID = topic.Split('/')[4]; |
| | | attrId = topic.Split('/')[5]; |
| | | }
|
| | |
|
| | | //Log写入(调试用)
|
| | | if (Shared.Phone.UserCenter.UserCenterResourse.HideOption.WriteSendAndReceveDataToFile == 1)
|
| | | {
|
| | | string text = "网关回复:" + topic + "\r\n";
|
| | | text += message + "\r\n";
|
| | | Shared.Phone.UserCenter.HdlLogLogic.Current.WriteLog(2, text);
|
| | | }
|
| | |
|
| | | //全局接收网关推送的的逻辑(为了执行速度,尽可能的别加耗时的操作)
|
| | | Shared.Phone.UserCenter.HdlGatewayReceiveLogic.Current.GatewayOverallMsgReceive(gatewayID, topic, reportStatus, message); |
| | | } |
| | | |
| | | //Log写入(调试用) |
| | | if (Shared.Phone.HdlUserCenterResourse.HideOption.WriteSendAndReceveDataToFile == 1) |
| | | { |
| | | string text = "网关回复:" + topic + "\r\n"; |
| | | text += message + "\r\n"; |
| | | Shared.Phone.HdlLogLogic.Current.WriteLog(2, text); |
| | | } |
| | | |
| | | //全局接收网关推送的的逻辑(为了执行速度,尽可能的别加耗时的操作) |
| | | Shared.Phone.HdlGatewayReceiveLogic.Current.GatewayOverallMsgReceive(gatewayID, topic, reportStatus, message); |
| | | |
| | | var gwa = GateWayList.Find(obj => obj.GwId == gatewayID); |
| | | if (gwa == null) |
| | |
| | | else |
| | | { |
| | | jobject = Newtonsoft.Json.Linq.JObject.Parse(message); |
| | | }
|
| | |
|
| | | } |
| | | |
| | | #region 远程,主网关上报通知 |
| | | if (IsRemote) |
| | | { |
| | |
| | | var gwList = GateWayList.FindAll(obj => obj.HomeId == Shared.Common.Config.Instance.HomeId); |
| | | for (int i = 0; i < gwList.Count; i++) |
| | | { |
| | | if (gwList[i].GwId == gatewayID)
|
| | | {
|
| | | gwList[i].IsMainGateWay = true;
|
| | | if (gwList[i].GwId == gatewayID) |
| | | { |
| | | gwList[i].IsMainGateWay = true; |
| | | } |
| | | else
|
| | | {
|
| | | gwList[i].IsMainGateWay = false;
|
| | | else |
| | | { |
| | | gwList[i].IsMainGateWay = false; |
| | | } |
| | | } |
| | | } |
| | |
| | | var tempEpoint = jobject.Value<int>("Epoint"); |
| | | var dataId = jobject.Value<int>("Data_ID"); |
| | | |
| | | var tempDevice = new CommonDevice { DeviceID = deviceID, DeviceAddr = deviceAddr, DeviceEpoint = tempEpoint };
|
| | | tempDevice.DeviceStatusReport = Newtonsoft.Json.JsonConvert.DeserializeObject<CommonDevice.DeviceStatusReportData>(jobject["Data"].ToString());
|
| | | var tempDevice = new CommonDevice { DeviceID = deviceID, DeviceAddr = deviceAddr, DeviceEpoint = tempEpoint }; |
| | | tempDevice.DeviceStatusReport = Newtonsoft.Json.JsonConvert.DeserializeObject<CommonDevice.DeviceStatusReportData>(jobject["Data"].ToString()); |
| | | UpdateDeviceInfo(tempDevice, "DeviceStatusReport"); |
| | | } |
| | | #endregion |
| | |
| | | UpdateDeviceInfo(doorLock, "DoorLockProgrammingEventNotificationCommand"); |
| | | break; |
| | | } |
| | | }
|
| | | } |
| | | #endregion |
| | | #region IAS安防信息上报 |
| | |
|
| | | //2020.05.11 删除
|
| | |
|
| | | |
| | | //2020.05.11 删除 |
| | | |
| | | #endregion |
| | | #region 下载进度上报 |
| | | else if (topic == gatewayID + "/" + "DownloadFile_Progress") |
| | |
| | | { |
| | | //上报类型通知 |
| | | if (gwa.ReportAction != null) |
| | | {
|
| | | var clientDataPassthrough = Newtonsoft.Json.JsonConvert.DeserializeObject<CommonDevice.ClientDataPassthroughResponseData>(jobject["Data"].ToString());
|
| | | if (clientDataPassthrough != null)
|
| | | {
|
| | | DebugPrintLog("DeviceRequestAcUpdateData");
|
| | | gwa.ReportAction("DeviceRequestAcUpdateData", clientDataPassthrough);
|
| | | { |
| | | var clientDataPassthrough = Newtonsoft.Json.JsonConvert.DeserializeObject<CommonDevice.ClientDataPassthroughResponseData>(jobject["Data"].ToString()); |
| | | if (clientDataPassthrough != null) |
| | | { |
| | | DebugPrintLog("DeviceRequestAcUpdateData"); |
| | | gwa.ReportAction("DeviceRequestAcUpdateData", clientDataPassthrough); |
| | | } |
| | | } |
| | | } |