using System; using System.Collections.Generic; using System.Text; using HDL_ON.Entity; using HDL_ON.UI; using Shared; namespace HDL_ON.DriverLayer { /// /// 通讯方式 /// public enum CommunicationMode { none, /// /// 本地udp /// local_BusUdp, /// /// 本地tcp客户端 /// tcp_local_client, } public class Control { static Control _control; public static Control Ins { get { if (_control == null) { _control = new Control(); } return _control; } } int _msg_id = 1; /// /// 通讯ID /// public int msg_id { get { return _msg_id++; } } /// /// 获取13位时间戳 /// /// public string Get_TimeStamp() { long t = DateTime.Now.Ticks / 10000; return t.ToString(); } /// /// 是否搜索本地网关成功 /// public bool IsSearchLocalGatewaySuccessful = false; /// /// /// bool _gatewayOnline = false; /// /// 网关是否在线 /// public bool GatewayOnline { get { return _gatewayOnline; } set { if (_gatewayOnline != value) { _gatewayOnline = value; //修改主页连接状态 UI.HomePage.LoadEvent_CheckLinkStatus(); if (value) { MainPage.Log($"网关在线,刷新设备状态"); new System.Threading.Thread(() => { System.Threading.Thread.Sleep(1000); FunctionList.List.ReadAllFunctionStatus(); }) { IsBackground = true, Priority = System.Threading.ThreadPriority.AboveNormal }.Start(); } } } } /// /// 网关通讯ID /// public string GatewayId = ""; bool _isRemote = false; /// /// 是否为远程连接 /// public bool IsRemote { get { return _isRemote; } set { _isRemote = value; //修改主页连接状态 HomePage.LoadEvent_CheckLinkStatus(); } } /// /// 通讯地址IP /// public string reportIp = "255.255.255.255"; /// /// tcp服务端 /// public Control_TcpServer myTcpServer = null; /// /// tcp客服端 /// public Control_TcpClient myTcpClient = null; /// /// 本地udp /// public Control_Udp myUdp1 = null; /// /// 通讯方式 /// public CommunicationMode communicationMode; /// /// 打开tcp服务端 /// public void OpenTcpServer() { myTcpServer = new Control_TcpServer(); myTcpServer.OpenServer(); } /// /// 打开Udp /// public void OpenUdp(int port) { UdpSocket._BusSocket.Start(port); } /// /// 关闭udp /// public void CloseUdp() { UdpSocket._BusSocket.Stop(); } /// /// 打开tcp客服端 /// public void OpenTcpClent() { if (myTcpClient == null) { myTcpClient = new Control_TcpClient(reportIp); myTcpClient.Connect(); } } /// /// 搜索本地网关列表 /// public void SearchLoaclGateway() { MainPage.Log($"搜索本地网关列表,网关类型:{DB_ResidenceData.Instance.GatewayType}"); if (MainPage.InternetStatus == 0) { Ins.GatewayOnline = false; return; } else if (MainPage.InternetStatus == 1) { if (!Ins.IsRemote) { Ins.IsRemote = true; DAL.Mqtt.MqttClient.InitState(); } } else if (MainPage.InternetStatus == 2) { OpenUdp(DB_ResidenceData.Instance.GatewayType == 0 ? 6000 : 8585); //重置搜索网关标志 IsSearchLocalGatewaySuccessful = false; new System.Threading.Thread(() => { for (int i = 0; i < 5; i++) { if (IsSearchLocalGatewaySuccessful) break; if (DB_ResidenceData.Instance.GatewayType == 0) { new Control_Udp().ControlBytesSend(Command.ReadGateway, 255, 255, new byte[] { (byte)new Random().Next(255), (byte)new Random().Next(255) }); } else if (DB_ResidenceData.Instance.GatewayType == 1) { new Control_Udp().SearchLocalGateway(); } System.Threading.Thread.Sleep(500); } if (!IsSearchLocalGatewaySuccessful) { //本地搜索不到网关 if (!Ins.IsRemote) { Ins.IsRemote = true; DAL.Mqtt.MqttClient.InitState(); } } }) { IsBackground = true }.Start(); } } /// /// 场景控制入口 /// public void ControlScene(Scene scene) { if (Ins.IsRemote || DB_ResidenceData.Instance.GatewayType == 1) { ControlAProtocolScene(scene); } else { if (DB_ResidenceData.Instance.GatewayType == 0) { new Control_Udp().ControlBusScenes(scene); } } } /// /// 发送命令 /// 自动判断是否为A协议设备, /// 不是A协议,自动转化bus命令数据 /// /// /// /// public void SendWriteCommand(Function function, Dictionary commandDictionary) { function.controlCounter++; function.refreshTime = DateTime.Now; //如果是控制调光的开时,亮度值不能为0 if (commandDictionary.Count > 2) { if (commandDictionary.ContainsKey(FunctionAttributeKey.OnOff) && commandDictionary.ContainsKey(FunctionAttributeKey.Brightness)) { if (commandDictionary[FunctionAttributeKey.OnOff] == "on") { if (commandDictionary[FunctionAttributeKey.Brightness] == "0") { commandDictionary[FunctionAttributeKey.Brightness] = "100"; } } if (commandDictionary[FunctionAttributeKey.OnOff] == "off") { if (commandDictionary[FunctionAttributeKey.Brightness] != "0") { commandDictionary[FunctionAttributeKey.Brightness] = "0"; } } } } //远程通讯 if (Ins.IsRemote) { DAL.Server.HttpServerRequest httpServer = new DAL.Server.HttpServerRequest(); //ALink控制、Bus控制使用同一个接口控制,由云端负责解析 var apiControlData = function.GetApiControlData(commandDictionary); var actionObjs = new List(); actionObjs.Add(apiControlData); var pack = httpServer.ControlDevice(actionObjs); //MainPage.Log($"{pack.Code}:{pack.Data}"); } //本地通讯 else { //Bus控制 if (DB_ResidenceData.Instance.GatewayType == 0) { try { new Control_Udp().WriteBusData(function, commandDictionary); } catch (Exception ex) { MainPage.Log($"发送数据异常: {ex.Message}"); } } //ALink控制 else { 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); MainPage.Log($"发送HDL-Link数据:{functionControlDataJson}"); } } } public void SendApiReadCommand(List functionIds) { var pm = new DAL.Server.HttpServerRequest(); var pack = pm.RefreshDeviceStatus(functionIds); } /// /// 发送读取命令 /// 自动判断是否为A协议设备 /// public void SendReadCommand(Function function) { function.refreshTime = DateTime.Now; if (Ins.IsRemote) { var pm = new DAL.Server.HttpServerRequest(); var pack = pm.RefreshDeviceStatus(new List() { function.deviceId }); } else { if (DB_ResidenceData.Instance.GatewayType == 0) { try { new Control_Udp().ReadBusData(function); } catch (Exception ex) { MainPage.Log($"发送数据异常: {ex.Message}"); } } else { var readKey = new Dictionary(); readKey.Add("sid", function.sid); var readDataObj = new AlinkReadFunctionStatusObj() { id = Ins.msg_id.ToString(), objects = new List>() { readKey }, time_stamp = Utlis.GetTimestamp() }; var functionControlDataJson = Newtonsoft.Json.JsonConvert.SerializeObject(readDataObj); var sendBytes = Ins.ConvertSendBodyData(CommunicationTopic.ct.ReadStatus, functionControlDataJson); MainPage.Log($"发送HDL-Link数据:{functionControlDataJson}"); new Control_Udp().SendLocalHdlLinkData(sendBytes, readDataObj.id); } } } ///// ///// 发送A协议读取命令 ///// //public void SendReadCommand(List> keyValuePairs) //{ // var readDataObj = new GatewayAlinkReadObj() // { // id = Ins.msg_id.ToString(), // objects = keyValuePairs, // time_stamp = Utlis.GetTimestamp() // }; // var functionControlDataJson = Newtonsoft.Json.JsonConvert.SerializeObject(readDataObj); // var sendBytes = Ins.ConvertSendBodyData(CommunicationTopic.ct.ReadStatus, functionControlDataJson); // Ins.myUdp.SendLocalHdlLinkData(sendBytes); //} /// /// a协议控制场景 /// /// static void ControlAProtocolScene(Scene scene) { if (Ins.IsRemote) { var pm = new HDL_ON.DAL.Server.HttpServerRequest(); pm.ExecuteScene(scene.userSceneId); } else { Dictionary keys = new Dictionary(); keys.Add("sid", scene.sid); var aLinkData = new AlinkReadFunctionStatusObj() { id = Ins.msg_id.ToString(), objects = new List>() { keys }, time_stamp = Utlis.GetTimestamp() }; var aLinkJson = Newtonsoft.Json.JsonConvert.SerializeObject(aLinkData); var sendBytes = Ins.ConvertSendBodyData(CommunicationTopic.ct.ControlScene, aLinkJson); new Control_Udp().SendLocalHdlLinkData(sendBytes, aLinkData.id); } } /// /// 转换通讯数据 /// public byte[] ConvertSendBodyData(string topic, string bodyDataString) { 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"); return sendDataBytes; } /// /// 转换接收到的数据 /// /// public void ConvertReceiveData(byte[] receiveBytes) { var reString = Encoding.UTF8.GetString(receiveBytes); AnalysisReceiveData(reString); } /// /// 转换接收到的数据 /// /// public LocalCommunicationData AnalysisReceiveData(string receiveString) { LocalCommunicationData receiveObj = new LocalCommunicationData(); var res = receiveString.Split("\r\n\r\n"); if (res.Length == 2) { var topics = res[0].Split("\r\n"); //MainPage.Log(res[1]); foreach (var ts in topics) { var key = ts.Split(":"); switch (key[0]) { case "Topic": receiveObj.Topic = key[1]; break; case "Length": receiveObj.Length = Convert.ToInt32(key[1]); break; } } MainPage.Log($"time 1 :{receiveObj.Topic}"); //验证有效数据长度 //if (res[1].Length != receiveObj.Length) //{ // MainPage.Log($"收到数据包长度不够"); // return receiveObj; //} receiveObj.BodyDataString = res[1]; var bodyJObj = Newtonsoft.Json.JsonConvert.DeserializeObject(res[1]); if (bodyJObj == null) { return receiveObj; } if (receiveObj.Topic == CommunicationTopic.SearchLoaclGatewayReply) { var device = Newtonsoft.Json.JsonConvert.DeserializeObject(bodyJObj.objects.ToString()); if (device.device_mac == DB_ResidenceData.Instance.residenceGatewayMAC) { //本地搜索网关成功 Control.Ins.IsSearchLocalGatewaySuccessful = true; Ins.GatewayOnline = true; if (!string.IsNullOrEmpty(device.gatewayId)) { Ins.GatewayId = device.gatewayId; } else { Ins.GatewayId = device.device_mac; } reportIp = "239.0.168.188";// device.ip_address; Ins.IsRemote = false; } } else if (receiveObj.Topic == CommunicationTopic.ct.ReadStatus + "_reply" || receiveObj.Topic == CommunicationTopic.ct.ControlFunctionTopic + "_reply" || receiveObj.Topic == CommunicationTopic.ct.GatewayUpStatus) { //TODO 暂时不传正确的数据上去,如果后面要优化前面这些代码 UpdataFunctionStatus(receiveObj.BodyDataString, null); } } return receiveObj; } /// /// 更新设备状态 /// A协议数据 /// /// public void UpdataFunctionStatus(string revString, byte[] usefulBytes) { MainPage.Log($"A协议更新状态:{revString}"); var temp = Newtonsoft.Json.JsonConvert.DeserializeObject(revString); if (temp != null) { Control_Udp.ReceiveRepeatManager(temp.id, usefulBytes); var allLocalFuntion = FunctionList.List.GetDeviceFunctionList(); foreach (var updateTemp in temp.objects) { try { //bool hadChange = false;//状态有变化再更新界面 var localFunction = allLocalFuntion.Find((obj) => obj.sid == updateTemp.sid); if (localFunction != null) { //var updateInfoString = $"更新设备:{localFunction.name}"; //foreach (var attr in updateTemp.status) //{ // updateInfoString += $" key:{attr.key};value:{attr.value}"; //} //MainPage.Log(updateInfoString); //更新界面状态 Function localObj = null; switch (localFunction.spk) { case SPK.LightSwitch: var localSwitch = FunctionList.List.lights.Find((obj) => obj.sid == updateTemp.sid); if (localSwitch != null) { localObj = localSwitch; foreach (var attr in updateTemp.status) { var localAttr = localSwitch.attributes.Find((obj) => obj.key == attr.key); if (localAttr != null) { localAttr.curValue = attr.value; } } //rgb.lastState = Language.StringByID(StringId.Brightness) + " : " + rgb.brightness + "%"; RelayPage.UpdataState(localSwitch); } break; case SPK.LightDimming: var dimming = FunctionList.List.lights.Find((obj) => obj.sid == updateTemp.sid); if (dimming != null) { localObj = dimming; foreach (var attr in updateTemp.status) { var localAttr = dimming.attributes.Find((obj) => obj.key == attr.key); if (localAttr != null) { localAttr.curValue = attr.value; } } dimming.lastState = Language.StringByID(StringId.Brightness) + " : " + dimming.brightness + "%"; DimmerPage.UpdataStates(dimming); } break; case SPK.ElectricFan: var fan = FunctionList.List.fans.Find((obj) => obj.sid == updateTemp.sid); if (fan != null) { localObj = fan; foreach (var attr in updateTemp.status) { var localAttr = fan.attributes.Find((obj) => obj.key == attr.key); if (localAttr != null) { localAttr.curValue = attr.value; } } fan.lastState = Language.StringByID(StringId.Level) + " : " + fan.openLevel; FanPage.UpdataState(fan); } break; case SPK.LightRGB: var rgb = FunctionList.List.lights.Find((obj) => obj.sid == updateTemp.sid); if (rgb != null) { localObj = rgb; foreach (var attr in updateTemp.status) { var localAttr = rgb.attributes.Find((obj) => obj.key == attr.key); if (localAttr != null) { localAttr.curValue = attr.value; } } rgb.lastState = Language.StringByID(StringId.Brightness) + " : " + rgb.brightness + "%"; RGBPage.UpdataStates(rgb); } break; case SPK.LightRGBW: break; case SPK.LightCCT: var lightCCT = FunctionList.List.lights.Find((obj) => obj.sid == updateTemp.sid); if (lightCCT != null) { localObj = lightCCT; foreach (var attr in updateTemp.status) { var localAttr = lightCCT.attributes.Find((obj) => obj.key == attr.key); if (localAttr != null) { localAttr.curValue = attr.value; } } lightCCT.lastState = Language.StringByID(StringId.Brightness) + " : " + lightCCT.brightness + "%"; ColorTureLampPage.UpdataStates(lightCCT); } break; case SPK.CurtainSwitch: var curtain = FunctionList.List.curtains.Find((obj) => obj.sid == updateTemp.sid); if (curtain != null) { localObj = curtain; foreach (var attr in updateTemp.status) { var localAttr = curtain.attributes.Find((obj) => obj.key == attr.key); if (localAttr != null) { localAttr.curValue = attr.value; } } curtain.lastState = curtain.trait_on_off.curValue.ToString() == "on" ? Language.StringByID(StringId.Open) : Language.StringByID(StringId.Close); CurtainModulePage.UpdataState(curtain); } break; case SPK.CurtainTrietex: var trietex = FunctionList.List.curtains.Find((obj) => obj.sid == updateTemp.sid); if (trietex != null) { localObj = trietex; foreach (var attr in updateTemp.status) { var localAttr = trietex.attributes.Find((obj) => obj.key == attr.key); if (localAttr != null) { localAttr.curValue = attr.value; } } trietex.lastState = Language.StringByID(StringId.Open) + trietex.percent + "%"; MotorCurtainPage.UpdataState(trietex); } break; case SPK.CurtainRoller: var roller = FunctionList.List.curtains.Find((obj) => obj.sid == updateTemp.sid); if (roller != null) { localObj = roller; foreach (var attr in updateTemp.status) { var localAttr = roller.attributes.Find((obj) => obj.key == attr.key); if (localAttr != null) { localAttr.curValue = attr.value; } } roller.lastState = Language.StringByID(StringId.Open) + roller.percent + "%"; RollingShutterPage.UpdataState(roller); } break; case SPK.CurtainShades: break; case SPK.AcStandard: var ac = FunctionList.List.aCs.Find((obj) => obj.sid == updateTemp.sid); if (ac != null) { localObj = ac; foreach (var attr in updateTemp.status) { var localAttr = ac.attributes.Find((obj) => obj.key == attr.key); if (localAttr != null) { localAttr.curValue = attr.value; } } ac.lastState = ""; switch (ac.trait_mode.curValue.ToString()) { case "cool": ac.lastState = Language.StringByID(StringId.Cool); break; case "heat": ac.lastState = Language.StringByID(StringId.Heat); break; case "dry": ac.lastState = Language.StringByID(StringId.Dry); break; case "auto": ac.lastState = Language.StringByID(StringId.Auto); break; case "fan": ac.lastState = Language.StringByID(StringId.AirSupply); break; } switch (ac.trait_fan.curValue.ToString()) { case "high": ac.lastState += " " + Language.StringByID(StringId.HighWindSpeed); break; case "medium": ac.lastState += " " + Language.StringByID(StringId.MiddleWindSpeed); break; case "low": ac.lastState += " " + Language.StringByID(StringId.LowWindSpeed); break; case "auto": ac.lastState += " " + Language.StringByID(StringId.Auto); break; } ac.lastState += " " + ac.trait_temp.curValue + ac.tempUnitString; ACPage.UpdataStates(ac); } break; case SPK.FloorHeatStandard: var fh = FunctionList.List.floorHeatings.Find((obj) => obj.sid == updateTemp.sid); if (fh != null) { localObj = fh; foreach (var attr in updateTemp.status) { var localAttr = fh.attributes.Find((obj) => obj.key == attr.key); if (localAttr != null) { localAttr.curValue = attr.value; } } switch (fh.trait_mode.curValue) { case "normal": fh.lastState = Language.StringByID(StringId.Normal); break; case "day": fh.lastState = Language.StringByID(StringId.Day); break; case "night": fh.lastState = Language.StringByID(StringId.Night); break; case "timer": fh.lastState = Language.StringByID(StringId.Auto); break; case "away": fh.lastState = Language.StringByID(StringId.Away); break; } fh.lastState += " " + fh.trait_temp.curValue + fh.tempUnitString; FloorHeatingPage.UpdataStates(fh); } break; case SPK.SensorPm25: case SPK.SensorCO2: case SPK.SensorTVOC: case SPK.SensorTemperature: case SPK.SensorHumidity: var sensor = FunctionList.List.sensorsEnvironmentalScience.Find((obj) => obj.sid == updateTemp.sid); if (sensor != null) { localObj = sensor; foreach (var attr in updateTemp.status) { var localAttr = sensor.attributes.Find((obj) => obj.key == attr.key); if (localAttr != null) { localAttr.curValue = attr.value; } } EnvironmentalSciencePage.LoadEvent_UpdataStatus(sensor); } break; case SPK.ElectricSocket: var es = FunctionList.List.switchSockets.Find((obj) => obj.sid == updateTemp.sid); if (es != null) { localObj = es; foreach (var attr in updateTemp.status) { var localAttr = es.attributes.Find((obj) => obj.key == attr.key); if (localAttr != null) { localAttr.curValue = attr.value; } } SocketPage.UpdataState(es); } break; case SPK.ElectricTV: break; default: break; } HomePage.UpdataFunctionStates(localObj); RoomPage.UpdataStates(localObj); FunctionPage.UpdataStates(localObj); ClassificationPage.UpdataInfo(localObj); } } catch (Exception ex) { MainPage.Log($"A协议更新状态异常:{ex.Message}"); } } } } } }