| | |
| | | public class Control |
| | | { |
| | | |
| | | |
| | | static Control _control; |
| | | public static Control Ins |
| | | { |
| | |
| | | return _control; |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// 记录接收到的消息,方便zb的工程师调试他们的设备 |
| | | /// </summary> |
| | | public List<string> MsgInfoList = new List<string>(); |
| | | |
| | | int _msg_id = 1; |
| | | /// <summary> |
| | | /// 通讯ID |
| | |
| | | /// 是否搜索本地网关成功 |
| | | /// </summary> |
| | | public bool IsSearchLocalGatewaySuccessful = false; |
| | | |
| | | /// <summary> |
| | | /// 是否本地加密,目前只对A网关有用 |
| | | /// </summary> |
| | | public bool IsLocalEncrypt; |
| | | /// <summary> |
| | | /// 判断是否本地加密并且加密key不为空 |
| | | /// </summary> |
| | | public bool IsLocalEncryptAndGetAesKey { |
| | | get { |
| | | return IsLocalEncrypt && (!string.IsNullOrEmpty(DB_ResidenceData.Instance.CurrentRegion.localSecret)); |
| | | } |
| | | } |
| | | |
| | | bool _GatewayOnline_Local = false; |
| | | /// <summary> |
| | | /// 网关在线-局域网 |
| | |
| | | else if (DB_ResidenceData.Instance.GatewayType == 1) |
| | | { |
| | | new Control_Udp().SearchLocalGateway(); |
| | | new Control_Udp().SearchLocalGateway(true); |
| | | } |
| | | System.Threading.Thread.Sleep(500); |
| | | } |
| | |
| | | } |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// 安防控制 |
| | | /// </summary> |
| | | public void ControlArm() |
| | | { |
| | | DAL.Server.HttpServerRequest httpServer = new DAL.Server.HttpServerRequest(); |
| | | //var pack = httpServer.GetSecurityAlarmLogList |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 发送命令 |
| | |
| | | /// <param name="function"></param> |
| | | /// <param name="useRemote">是否直接使用远程发送</param> |
| | | /// <returns></returns> |
| | | public void SendWriteCommand(Function function, Dictionary<string, string> commandDictionary, bool useRemote = false) |
| | | public void SendWriteCommand(Function function, Dictionary<string, string> commandDictionary, bool useRemote = false,int resend = 3) |
| | | { |
| | | function.controlCounter++; |
| | | function.refreshTime = DateTime.Now; |
| | |
| | | switch (function.spk) |
| | | { |
| | | case SPK.ElectricTuyaAirCleaner: |
| | | case SPK.ElectricTuyaAirCleaner2: |
| | | case SPK.ElectricTuyaFan: |
| | | case SPK.ElectricTuyaFan2: |
| | | case SPK.ElectricTuyaWaterValve: |
| | | case SPK.ElectricTuyaWeepRobot: |
| | | case SPK.ElectricTuyaWeepRobot2: |
| | | useRemote = true; |
| | | break; |
| | | } |
| | |
| | | var functionControlDataObj = function.GetGatewayAlinkControlData(commandDictionary); |
| | | var functionControlDataJson = Newtonsoft.Json.JsonConvert.SerializeObject(functionControlDataObj); |
| | | var sendBytes = Ins.ConvertSendBodyData(CommunicationTopic.ct.ControlFunctionTopic, functionControlDataJson); |
| | | new Control_Udp().SendLocalHdlLinkData(sendBytes, functionControlDataObj.id); |
| | | new Control_Udp().SendLocalHdlLinkData(sendBytes, functionControlDataObj.id,resend); |
| | | MainPage.Log($"本地通讯 发送HDL-Link数据:{functionControlDataJson}"); |
| | | } |
| | | } |
| | |
| | | var actionObjs = new List<ApiAlinkControlActionObj>(); |
| | | actionObjs.Add(apiControlData); |
| | | var pack = httpServer.ControlDevice(actionObjs); |
| | | MainPage.Log($"远程控制反馈:{pack.message}"); |
| | | } |
| | | |
| | | } |
| | |
| | | { |
| | | id = Ins.msg_id.ToString(), |
| | | objects = new List<Dictionary<string, string>>() |
| | | { |
| | | readKey |
| | | }, |
| | | { |
| | | readKey |
| | | }, |
| | | time_stamp = Utlis.GetTimestamp() |
| | | }; |
| | | var functionControlDataJson = Newtonsoft.Json.JsonConvert.SerializeObject(readDataObj); |
| | |
| | | var pm = new DAL.Server.HttpServerRequest(); |
| | | var pack = pm.RefreshDeviceStatus(new List<string>() { function.deviceId }); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 安防控制 |
| | | /// </summary> |
| | | public void ControlSecurity(SecurityAlarm securityAlarm,string state) |
| | | { |
| | | if (!Ins.GatewayOnline_Local)//网关本地不在线 |
| | | { |
| | | var pm = new DAL.Server.HttpServerRequest(); |
| | | var result = pm.SetSecurityStatus(new List<SecurityState>() { new SecurityState() { |
| | | gatewayId = DB_ResidenceData.Instance.HomeGateway.gatewayId, |
| | | sid = securityAlarm.sid, status = state, userSecurityId = securityAlarm.userSecurityId |
| | | } }); |
| | | MainPage.Log($"安防控制结果:{result.Code}"); |
| | | } |
| | | else |
| | | { |
| | | Dictionary<string, string> keys = new Dictionary<string, string>(); |
| | | keys.Add("sid", securityAlarm.sid); |
| | | keys.Add("status", state); |
| | | keys.Add("alarm", securityAlarm.alarm.ToString()); |
| | | var aLinkData = new AlinkReadFunctionStatusObj() |
| | | { |
| | | id = Ins.msg_id.ToString(), |
| | | objects = new List<Dictionary<string, string>>() |
| | | { |
| | | keys |
| | | }, |
| | | time_stamp = Utlis.GetTimestamp() |
| | | }; |
| | | var aLinkJson = Newtonsoft.Json.JsonConvert.SerializeObject(aLinkData); |
| | | var sendBytes = Ins.ConvertSendBodyData(CommunicationTopic.ct.ControlSeurity, aLinkJson); |
| | | new Control_Udp().SendLocalHdlLinkData(sendBytes, aLinkData.id); |
| | | } |
| | | } |
| | | |
| | |
| | | }; |
| | | var aLinkJson = Newtonsoft.Json.JsonConvert.SerializeObject(aLinkData); |
| | | var sendBytes = Ins.ConvertSendBodyData(CommunicationTopic.ct.ControlScene, aLinkJson); |
| | | new Control_Udp().SendLocalHdlLinkData(sendBytes, aLinkData.id); |
| | | new Control_Udp().SendLocalHdlLinkData(sendBytes, aLinkData.id,0); |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// 网关进入配网模式 |
| | | /// </summary> |
| | | public void AuthGateway() |
| | | { |
| | | var objects1 = new { spk = "", time = "180" }; |
| | | //{"objects":[{"spk":"","time":"180"}],"id":"8","time_stamp":"1635241216669"} |
| | | var sendId = Ins.msg_id.ToString(); |
| | | var sendObj = new { objects = objects1, id = sendId, time_stamp = Utlis.GetTimestamp() }; |
| | | |
| | | var aLinkJson = Newtonsoft.Json.JsonConvert.SerializeObject(sendObj); |
| | | var sendBytes = Ins.ConvertSendBodyData(CommunicationTopic.ct.AuthGateway, aLinkJson); |
| | | new Control_Udp().SendLocalHdlLinkData(sendBytes, Ins.msg_id.ToString()); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 转换发送数据 |
| | | /// </summary> |
| | | public byte[] ConvertSendBodyData(string topic, string bodyDataString) |
| | | /// <param name="topic">主题</param> |
| | | /// <param name="bodyDataString">body内容数据</param> |
| | | /// <param name="isEncryption">是否要对body加密</param> |
| | | /// <returns></returns> |
| | | public byte[] ConvertSendBodyData(string topic, string bodyDataString, bool isEncryption = true) |
| | | { |
| | | string topicString = "Topic:" + topic + "\r\n"; |
| | | byte[] bodyBytes = Encoding.ASCII.GetBytes(bodyDataString); |
| | | string lengthString = "Length:" + bodyBytes.Length.ToString() + "\r\n" + "\r\n"; |
| | | //string topicString = "Topic:" + topic + "\r\n"; |
| | | //byte[] bodyBytes = Encoding.ASCII.GetBytes(bodyDataString); |
| | | //string lengthString = "Length:" + bodyBytes.Length.ToString() + "\r\n" + "\r\n"; |
| | | |
| | | string sendDataString = topicString + lengthString + bodyDataString; |
| | | byte[] sendDataBytes = Encoding.ASCII.GetBytes(sendDataString); |
| | | MainPage.Log($"转换HDL-Link数据\r\n{sendDataString}\r\n"); |
| | | //string sendDataString = topicString + lengthString + bodyDataString; |
| | | //byte[] sendDataBytes = Encoding.ASCII.GetBytes(sendDataString); |
| | | //MainPage.Log($"转换HDL-Link数据\r\n{sendDataString}\r\n"); |
| | | |
| | | //*************************************************************** |
| | | //2021-09-23 增加本地通信加密处理 |
| | | //1.拼接头 |
| | | string topicString = "Topic:" + topic + "\r\n"; |
| | | //2.Body字符串转为byte数组 |
| | | byte[] bodyBytes = Encoding.UTF8.GetBytes(bodyDataString); |
| | | //判断是否需加密Body数据 |
| | | if (isEncryption && IsLocalEncryptAndGetAesKey) |
| | | { |
| | | bodyBytes = Securitys.EncryptionService.AesEncryptPayload(bodyBytes, DB_ResidenceData.Instance.CurrentRegion.localSecret); |
| | | //bodyDataString = Encoding.UTF8.GetString(bodyBytes); |
| | | //MainPage.Log($"转换HDL-Link数据 加密key:" + DB_ResidenceData.Instance.CurrentRegion.localSecret); |
| | | } |
| | | //3.拼接body的Length长度数据 |
| | | string lengthString = "Length:" + bodyBytes.Length.ToString() + "\r\n" + "\r\n"; |
| | | string topicAndLengthString = topicString + lengthString; |
| | | byte[] topicAndLengthBytes = Encoding.UTF8.GetBytes(topicAndLengthString); |
| | | //4.拼接合并 Topic 和 body的byte数组数据 |
| | | byte[] sendDataBytes = new byte[topicAndLengthBytes.Length + bodyBytes.Length]; |
| | | topicAndLengthBytes.CopyTo(sendDataBytes, 0); |
| | | bodyBytes.CopyTo(sendDataBytes, topicAndLengthBytes.Length); |
| | | |
| | | //var sendDataString = Encoding.UTF8.GetString(sendDataBytes); |
| | | //MainPage.Log($"转换HDL-Link数据\r\n{sendDataString}\r\n"); |
| | | //*************************************************************** |
| | | |
| | | return sendDataBytes; |
| | | } |
| | |
| | | /// 转换接收到的数据 |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | public void ConvertReceiveData(byte[] receiveBytes) |
| | | public void ConvertReceiveData(byte[] receiveBytes,string ip) |
| | | { |
| | | var reString = Encoding.UTF8.GetString(receiveBytes); |
| | | AnalysisReceiveData(reString); |
| | | AnalysisReceiveData(reString, receiveBytes,ip); |
| | | } |
| | | /// <summary> |
| | | /// 转换接收到的数据 |
| | | /// </summary> |
| | | /// <param name="receiveString">转String后的数据</param> |
| | | /// <param name="originalReceiveBytes"原始Bytes数据</param> |
| | | /// <returns></returns> |
| | | public LocalCommunicationData AnalysisReceiveData(string receiveString) |
| | | public LocalCommunicationData AnalysisReceiveData(string receiveString, byte[] originalReceiveBytes , string sIp = null) |
| | | { |
| | | LocalCommunicationData receiveObj = new LocalCommunicationData(); |
| | | |
| | | MainPage.Log($"局域网信息: \r\n{receiveString}"); |
| | | |
| | | var res = receiveString.Split("\r\n\r\n"); |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | MainPage.Log($"局域网信息: {receiveObj.Topic} : 内容: {res[1]}"); |
| | | |
| | | //MainPage.Log($"局域网信息: {receiveObj.Topic} : 内容: {res[1]}"); |
| | | |
| | | //验证有效数据长度 |
| | | //if (res[1].Length != receiveObj.Length) |
| | |
| | | //} |
| | | receiveObj.BodyDataString = res[1]; |
| | | |
| | | if (receiveObj.Topic == CommunicationTopic.SearchLoaclGatewayReply) |
| | | //2021-09-23 过滤不需要解密的主题 目前搜索网关主题不加密 |
| | | if (receiveObj.Topic != CommunicationTopic.SearchLoaclGatewayReply) |
| | | { |
| | | //判断当前网关是否开启了本地加密 |
| | | if (IsLocalEncryptAndGetAesKey) |
| | | { |
| | | MainPage.Log($"局域网信息 开始解密"); |
| | | if (originalReceiveBytes != null) |
| | | { |
| | | //拿到原始Bytes数据去解密 |
| | | byte[] topicBytes = Encoding.UTF8.GetBytes(res[0]); |
| | | byte[] bodyBytes = new byte[receiveObj.Length]; |
| | | Array.Copy(originalReceiveBytes, topicBytes.Length + 4, bodyBytes, 0, receiveObj.Length); |
| | | byte[] receiveBytes = Securitys.EncryptionService.AesDecryptPayload(bodyBytes, DB_ResidenceData.Instance.CurrentRegion.localSecret); |
| | | var revString = Encoding.UTF8.GetString(receiveBytes); |
| | | receiveObj.BodyDataString = revString; |
| | | MainPage.Log($"局域网信息: 解密后:" + receiveObj.BodyDataString); |
| | | if(receiveObj.Topic.EndsWith("/thing/property/up")) |
| | | { |
| | | MsgInfoList.Add(revString + "\r\n"); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | //目前不拿原始Bytes数据 解密不了 |
| | | //byte[] receiveBytes = Encoding.UTF8.GetBytes(res[1]); |
| | | //MainPage.Log($"局域网信息 receiveBytes {receiveBytes.Length}"); |
| | | //receiveBytes = Securitys.EncryptionService.AesDecryptPayload(receiveBytes, DB_ResidenceData.Instance.CurrentRegion.localSecret); |
| | | //MainPage.Log($"局域网信息 解密后:receiveBytes {receiveBytes.Length}"); |
| | | //var revString = Encoding.UTF8.GetString(receiveBytes); |
| | | //receiveObj.BodyDataString = revString; |
| | | //MainPage.Log($"局域网信息: 解密后:" + receiveObj.BodyDataString); |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | |
| | | if (receiveObj.Topic == CommunicationTopic.SearchLoaclGatewayReply || receiveObj.Topic == CommunicationTopic.GatewayBroadcast) |
| | | { |
| | | |
| | | var bodyJObj = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponsePack>(res[1]); |
| | | if (bodyJObj == null) |
| | | { |
| | |
| | | { |
| | | Ins.GatewayId = device.device_mac; |
| | | } |
| | | reportIp = "239.0.168.188";// device.ip_address;//主播地址也能控制设备 |
| | | if (!string.IsNullOrEmpty(sIp)) |
| | | { |
| | | device.ip_address = sIp; |
| | | } |
| | | reportIp = device.ip_address;//主播地址也能控制设备//"239.0.168.188";// |
| | | //2021-09-23 新增获取当前网关是否本地加密 |
| | | Ins.IsLocalEncrypt = device.isLocalEncrypt; |
| | | //MainPage.Log("网关本地加密状态:" + device.local_encrypt.ToString()); |
| | | } |
| | | } |
| | | else if (receiveObj.Topic == CommunicationTopic.ct.ReadStatus + "_reply" || |
| | | receiveObj.Topic == CommunicationTopic.ct.ControlFunctionTopic + "_reply" || |
| | | receiveObj.Topic == CommunicationTopic.ct.GatewayUpStatus) |
| | | receiveObj.Topic == CommunicationTopic.ct.GatewayUpStatus || |
| | | receiveObj.Topic.Contains( CommunicationTopic.ct.GatewayUpSortTopic)) |
| | | { |
| | | //TODO 暂时不传正确的数据上去,如果后面要优化前面这些代码 |
| | | UpdataFunctionStatus(receiveObj.BodyDataString, null); |
| | | } |
| | | else if (receiveObj.Topic == CommunicationTopic.ct.ControlSeurity +"_reply" |
| | | || receiveObj.Topic == CommunicationTopic.ct.ReadSecurityStatus + "_reply" |
| | | || receiveObj.Topic == CommunicationTopic.ct.SecurityStatusUp) |
| | | { |
| | | try |
| | | { |
| | | MainPage.Log($"局域网安防信息: {receiveObj.Topic} : 内容: {res[1]}"); |
| | | var tt = ""; |
| | | lock (tt) { |
| | | var temp = Newtonsoft.Json.JsonConvert.DeserializeObject<SecurityStatusObj>(receiveObj.BodyDataString); |
| | | if (temp != null) |
| | | { |
| | | Control_Udp.ReceiveRepeatManager(temp.id, null); |
| | | foreach (var updataSecurity in temp.objects) |
| | | { |
| | | var updataLocalSecurity = FunctionList.List.securities.Find((obj) => obj.sid == updataSecurity.sid); |
| | | if (updataLocalSecurity != null) |
| | | { |
| | | updataLocalSecurity.status = updataSecurity.status; |
| | | updataLocalSecurity.alarm = updataSecurity.alarm; |
| | | ArmCenterPage.LoadEvent_RefreshSecurityStatus(updataLocalSecurity); |
| | | } |
| | | } |
| | | HomePage.LoadEvent_RefreshSecurityStatus(); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex){ |
| | | MainPage.Log($"安防局域网异常:{ex.Message}"); |
| | | } |
| | | } |
| | | else |
| | | { |
| | |
| | | return; |
| | | } |
| | | } |
| | | MainPage.Log($"A协议更新状态:{revString}"); |
| | | //MainPage.Log($"A协议更新状态:{revString}"); |
| | | foreach (var attr in updateTemp.status) |
| | | { |
| | | localFunction.time_stamp = temp.time_stamp; |
| | |
| | | } |
| | | |
| | | //更新界面状态 |
| | | Function localObj = null; |
| | | switch (localFunction.spk) |
| | | { |
| | | case SPK.AirSwitch: |
| | | AirSwitchPage.UpdataState(localFunction); |
| | | if(localFunction.GetAttribute(FunctionAttributeKey.Power)!=null)//如果是带电量的空开也要更新能源界面 |
| | | { |
| | | EnergyMainPage.UpdataStatus(localFunction); |
| | | } |
| | | break; |
| | | case SPK.ElectricEnergy: |
| | | EnergyMainPage.UpdataStatus(localFunction); |
| | | break; |
| | |
| | | DimmerPage.UpdataStates(localFunction); |
| | | break; |
| | | case SPK.ElectricFan: |
| | | case SPK.HvacFan: |
| | | localFunction.lastState = Language.StringByID(StringId.Level) + " : " + |
| | | localFunction.GetAttrState(FunctionAttributeKey.OpenLevel); |
| | | FanPage.UpdataState(localFunction); |
| | |
| | | case SPK.CurtainShades: |
| | | break; |
| | | case SPK.AcStandard: |
| | | case SPK.HvacAC: |
| | | case SPK.AcIr: |
| | | Stan.HdlDeviceStatuPushLogic.Current.UpdateDeviceStatu(updateTemp.sid, updateTemp.status); |
| | | if (localFunction != null) |
| | | { |
| | |
| | | break; |
| | | } |
| | | localFunction.lastState += " " + localFunction.GetAttrState(FunctionAttributeKey.SetTemp) + new AC().GetTempUnitString(localFunction); |
| | | ACPage.UpdataStates(localFunction); |
| | | |
| | | } |
| | | break; |
| | | case SPK.HvacFloorHeat: |
| | | case SPK.FloorHeatStandard: |
| | | localFunction.lastState = ""; |
| | | switch (localFunction.GetAttrState(FunctionAttributeKey.Mode)) |
| | | { |
| | | case "normal": |
| | |
| | | case SPK.SensorTVOC: |
| | | case SPK.SensorTemperature: |
| | | case SPK.SensorHumidity: |
| | | case SPK.SensorHcho: |
| | | if(localFunction.spk == SPK.SensorTemperature) |
| | | { |
| | | HomePage.LoadEvent_RefreshEnvirIndoorTemp(); |
| | |
| | | HomePage.LoadEvent_RefreshEnvirIndoorHumi(); |
| | | } |
| | | EnvironmentalPage.LoadEvent_UpdataStatus(localFunction); |
| | | //A_EnvironmentalDataCenter.LoadEvent_UpdataStatus(localFunction); |
| | | break; |
| | | case SPK.SensorEnvironment: |
| | | case SPK.SensorEnvironment2: |
| | | case SPK.SensorEnvironment3: |
| | | if (localFunction.GetAttributes().Contains(FunctionAttributeKey.Temperature)) |
| | | { |
| | | HomePage.LoadEvent_RefreshEnvirIndoorTemp(); |
| | |
| | | HomePage.LoadEvent_RefreshEnvirIndoorHumi(); |
| | | } |
| | | EnvironmentalPage.LoadEvent_UpdataStatus(localFunction); |
| | | //A_EnvironmentalDataCenter.LoadEvent_UpdataStatus(localFunction); |
| | | break; |
| | | case SPK.ElectricSocket: |
| | | case SPK.PanelSocket: |
| | | SocketPage.UpdataState(localFunction); |
| | | break; |
| | | case SPK.ElectricTV: |
| | | break; |
| | | case SPK.ElectricTuyaAirCleaner: |
| | | case SPK.ElectricTuyaAirCleaner2: |
| | | case SPK.ElectricTuyaFan: |
| | | case SPK.ElectricTuyaFan2: |
| | | case SPK.ElectricTuyaWeepRobot: |
| | | case SPK.ElectricTuyaWeepRobot2: |
| | | case SPK.ElectricTuyaWaterValve: |
| | | case SPK.ElectricTuyaWaterValve2: |
| | | case SPK.SensorPir: |
| | | case SPK.SensorDoorWindow: |
| | | case SPK.SensorSmoke: |
| | | case SPK.SensorWater: |
| | | case SPK.ClothesHanger: |
| | | case SPK.AcIr: |
| | | case SPK.SenesorMegahealth: |
| | | case SPK.SenesorMegahealth2: |
| | | case SPK.AirFreshStandard: |
| | | case SPK.HvacAirFresh: |
| | | case SPK.SensorGas: |
| | | //设备状态推送 |
| | | //状态更新 |
| | | Stan.HdlDeviceStatuPushLogic.Current.UpdateDeviceStatu(updateTemp.sid, updateTemp.status); |