| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Text; |
| | | using HDL_ON.Entity; |
| | | using HDL_ON.UI; |
| | | using Shared; |
| | | |
| | | namespace HDL_ON.DriverLayer |
| | | { |
| | | |
| | | /// <summary> |
| | | /// 通讯方式 |
| | | /// </summary> |
| | | public enum CommunicationMode |
| | | { |
| | | none, |
| | | /// <summary> |
| | | /// 本地udp |
| | | /// </summary> |
| | |
| | | tcp_local_client, |
| | | } |
| | | |
| | | |
| | | |
| | | public class Control |
| | | { |
| | | static Control _control; |
| | | public static Control ins |
| | | public static Control Ins |
| | | { |
| | | get |
| | | { |
| | |
| | | return _control; |
| | | } |
| | | } |
| | | int _msg_id = 1; |
| | | /// <summary> |
| | | /// 通讯ID |
| | | /// </summary> |
| | | public int msg_id |
| | | { |
| | | get |
| | | { |
| | | return _msg_id++; |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// 获取13位时间戳 |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | public string Get_TimeStamp() |
| | | { |
| | | long t = DateTime.Now.Ticks / 10000; |
| | | return t.ToString(); |
| | | } |
| | | |
| | | bool _gatewayOnline = false; |
| | | /// <summary> |
| | | /// 网关是否在线 |
| | | /// </summary> |
| | | public 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(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// 网关通讯ID |
| | | /// </summary> |
| | | public string GatewayId; |
| | | |
| | | bool _isRemote = false; |
| | | /// <summary> |
| | | /// 是否为远程连接 |
| | | /// </summary> |
| | | public bool IsRemote { |
| | | get |
| | | { |
| | | return _isRemote; |
| | | } |
| | | set |
| | | { |
| | | _isRemote = value; |
| | | //修改主页连接状态 |
| | | HomePage.LoadEvent_CheckLinkStatus(); |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// 通讯地址IP |
| | | /// </summary> |
| | |
| | | /// <summary> |
| | | /// 本地udp |
| | | /// </summary> |
| | | public Control_Udp_Bus myUdp = null; |
| | | public Control_Udp myUdp = null; |
| | | |
| | | /// <summary> |
| | | /// 通讯方式 |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 改变通讯方式 |
| | | /// 打开Udp |
| | | /// </summary> |
| | | public void ChangeCommunicationMode(CommunicationMode communicationMode) |
| | | public void OpenUdp(int port) |
| | | { |
| | | if (this.communicationMode == communicationMode) |
| | | if (myUdp == null) |
| | | { |
| | | return; |
| | | myUdp = new Control_Udp(); |
| | | } |
| | | |
| | | this.communicationMode = communicationMode; |
| | | |
| | | |
| | | switch (this.communicationMode) |
| | | UdpSocket._BusSocket.Start(port); |
| | | } |
| | | /// <summary> |
| | | /// 关闭udp |
| | | /// </summary> |
| | | public void CloseUdp() |
| | | { |
| | | if (myUdp != null) |
| | | { |
| | | case CommunicationMode.local_BusUdp: |
| | | if (myUdp == null) |
| | | { |
| | | myUdp = new Control_Udp_Bus(); |
| | | } |
| | | UdpSocket._BusSocket.Start(); |
| | | if (myTcpClient != null) |
| | | { |
| | | myTcpClient.Close(); |
| | | myTcpClient = null; |
| | | } |
| | | break; |
| | | case CommunicationMode.tcp_local_client: |
| | | if (myTcpClient == null) |
| | | { |
| | | myTcpClient = new Control_TcpClient(reportIp); |
| | | myTcpClient.Connect(); |
| | | } |
| | | if (myUdp != null) |
| | | { |
| | | UdpSocket._BusSocket.Stop(); |
| | | myUdp = null; |
| | | } |
| | | break; |
| | | myUdp = null; |
| | | } |
| | | UdpSocket._BusSocket.Stop(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 打开tcp客服端 |
| | | /// </summary> |
| | | public void OpenTcpClent() |
| | | { |
| | | if (myTcpClient == null) |
| | | { |
| | | myTcpClient = new Control_TcpClient(reportIp); |
| | | myTcpClient.Connect(); |
| | | } |
| | | } |
| | | |
| | | ///// <summary> |
| | | ///// 改变通讯方式 |
| | | ///// </summary> |
| | | //public void ChangeCommunicationMode(CommunicationMode communicationMode) |
| | | //{ |
| | | // this.communicationMode = communicationMode; |
| | | //} |
| | | |
| | | /// <summary> |
| | | /// 搜索本地网关列表 |
| | | /// </summary> |
| | | public void SearchLoaclGateway() |
| | | { |
| | | ChangeCommunicationMode(CommunicationMode.local_BusUdp); |
| | | if (DB_ResidenceData.residenceData.GatewayType == 0) |
| | | OpenUdp(DB_ResidenceData.residenceData.GatewayType == 0 ? 6000 : 8585); |
| | | new System.Threading.Thread(() => |
| | | { |
| | | 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) |
| | | { |
| | | UdpSocket._BusSocket.SearchNetDeviceAction = (revIp) => |
| | | for (int i = 0; i < 5; i++) |
| | | { |
| | | MainPage.Log($"搜索到网络设备:{revIp}"); |
| | | }; |
| | | myUdp.SearchLocalGateway(); |
| | | 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(); |
| | | } |
| | | } |
| | | |
| | |
| | | { |
| | | function.usageCount++; |
| | | function.refreshTime = DateTime.Now; |
| | | if (DB_ResidenceData.residenceData.GatewayType == 0) |
| | | DAL.Server.HttpServerRequest httpServer = new DAL.Server.HttpServerRequest(); |
| | | //远程通讯 |
| | | if (Ins.IsRemote) |
| | | { |
| | | try |
| | | { |
| | | if(myUdp != null) |
| | | { |
| | | myUdp.WriteBusData(function, commandDictionary); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | MainPage.Log($"发送数据异常: {ex.Message}"); |
| | | } |
| | | //ALink控制、Bus控制使用同一个接口控制,由云端负责解析 |
| | | var apiControlData = function.GetApiControlData(commandDictionary); |
| | | var actionObjs = new List<ApiAlinkControlActionObj>(); |
| | | actionObjs.Add(apiControlData); |
| | | var pack = httpServer.ControlDevice(actionObjs); |
| | | MainPage.Log($"{pack.Code}:{pack.Data}"); |
| | | } |
| | | //本地通讯 |
| | | else |
| | | { |
| | | if (myTcpClient != null) |
| | | //Bus控制 |
| | | if (DB_ResidenceData.residenceData.GatewayType == 0) |
| | | { |
| | | var sendDataObj = function.GetControlSendData(commandDictionary); |
| | | var sendJson = Newtonsoft.Json.JsonConvert.SerializeObject(sendDataObj); |
| | | var sendBytes = System.Text.Encoding.UTF8.GetBytes(sendJson); |
| | | myTcpClient.SendMessage(sendBytes); |
| | | 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 SendReadCommand(Function function) |
| | | { |
| | | function.refreshTime = DateTime.Now; |
| | | if (function.bus_Data != null) |
| | | if (Ins.IsRemote) |
| | | { |
| | | try |
| | | { |
| | | //ReadBusData(function); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | MainPage.Log($"发送数据异常: {ex.Message}"); |
| | | } |
| | | var pm = new DAL.Server.HttpServerRequest(); |
| | | var pack = pm.RefreshDeviceStatus(new List<string>() { function.deviceId}); |
| | | } |
| | | else |
| | | { |
| | | //var commandObj = function.GetSendJObject(CommandType_A.read); |
| | | //var commandString = Newtonsoft.Json.JsonConvert.SerializeObject(commandObj); |
| | | //var commandBytes = System.Text.Encoding.UTF8.GetBytes(commandString); |
| | | //MqttCommon.MqttRemoteSend(commandBytes); |
| | | if (DB_ResidenceData.residenceData.GatewayType == 0) |
| | | { |
| | | try |
| | | { |
| | | Ins.myUdp.ReadBusData(function); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | MainPage.Log($"发送数据异常: {ex.Message}"); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | var readKey = new Dictionary<string, string>(); |
| | | readKey.Add("sid", function.sid); |
| | | |
| | | var readDataObj = new AlinkReadFunctionStatusObj() |
| | | { |
| | | id = Ins.msg_id.ToString(), |
| | | objects = new List<Dictionary<string, string>>() |
| | | { |
| | | readKey |
| | | }, |
| | | time_stamp = Utlis.GetTimestamp() |
| | | }; |
| | | var functionControlDataJson = Newtonsoft.Json.JsonConvert.SerializeObject(readDataObj); |
| | | var sendBytes = Ins.ConvertSendBodyData(CommunicationTopic.ct.ReadStatus, functionControlDataJson); |
| | | Ins.myUdp.SendLocalHdlLinkData(sendBytes); |
| | | } |
| | | } |
| | | } |
| | | ///// <summary> |
| | | ///// 发送A协议读取命令 |
| | | ///// </summary> |
| | | //public void SendReadCommand(List<Dictionary<string, string>> 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); |
| | | //} |
| | | |
| | | /// <summary> |
| | | /// 控制a协议场景 |
| | |
| | | sendSidObj.type = "device_sid"; |
| | | sendSidObj.command = "get_list_response"; |
| | | } |
| | | /// <summary> |
| | | /// 转换通讯数据 |
| | | /// </summary> |
| | | 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; |
| | | } |
| | | /// <summary> |
| | | /// 转换接收到的数据 |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | public void ConvertReceiveData(byte[] receiveBytes) |
| | | { |
| | | var reString = Encoding.UTF8.GetString(receiveBytes); |
| | | AnalysisReceiveData(reString); |
| | | } |
| | | /// <summary> |
| | | /// 转换接收到的数据 |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | 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<ResponsePack>(res[1]); |
| | | if (bodyJObj == null) |
| | | { |
| | | return receiveObj; |
| | | } |
| | | if (receiveObj.Topic == CommunicationTopic.SearchLoaclGatewayReply) |
| | | { |
| | | var device = Newtonsoft.Json.JsonConvert.DeserializeObject<DeviceModule>(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; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 更新设备状态 |
| | | /// A协议数据 |
| | | /// </summary> |
| | | /// <param name="updateBytes"></param> |
| | | public void UpdataFunctionStatus(string revString) |
| | | { |
| | | MainPage.Log($"A协议更新状态:{revString}"); |
| | | var temp = Newtonsoft.Json.JsonConvert.DeserializeObject<AlinkFunctionStatusObj>(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}"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |