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(); } bool _gatewayOnline = false; /// /// 网关是否在线 /// public bool GatewayOnline { get { return _gatewayOnline; } set { if (_gatewayOnline != value) { _gatewayOnline = value; //修改主页连接状态 UI.HomePage.LoadEvent_CheckLinkStatus(); if (value) { MainPage.Log($"网关在线,刷新设备状态"); FunctionList.List.ReadAllFunctionStatus(); } } } } /// /// 网关通讯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 myUdp = null; /// /// 通讯方式 /// public CommunicationMode communicationMode; /// /// 打开tcp服务端 /// public void OpenTcpServer() { myTcpServer = new Control_TcpServer(); myTcpServer.OpenServer(); } /// /// 打开Udp /// public void OpenUdp(int port) { if (myUdp == null) { myUdp = new Control_Udp(); } UdpSocket._BusSocket.Start(port); } /// /// 关闭udp /// public void CloseUdp() { if (myUdp != null) { myUdp = null; } UdpSocket._BusSocket.Stop(); } /// /// 打开tcp客服端 /// public void OpenTcpClent() { if (myTcpClient == null) { myTcpClient = new Control_TcpClient(reportIp); myTcpClient.Connect(); } } ///// ///// 改变通讯方式 ///// //public void ChangeCommunicationMode(CommunicationMode communicationMode) //{ // this.communicationMode = communicationMode; //} /// /// 搜索本地网关列表 /// public void SearchLoaclGateway() { OpenUdp(DB_ResidenceData.residenceData.GatewayType == 0 ? 6000 : 8585); new System.Threading.Thread(() => { for (int i = 0; i < 5; i++) { if (GatewayOnline) break; if (DB_ResidenceData.residenceData.GatewayType == 0) { myUdp.ControlBytesSend(Command.ReadGateway, 255, 255, new byte[] { (byte)new Random().Next(255), (byte)new Random().Next(255) }); } else if (DB_ResidenceData.residenceData.GatewayType == 1) { myUdp.SearchLocalGateway(); } System.Threading.Thread.Sleep(500); } }) { IsBackground = true }.Start(); if (!GatewayOnline)//网关不在线的时候才可尝试远程连接 { Ins.IsRemote = true; DAL.Mqtt.MqttClient.InitState(); } } /// /// 场景控制入口 /// public void ControlScene(Scene scene) { if(myUdp!=null) { myUdp.ControlBusScenes(scene); } if(myTcpClient!= null) { ControlAProtocolScene(scene); } } /// /// 发送命令 /// 自动判断是否为A协议设备, /// 不是A协议,自动转化bus命令数据 /// /// /// /// public void SendWriteCommand(Function function, Dictionary commandDictionary) { function.usageCount++; function.refreshTime = DateTime.Now; DAL.Server.HttpServerRequest httpServer = new DAL.Server.HttpServerRequest(); //远程通讯 if (Ins.IsRemote) { //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.residenceData.GatewayType == 0) { try { if (myUdp != null) { myUdp.WriteBusData(function, commandDictionary); } } catch (Exception ex) { MainPage.Log($"发送数据异常: {ex.Message}"); } } //ALink控制 else { if (myUdp != null) { var functionControlDataObj = function.GetGatewayAlinkControlData(commandDictionary); var functionControlDataJson = Newtonsoft.Json.JsonConvert.SerializeObject(functionControlDataObj); var sendBytes = Ins.ConvertSendBodyData(CommunicationTopic.ct.ControlFunctionTopic, functionControlDataJson); myUdp.SendLocalHdlLinkData(sendBytes); } } } } 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.residenceData.GatewayType == 0) { try { Ins.myUdp.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); Ins.myUdp.SendLocalHdlLinkData(sendBytes); } } } ///// ///// 发送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) { var sendSidObj = new AProtocolSendingObject(); sendSidObj.time_stamp = ""; sendSidObj.type = "device_sid"; sendSidObj.command = "get_list_response"; } /// /// 转换通讯数据 /// 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; } } //验证有效数据长度 //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.residenceData.residenceGatewayMAC) { 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.GatewayUpStatus) { UpdataFunctionStatus(receiveObj.BodyDataString); } } return receiveObj; } /// /// 更新设备状态 /// A协议数据 /// /// public void UpdataFunctionStatus(string revString) { MainPage.Log($"A协议更新状态:{revString}"); var temp = Newtonsoft.Json.JsonConvert.DeserializeObject(revString); if (temp != null) { var allLocalFuntion = FunctionList.List.GetAllDeviceFunctionList(); foreach (var updateTemp in temp.objects) { try { bool hadChange = false;//状态有变化再更新界面 var updataObj = allLocalFuntion.Find((obj) => obj.sid == updateTemp.sid); if (updataObj != null) { foreach (var attr in updateTemp.status) { foreach (var locatAttr in updataObj.attributes) { if (attr.key == locatAttr.key) { if (locatAttr.curValue.ToString() == attr.value) { continue; } locatAttr.curValue = attr.value; hadChange = true; } } } if (!hadChange)//状态有变化再更新界面 { continue; } //更新界面状态 switch (updataObj.spk) { case SPK.LightSwitch: RelayPage.UpdataState(updataObj as Light); break; case SPK.LightDimming: var dimming = updataObj as Light; dimming.lastState = Language.StringByID(StringId.Brightness) + " : " + dimming.brightness + "%"; DimmerPage.UpdataStates(dimming); break; case SPK.ElectricFan: var fan = updataObj as Fan; fan.lastState = Language.StringByID(StringId.Level) + " : " + fan.openLevel; FanPage.UpdataState(fan); break; case SPK.LightRGB: var rgb = updataObj as Light; rgb.lastState = Language.StringByID(StringId.Brightness) + " : " + rgb.brightness + "%"; RGBPage.UpdataStates(rgb); break; case SPK.LightRGBW: case SPK.LightCCT: break; case SPK.CurtainSwitch: var curtain = updataObj as Curtain; 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 = updataObj as Curtain; trietex.lastState = Language.StringByID(StringId.Open) + trietex.percent + "%"; MotorCurtainPage.UpdataState(trietex); break; case SPK.CurtainRoller: var roller = updataObj as Curtain; roller.lastState = Language.StringByID(StringId.Open) + roller.percent + "%"; RollingShutterPage.UpdataState(roller); break; case SPK.CurtainShades: break; case SPK.AcStandard: var ac = updataObj as AC; 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 = updataObj as FloorHeating; 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 = updataObj as Sensor; EnvironmentalSciencePage.LoadEvent_UpdataStatus(sensor); break; case SPK.ElectricSocket: break; case SPK.ElectricTV: break; default: break; } HomePage.UpdataFunctionStates(updataObj); RoomPage.UpdataStates(updataObj); FunctionPage.UpdataStates(updataObj); ClassificationPage.UpdataInfo(updataObj); } } catch (Exception ex) { MainPage.Log($"A协议更新状态异常:{ex.Message}"); } } } } } }