using System; using System.Collections.Generic; using Shared; using Shared.IO; using Shared.SimpleControl; namespace Shared { /// /// HDLLink协议 工具类 /// public class HDLLinkUtlis { /// /// 生成逻辑sid方法 /// public static string NewSceneSid () { string sceneId = ""; try { string sOidBeginsWith = "000101";//厂商 + 通讯方式 string sTimeSpan = "00000000"; long sTimeSp = ConvertDateTimeLong (); //以2020年1月1日算出的时间戳0.1s为单位 ConvertIntToByteArray (sTimeSp, ref sTimeSpan); if (sTimeSpan.Length > 8) { sTimeSpan = sTimeSpan.Substring (0, 8); } sceneId = sOidBeginsWith + sTimeSpan; sceneId += "0A"; sceneId += "0A01"; int maxId = 1; Random random = new Random (Guid.NewGuid ().GetHashCode ()); maxId = random.Next (65535); sceneId += (maxId).ToString ("X4"); sceneId += "0000"; } catch { return sceneId; } return sceneId; } /// /// /// /// /// public static string GetCurtainStatusKey (CurtainStatus curtainStatus) { if(curtainStatus == CurtainStatus.Open) { return "on"; } else if (curtainStatus == CurtainStatus.Close) { return "off"; } else if (curtainStatus == CurtainStatus.Stop) { return "stop"; } else { return "off"; } } #region 生成4位byte 时间戳 private static long LastTime = 0; /// /// DateTime时间格式转换为13位带毫秒的Unix时间戳 /// /// DateTime时间格式 /// Unix时间戳格式 public static long ConvertDateTimeLong () { System.DateTime startTime = TimeZoneInfo.ConvertTimeToUtc (new System.DateTime (2020, 1, 1)); long l = (long)(Math.Round ((DateTime.Now - startTime).TotalMilliseconds, 1) / 10); if (l <= LastTime) l = LastTime + 1; LastTime = l; return l; } /// /// /// /// /// /// public static bool ConvertIntToByteArray (long m, ref string strTmp) { strTmp = "00000000"; byte [] arry = new byte [4]; arry [0] = (byte)(m & 0xFF); arry [1] = (byte)((m & 0xFF00) >> 8); arry [2] = (byte)((m & 0xFF0000) >> 16); arry [3] = (byte)((m & 0xFF000000) >> 24); strTmp = arry [0].ToString ("X2") + arry [1].ToString ("X2") + arry [2].ToString ("X2") + arry [3].ToString ("X2"); return true; } #endregion #region ■ Current___________________________ /// /// 通用方法 /// private static HDLLinkUtlis m_Current = null; /// /// 通用方法 /// public static HDLLinkUtlis Current { get { if (m_Current == null) { m_Current = new HDLLinkUtlis (); } return m_Current; } } #endregion /// /// 一键将本地回路设备和场景数据转换 /// 然后上传oid、sid、以及场景列表 /// /// public void OneclickUpload (bool isMigrate = false) { if (isMigrate) { var res = false; res = UploadOidAndSidList (); if (res) { res = GetFunctionList (); if (res) { res = UploadSecneList (); } } return; } MainPage.Loading.Start ("Uploading..."); System.Threading.Tasks.Task.Run (() => { try { var res = false; res = UploadOidAndSidList (); if (res) { res = GetFunctionList (); if (res) { res = UploadSecneList (); } } if (res) { Utlis.ShowAlertOnMainThread (Language.StringByID (SimpleControl.R.MyInternationalizationString.SuccessfullySynchronizedToTheCloud)); } else { Utlis.ShowAlertOnMainThread (Language.StringByID (SimpleControl.R.MyInternationalizationString.FailedToSyncToTheCloud)); } } catch { } finally { Application.RunOnMainThread (() => { MainPage.Loading.Hide (); }); } }); } /// /// /// /// public bool GetFunctionList () { var res = false; try { var revertObj = HttpServerRequest.Current.GetDeviceList (); if (revertObj.Code == StateCode.SUCCESS) { var devcieFunctionRes = Newtonsoft.Json.JsonConvert.DeserializeObject (revertObj.Data.ToString ()); if (devcieFunctionRes != null && devcieFunctionRes.list != null && devcieFunctionRes.list.Count > 0) { CommonConfig.Current.FunctionList = devcieFunctionRes.list; } else { CommonConfig.Current.FunctionList = new List (); } CommonConfig.Current.Save (); res = true; } else { //提示错误 IMessageCommon.Current.ShowErrorInfoAlter (revertObj.Code); } } catch { } return res; } #region ■ 上传场景列表___________________________ /// /// 上传场景列表 /// public bool UploadSecneList () { var res = false; try { //1.加载所有场景并转换 var allSecneList = GetAllSecneList (); var hdlLinkSceneList = new List (); foreach (var sence in allSecneList) { var mHDLLinkScene = GetHDLLinkScene (sence); //1.1成功转换的场景才添加到准备上传列表 if(mHDLLinkScene != null && mHDLLinkScene.functions != null && mHDLLinkScene.functions.Count > 0) { hdlLinkSceneList.Add (mHDLLinkScene); } } //全量同步场景 res = UploadSceneList (hdlLinkSceneList); } catch (Exception ex){ Utlis.WriteLine ("catch :" + ex.ToString ()); } return res; } /// /// 获取所有场景列表 /// /// public List GetAllSecneList () { List targetSceneList = new List (); //// 找出需要显示的场景 // 1.全局场景 var globalSceneFileList = Newtonsoft.Json.JsonConvert.DeserializeObject> (System.Text.Encoding.UTF8.GetString (IO.FileUtils.ReadFile (Scene.GlobalSceneFilePath))); if (globalSceneFileList == null) { globalSceneFileList = new List (); } // 2.房间场景 List RoomsSceneFileList = new List (); foreach (var r in Room.Lists) { if (string.IsNullOrEmpty (r.Name)) { continue; } if (r != null) { RoomsSceneFileList.AddRange (r.SceneFilePathList); } } foreach (var sceneFilePath in globalSceneFileList) { var tempScene = Scene.GetSceneByFilePath (sceneFilePath); if (tempScene != null) { if (string.IsNullOrEmpty (tempScene.Sid)) { //如果Sid为空,重新生成并保存 tempScene.Sid = NewSceneSid (); tempScene.Save (sceneFilePath); Utlis.WriteLine ("生成新的场景id: " + tempScene.Sid); } targetSceneList.Add (tempScene); } } foreach (var roomSceneFilePath in RoomsSceneFileList) { var tempScene = Scene.GetSceneByFilePath (roomSceneFilePath); if (tempScene != null) { if (string.IsNullOrEmpty (tempScene.Sid)) { //如果Sid为空,重新生成并保存 tempScene.Sid = NewSceneSid (); tempScene.Save (roomSceneFilePath); Utlis.WriteLine ("生成新的场景id: " + tempScene.Sid); } targetSceneList.Add (tempScene); } } // 所有场景 return targetSceneList; } /// /// 全量同步场景 /// /// bool UploadSceneList (List hdlLinkSceneList) { var res = false; try { var revertObj = HttpServerRequest.Current.SecneSyncList (hdlLinkSceneList); if (revertObj.Code == StateCode.SUCCESS) { res = true; } else { IMessageCommon.Current.ShowErrorInfoAlter (revertObj.Code); } } catch { } return res; } ///// ///// ///// ///// //bool UpdateSceneList (List updateLinkSceneList) //{ // var res = false; // try { // var revertObj = HttpServerRequest.Current.EditScene (updateLinkSceneList); // if (revertObj.Code == StateCode.SUCCESS) { // res = true; // } else { // IMessageCommon.Current.ShowErrorInfoAlter (revertObj.Code); // } // } catch { // } // return res; //} /// /// 原生协议Scene 转换成 HDLLinkScene数据格式 /// /// /// HDLLinkScene GetHDLLinkScene (Scene mScene) { var mHDLLinkScene = new HDLLinkScene (); mHDLLinkScene.sid = mScene.Sid; mHDLLinkScene.name = mScene.Name; if (UserConfig.Instance.CheckWhetherGatewayIdNotNull ()) { mHDLLinkScene.gatewayId = UserConfig.Instance.HomeGateway.gatewayId; } var functions = new List (); if (!mScene.busScene) { foreach (var deviceFilePath in mScene.DeviceFilePathList) { var jsonInfo = System.Text.Encoding.UTF8.GetString (IO.FileUtils.ReadFile (deviceFilePath)); var common = Newtonsoft.Json.JsonConvert.DeserializeObject (jsonInfo); if (common == null) continue; var function = CommonUtlis.Current.CommonToFunction (common, CommonConfig.Current.FunctionList); if (function == null) continue; if (common.Type == DeviceType.LightDimming) { var commonNew = Newtonsoft.Json.JsonConvert.DeserializeObject (jsonInfo); var mSceneFunction = new SceneFunction (); mSceneFunction.sid = function.sid; //1.on_off var status = new List (); status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.OnOff, value = commonNew.CurrentBrightness > 0 ? "on" : "off", }); //2.Brightness status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.Brightness, value = commonNew.CurrentBrightness.ToString(), }); //3.Delay status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.Delay, value = (commonNew.DelayTimeHeight * 256 + commonNew.DelayTimeLow).ToString (), }); mSceneFunction.status = status; functions.Add (mSceneFunction); } else if (common.Type == DeviceType.LightEnergySocket) { var commonNew = Newtonsoft.Json.JsonConvert.DeserializeObject (jsonInfo); var mSceneFunction = new SceneFunction (); mSceneFunction.sid = function.sid; //1.on_off var status = new List (); status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.OnOff, value = commonNew.CurrentBrightness > 0 ? "on" : "off", }); //2.Delay status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.Delay, value = (commonNew.DelayTimeHeight * 256 + commonNew.DelayTimeLow).ToString (), }); mSceneFunction.status = status; functions.Add (mSceneFunction); } else if (common.Type == DeviceType.LightEnergySwitch) { var commonNew = Newtonsoft.Json.JsonConvert.DeserializeObject (jsonInfo); var mSceneFunction = new SceneFunction (); mSceneFunction.sid = function.sid; //1.on_off var status = new List (); status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.OnOff, value = commonNew.CurrentBrightness > 0 ? "on" : "off", }); //2.Delay status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.Delay, value = (commonNew.DelayTimeHeight * 256 + commonNew.DelayTimeLow).ToString(), }); mSceneFunction.status = status; functions.Add (mSceneFunction); } else if (common.Type == DeviceType.LightRGB) { var commonNew = Newtonsoft.Json.JsonConvert.DeserializeObject (jsonInfo); var mSceneFunction = new SceneFunction (); mSceneFunction.sid = function.sid; //1.on_off var status = new List (); status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.OnOff, value = commonNew.CurrentBrightness > 0 ? "on" : "off", }); //2.Brightness status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.Brightness, value = commonNew.CurrentBrightness.ToString (), }); //3.Delay status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.Delay, value = (commonNew.DelayTimeHeigh * 256 + commonNew.DelayTimeLow).ToString (), }); //4.rgb status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.RGB, value = commonNew.RStatus + "," + commonNew.GStatus + "," + commonNew.BStatus, }); mSceneFunction.status = status; functions.Add (mSceneFunction); //var device = Newtonsoft.Json.JsonConvert.DeserializeObject (System.Text.Encoding.UTF8.GetString (IO.FileUtils.ReadFile (deviceFilePath))); ////if (device == null) { //// mSendCount--; //// continue; ////} //if (device == null) { // //replyBytes = new byte [] { 0x00 }; //} else { // var mSceneFunction = new SceneFunction (); // functions.Add (mSceneFunction); // replyBytes = Control.ControlBytesSendHasReturn (Command.SetLogicLoopColor, device.SubnetID, device.DeviceID, new byte [] { device.LoopID, device.CurrentBrightness, 254, device.DelayTimeHeigh,device.DelayTimeLow, // 3,device.RStatus,device.GStatus,device.BStatus,0,0}); //} } else if (common.Type == DeviceType.LightSwitch) { var commonNew = Newtonsoft.Json.JsonConvert.DeserializeObject (jsonInfo); var mSceneFunction = new SceneFunction (); mSceneFunction.sid = function.sid; //1.OnOff var status = new List (); status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.OnOff, value = commonNew.CurrentBrightness > 0 ? "on" : "off", }); //2.Delay status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.Delay, value = (commonNew.DelayTimeHeight * 256 + commonNew.DelayTimeLow).ToString (), }); mSceneFunction.status = status; functions.Add (mSceneFunction); } else if (common.Type == DeviceType.CurtainModel) { var commonNew = Newtonsoft.Json.JsonConvert.DeserializeObject (jsonInfo); var mSceneFunction = new SceneFunction (); mSceneFunction.sid = function.sid; //1.on_off stop var status = new List (); status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.OnOff, value = GetCurtainStatusKey(commonNew.Status), }); mSceneFunction.status = status; functions.Add (mSceneFunction); } else if (common.Type == DeviceType.CurtainRoller) { var commonNew = Newtonsoft.Json.JsonConvert.DeserializeObject (jsonInfo); var mSceneFunction = new SceneFunction (); mSceneFunction.sid = function.sid; //1.percent var status = new List (); status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.Percent, value = commonNew.CurtainProress.ToString(), }); mSceneFunction.status = status; functions.Add (mSceneFunction); } else if (common.Type == DeviceType.CurtainTrietex) { var commonNew = Newtonsoft.Json.JsonConvert.DeserializeObject (jsonInfo); var mSceneFunction = new SceneFunction (); mSceneFunction.sid = function.sid; //1.percent var status = new List (); status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.Percent, value = commonNew.CurtainProress.ToString (), }); mSceneFunction.status = status; functions.Add (mSceneFunction); } else if (common.Type == DeviceType.HVAC || common.Type == DeviceType.ACInfrared) { var commonNew = Newtonsoft.Json.JsonConvert.DeserializeObject (jsonInfo); var mSceneFunction = new SceneFunction (); mSceneFunction.sid = function.sid; //1.on_off var status = new List (); status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.OnOff, value = commonNew.Power > 0 ? "on" : "off", }); //2.mode status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.Mode, value = commonNew.SetModeAttribute, }); //3.fan status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.FanSpeed, value = commonNew.SetFanSpeedAttribute, }); //4.SetTemp status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.SetTemp, value = commonNew.SetTemperature.ToString(), }); mSceneFunction.status = status; functions.Add (mSceneFunction); //replyBytes = Control.ControlBytesSendHasReturn (Command.SetACMode, device.SubnetID, device.DeviceID, new byte [] { // device.LoopID, // device.TemperatureMode, // device.IndoorTemperature, // device.CoolTemperature, // device.HeatTemperature, // device.AutoTemperature, // device.ChuShiTemperature, // device.RealModeAndFanSpeed, // device.Power, // device.SetMode, // device.SetFanSpeed, // device.SetTemperature, // device.ShaoFanMode}); } else if (common.Type == DeviceType.FoolHeat) { var commonNew = Newtonsoft.Json.JsonConvert.DeserializeObject (jsonInfo); var mSceneFunction = new SceneFunction (); mSceneFunction.sid = function.sid; //1.on_off var status = new List (); status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.OnOff, value = commonNew.Status > 0 ? "on" : "off", }); //2.mode status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.Mode, value = commonNew.SetModeAttribute, }); //3.SetTemp status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.SetTemp, value = commonNew.WorkingTemperature.ToString (), }); mSceneFunction.status = status; functions.Add (mSceneFunction); //var device = Newtonsoft.Json.JsonConvert.DeserializeObject (System.Text.Encoding.UTF8.GetString (IO.FileUtils.ReadFile (deviceFilePath))); ////if (device == null) { //// mSendCount--; //// continue; ////} //if (device == null) { // //replyBytes = new byte [] { 0x00 }; //} else { // var mSceneFunction = new SceneFunction (); // functions.Add (mSceneFunction); //replyBytes = Control.ControlBytesSendHasReturn (Command.SetFoolHeat, device.SubnetID, device.DeviceID, // new byte [] { device.LoopID, (byte)(device.Status + device.WorkingMode * 16), 0,device.WorkingMode,device.NormalTemperature, device.DayTemperature, // device.NightTemperature, device.AwayTemperature , 0, 0 }); //} } else if (common.Type == DeviceType.FanModule) { var commonNew = Newtonsoft.Json.JsonConvert.DeserializeObject (jsonInfo); var mSceneFunction = new SceneFunction (); mSceneFunction.sid = function.sid; //1.on_off var status = new List (); status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.OnOff, value = commonNew.WindSpeed > 0 ? "on" : "off", }); //2.FanSpeedPercent status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.FanSpeedPercent, value = commonNew.WindSpeed.ToString(), }); mSceneFunction.status = status; functions.Add (mSceneFunction); //replyBytes = Control.ControlBytesSendHasReturn (Command.SetSingleLight, device.SubnetID, device.DeviceID, new byte [] { device.LoopID, (byte)device.WindSpeed }); } else if (common.Type == DeviceType.LogicModule) { //replyBytes = Control.ControlBytesSendHasReturn (Command.SetScene, device.SubnetID, device.DeviceID, new byte [] { //device.AreaID,device.AreaSceneID}); } else if (common.Type == DeviceType.UniversalDevice) {//2020-09-02 增加通用开关 var commonNew = Newtonsoft.Json.JsonConvert.DeserializeObject (jsonInfo); var mSceneFunction = new SceneFunction (); mSceneFunction.sid = function.sid; //1.on_off var status = new List (); status.Add (new SceneFunctionStatus () { key = FunctionAttributeKey.OnOff, value = commonNew.SendBytes [1] > 0 ? "on" : "off", }); mSceneFunction.status = status; functions.Add (mSceneFunction); //replyBytes = Control.ControlBytesSendHasReturn (Command.SetCommonSwitch, device.SubnetID, device.DeviceID, new byte [] { device.SendBytes [0], device.SendBytes [1] }); } } } else { } mHDLLinkScene.functions = functions; return mHDLLinkScene; } #endregion #region ■ 上传设备列表___________________________ /// /// 上传设备列表 /// /// public bool UploadOidAndSidList () { var res = false; try { IotCloud currentProject = new IotCloud (); var list = GetAllDeviceList (); ConvertOidListToIotStruct (UserConfig.Instance.CurrentRegion.Id, UserConfig.Instance.HomeGateway.gatewayId, list, ref currentProject); //2022-06-21 13:10:07 mac不能为空,否则云端有问题 foreach (var bean in currentProject.modules.devices) { if (string.IsNullOrEmpty (bean.mac)) { bean.mac = bean.oid; } } Utlis.WriteLine ("list: " + list.Count + "currentProject : " + currentProject.functions.devices.Count); var revertObj = HttpServerRequest.Current.UploadDeviceOidList (currentProject.modules); if(revertObj.Code == StateCode.SUCCESS) { var revertObj2 = HttpServerRequest.Current.UploadDeviceSidList (currentProject.functions); if (revertObj2.Code == StateCode.SUCCESS) { res = true; } else { IMessageCommon.Current.ShowErrorInfoAlter (revertObj2.Code); } } else { IMessageCommon.Current.ShowErrorInfoAlter (revertObj.Code); } } catch(Exception EX) { Utlis.WriteLine ("catch: " + EX.ToString()); } return res; } /// /// /// /// public List GetAllDeviceList () { List TargetList = new List (); //找出需要显示的设备 var localEquipments = CommonUtlis.Current.GetAllLocalEquipments (); foreach (string deviceFilePath in localEquipments) { try { string [] str = deviceFilePath.Split ('_'); var commonBytes = FileUtils.ReadFile (deviceFilePath); if (commonBytes.Length == 0) { Utlis.WriteLine ("length loss"); continue; } if (commonBytes.Length == 1) { Utlis.WriteLine ("length loss 1"); continue; } Common commonDevice = Newtonsoft.Json.JsonConvert.DeserializeObject (System.Text.Encoding.UTF8.GetString (commonBytes)); if (commonDevice == null) { continue; } TargetList.Add (commonDevice); } catch { } } return TargetList; } /// /// 将在线设备转换成sid + 属性列表 /// /// 模块设备 /// public List ConvertToSidListToIotCloud (string sOid, Common loopCommon) { List sidList = new List (); try { Sid tmpSid = new Sid (); tmpSid.sid = FormingNewSid (sOid, loopCommon); tmpSid.oid = sOid; tmpSid.name = loopCommon.Name; SidObject tmp = UpdateSidAttributesToDeviceList (loopCommon, sOid); tmpSid.attributes = tmp.attributes; //UpdateSidAttributesToDeviceList(onlineDevice.DeviceType, sOid, j, BigType, SmallType, ref spk); tmpSid.spk = tmp.spk; sidList.Add (tmpSid); return sidList; } catch (Exception) { return sidList; } } /// /// 处理本地数据,转换生成Oid和Sid列表 /// /// /// /// /// public void ConvertOidListToIotStruct (string homeId, string gatewayId, List loopCommonList, ref IotCloud currentProject) { try { //step 1 转换类型 Sids functionList = new Sids(); List tmpFunction = new List (); //step 2 转换生成Oids列表和sid 设备列表 Oids mOidList = ConvertToOidListToIotCloud (loopCommonList, ref tmpFunction); mOidList.homeId = homeId; //step 3 functionList.devices = new List (); functionList.homeId = homeId; functionList.gatewayId = gatewayId; if (tmpFunction != null) { functionList.devices = tmpFunction; } currentProject.modules = mOidList; currentProject.functions = functionList; } catch (Exception ex) { //MessageBox.Show (ex.Tostring ()); //throw; } } /// /// 转换类型在线设备列表转OID列表 只在上传或者下载时使用 /// /// /// public Oids ConvertToOidListToIotCloud (List loopCommonListlolooloopl, ref List functionLists) { Oids mOidsList = new Oids (); try { mOidsList.devices = new List (); //HDLSysPF.IniDeviceChannelRemark (); //整理全部设备备注到缓存列表 foreach (Common tmp in loopCommonListlolooloopl) { //1.deviceType标识 云端是int类型 var deviceType = ((int)tmp.Type); //2.addresses标识 子网号、设备号 var addresses = string.Format ("{0}{1}", tmp.SubnetID.ToString ("X2"), tmp.DeviceID.ToString ("X2")); //3.判断当前回路设备之前是否生成过相同模块的oid,存在则取之前的oid 没有则创建新增新的oid var deviceOid = mOidsList.devices.Find (o => o.deviceType == deviceType && o.addresses == addresses); if (deviceOid == null) { //3.1没有则创建新增新的oid Oid tmpOid = new Oid (); tmpOid.protocolType = "bus"; tmpOid.device_name = tmp.Type.ToString (); tmpOid.oid = FormingNewOid (tmp); tmpOid.addresses = addresses; tmpOid.device_model = tmp.Type.ToString (); tmpOid.fw_version = ""; tmpOid.deviceType = deviceType; tmpOid.hw_info = ""; tmpOid.mac = tmp.MAC; mOidsList.devices.Add (tmpOid); functionLists.AddRange (ConvertToSidListToIotCloud (tmpOid.oid, tmp)); //Utlis.WriteLine ("新的模块,新的的OID:" + tmpOid.addresses + " deviceType:" + tmpOid.deviceType); } else { //3.2存在则取之前的oid functionLists.AddRange (ConvertToSidListToIotCloud (deviceOid.oid, tmp)); //Utlis.WriteLine ("相同的模块,取之前的OID:" + deviceOid.addresses + " deviceType:" + deviceOid.deviceType); } } return mOidsList; } catch (Exception ex) { return mOidsList; } } ///// ///// ///// ///// ///// ///// ///// //public void ConvertOidListToIotStruct (string homeId, List onlineDevices, string gatewayId, ref IotCloud currentProject) //{ // try { // //step 1 转换类型 // Sids functionList = currentProject.functions; // List tmpFunction = new List (); // //step 2 转换类型 // Oids tmp = ConvertToOidListToIotCloud (onlineDevices, ref tmpFunction); // if (currentProject.modules == null || currentProject.modules.devices == null || currentProject.modules.devices.Count == 0) currentProject.modules = tmp; // else { // foreach (Oid tmpModule in tmp.devices) { // Oid tmpFind = currentProject.modules.devices.Find (P => P.mac.Equals (tmpModule.mac)); // if (tmpFind == null) currentProject.modules.devices.Add (tmpModule); // } // } // tmp.homeId = homeId; // //上传功能列表 // #region // //if (functionList == null) // //{ // functionList = new Sids (); // functionList.devices = new List (); // functionList.devices = tmpFunction; // //} // functionList.homeId = homeId; // functionList.gatewayId = gatewayId; // currentProject.modules = tmp; // currentProject.functions = functionList; // #endregion // } catch (Exception ex) { // //MessageBox.Show (ex.Tostring ()); // //throw; // } //} /// /// 生成设备Oid /// /// /// public string FormingNewOid (Common common) { string sOid = ""; try { //1.生成 厂商 + 通讯方式 string sOidBeginsWith = "000101";//厂商 + 通讯方式 //**************************** ////2.生成产品时间戳 //long sTimeSp = ConvertDateTimeLong (); //以2020年1月1日算出的时间戳0.1s为单位 //string sTimeSpan = ""; //ConvertIntToByteArray (sTimeSp, ref sTimeSpan); //if (sTimeSpan.Length != 8) return sOid; ////延迟10ms //2.方案二:生成产品时间戳(云端不解析)印度APP把当前位置改为(子网号、设备号、大类小类)表示,保证设备在子网号设备号不变的情况下 oid生成也不变 string sTimeSpan = ""; sTimeSpan = common.SubnetID.ToString ("X2") + common.DeviceID.ToString ("X2") + common.DeviceTypeString; //**************************** //3.生成产品类别 var productType = GetProductType (common.Type); sOid = sOidBeginsWith + sTimeSpan + productType; return sOid; } catch { return sOid; } } /// /// 获取产品类别 /// 产品类别目前没有规范的文档,没有确定的标准 /// 暂时和buspro软件规则一致 /// ///文档规则,但是不是正确的版本 //产品类别 1byte //编号 描述 //01 调光器 //02 继电器 //03 干接点模块 //04 传感器 //05 面板 //06 RCU //07 网关 //08 红外发射 //09 Android屏 //10 场景 //11 音乐播放器 //12 232/485转换器 //21 自动化 //22 安防防区 //14 窗帘模块 //15 HVAC //16 地热模块 /// /// /// public string GetProductType (DeviceType deviceType) { string productType = ""; switch (deviceType) { case DeviceType.LightDimming: case DeviceType.LightCCT: case DeviceType.LightDALI: case DeviceType.LightRGB: case DeviceType.LightRGBW: case DeviceType.LightLogic: case DeviceType.LightRGBandCCT: case DeviceType.DMX48: productType = "01";//01 调光器 break; case DeviceType.LightSwitch: case DeviceType.LightEnergySwitch: case DeviceType.LightEnergySocket: case DeviceType.LightSwitchSocket: case DeviceType.LightMixSwitch: productType = "02";//02 继电器类 break; case DeviceType.CurtainModel: case DeviceType.CurtainRoller: case DeviceType.CurtainTrietex: productType = "03";//03 遮阳类(窗帘) break; case DeviceType.SensorWindSpeed: productType = "04";//04 传感器) break; case DeviceType.OnePortWirelessFR: case DeviceType.OnePortBus: case DeviceType.RCU: case DeviceType.SuperWireless: case DeviceType.OnePortMqttFR: productType = "07";//07 网关类 break; case DeviceType.ACPanel: case DeviceType.ACDevice: case DeviceType.ACInfrared: case DeviceType.ACCoolmaster: case DeviceType.CustomAC: case DeviceType.HVAC: case DeviceType.FoolHeat: case DeviceType.FoolHeatPanel: productType = "12";//12 恒温器(空调、地热) break; case DeviceType.MusicModel: case DeviceType.MusicPanel: case DeviceType.MusicA31: productType = "0B"; break; default: productType = "00"; break; } return productType; } /// /// 获取生成物理模型参数 /// 2021-01-22 目前物模还不完善 /// /// /// public string GetPhysicalModelType (DeviceType deviceType) { string productType = ""; switch (deviceType) { case DeviceType.LightEnergySwitch: productType = "0101"; break; case DeviceType.LightEnergySocket: case DeviceType.LightSwitchSocket: productType = "0102"; break; case DeviceType.LightSwitch: case DeviceType.LightMixSwitch: productType = "0201"; break; case DeviceType.LightDimming: productType = "0202"; break; case DeviceType.LightCCT: case DeviceType.LightDALI: productType = "0203"; break; case DeviceType.LightRGB: case DeviceType.LightRGBW: case DeviceType.LightLogic: case DeviceType.LightRGBandCCT: case DeviceType.DMX48: productType = "0204"; break; //窗帘 case DeviceType.CurtainModel: productType = "0301"; break; case DeviceType.CurtainTrietex: productType = "0303"; break; case DeviceType.CurtainRoller: productType = "0304"; break; case DeviceType.ACPanel: case DeviceType.ACDevice: case DeviceType.ACInfrared: case DeviceType.ACCoolmaster: case DeviceType.CustomAC: case DeviceType.HVAC: productType = "0701"; break; case DeviceType.FoolHeat: case DeviceType.FoolHeatPanel: productType = "0801"; break; case DeviceType.MusicModel: case DeviceType.MusicPanel: case DeviceType.MusicA31: productType = "0901"; break; case DeviceType.FanModule: productType = "1001"; break; default: productType = ((int)deviceType).ToString ("X4"); break; } return productType; } /// /// 生成功能设备Sid /// /// /// /// /// /// /// /// public string FormingNewSid (string sOid, Common loopCommon) { if (sOid == null || sOid == "") return ""; try { //物模型类+通道号+大小类别 string sSid = ""; //1.物模型类 string mPhysicalModelType = GetPhysicalModelType (loopCommon.Type); //2.通道号 string loopIDStr = loopCommon.LoopID.ToString ("X4"); //3.大小类别 string bigMinStr = loopCommon.DeviceTypeString; //4.拼接 sSid = sOid + mPhysicalModelType + loopIDStr + bigMinStr; return sSid; } catch { return ""; } } /// /// 生成SPK属性 /// /// /// /// /// /// /// /// /// public SidObject UpdateSidAttributesToDeviceList (Common loopCommon, string sOid) { SidObject tmp = new SidObject (); try { string sSid = FormingNewSid (sOid, loopCommon); tmp.oid = sOid; tmp.sid = sSid; tmp.name = loopCommon.Name; tmp.attributes = new List (); tmp.omodel = loopCommon.Type.ToString (); if (loopCommon.Type == DeviceType.UniversalDevice) { //通用开关 tmp.spk = SPK.UniversalDevice; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "on_off"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("on"); tempAttribute.value.Add ("off"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion }else if (loopCommon.Type == DeviceType.FanModule ) { //风扇 tmp.spk = SPK.ElectricFan; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "on_off"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("on"); tempAttribute.value.Add ("off"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion #region volume_level Attribute tempSpeedAttribute = new Attribute (); tempSpeedAttribute.key = FunctionAttributeKey.FanSpeedPercent; tempSpeedAttribute.data_type = "integer"; tempSpeedAttribute.value = new List (); tempSpeedAttribute.max = 8; tempSpeedAttribute.min = 0; tmp.attributes.Add (tempSpeedAttribute); #endregion } else if (loopCommon.Type == DeviceType.LightSwitch || loopCommon.Type == DeviceType.LightEnergySwitch || loopCommon.Type == DeviceType.LightMixSwitch) { //继电器开关类 tmp.spk = SPK.LightSwitch; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "on_off"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("on"); tempAttribute.value.Add ("off"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion }else if (loopCommon.Type == DeviceType.LightEnergySocket || loopCommon.Type == DeviceType.LightSwitchSocket) { //电器 插座 tmp.spk = SPK.ElectricSocket; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "on_off"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("on"); tempAttribute.value.Add ("off"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion } else if (loopCommon.Type == DeviceType.LightDimming || loopCommon.Type == DeviceType.LightCCT || loopCommon.Type == DeviceType.LightDALI) { //调光类 //tmp.spk = "light.dimming"; tmp.spk = SPK.LightDimming; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "on_off"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("on"); tempAttribute.value.Add ("off"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion #region brightness Attribute tempAttribute1 = new Attribute (); tempAttribute1.key = "brightness"; tempAttribute1.data_type = "integer"; tempAttribute1.value = new List (); tempAttribute1.max = 100; tempAttribute1.min = 0; tmp.attributes.Add (tempAttribute1); #endregion #region fade_time Attribute tempAttribute3 = new Attribute (); tempAttribute3.key = "fade_time"; tempAttribute3.data_type = "integer"; tempAttribute3.value = new List (); //tempAttribute1.value.Add("percent"); //for (int iPercent = 0; iPercent <= 100; iPercent++) //{ // tempAttribute1.value.Add(iPercent.ToString()); //} tempAttribute3.max = 100; tempAttribute3.min = 0; tmp.attributes.Add (tempAttribute3); #endregion if (loopCommon.Type == DeviceType.LightCCT || loopCommon.Type == DeviceType.LightDALI)//色温类别 { //tmp.spk = "light.cct"; tmp.spk = SPK.LightCCT; #region cct Attribute tempAttribute2 = new Attribute (); tempAttribute2.key = "cct"; tempAttribute2.data_type = "integer"; tempAttribute2.value = new List (); //tempAttribute2.value.Add("warm light "); //tempAttribute2.value.Add("cold light "); tempAttribute2.max = 65535; tempAttribute2.min = 0; tmp.attributes.Add (tempAttribute2); #endregion } } else if (loopCommon.Type == DeviceType.LightRGB || loopCommon.Type == DeviceType.LightRGBW || loopCommon.Type == DeviceType.LightLogic || loopCommon.Type == DeviceType.LightRGBandCCT || loopCommon.Type == DeviceType.DMX48) { tmp.spk = SPK.LightRGB; //tmp.spk = "light.rgb"; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "on_off"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("on"); tempAttribute.value.Add ("off"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion #region brightness Attribute tempAttribute2 = new Attribute (); tempAttribute2.key = "brightness"; tempAttribute2.data_type = "integer"; tempAttribute2.value = new List (); tempAttribute2.max = 100; tempAttribute2.min = 0; tmp.attributes.Add (tempAttribute2); #endregion if (loopCommon.Type == DeviceType.LightRGBW) { //tmp.spk = "light.rgbw"; tmp.spk = SPK.LightRGBW; #region color Attribute tempAttribute3 = new Attribute (); tempAttribute3.key = "rgb"; tempAttribute3.data_type = "integer"; tempAttribute3.value = new List (); //tempAttribute2.value.Add("red"); //tempAttribute2.value.Add("green"); //tempAttribute2.value.Add("blue"); tempAttribute3.max = 255; tempAttribute3.min = 0; tmp.attributes.Add (tempAttribute3); #endregion } else { #region color Attribute tempAttribute3 = new Attribute (); tempAttribute3.key = "rgb"; tempAttribute3.data_type = "integer"; tempAttribute3.value = new List (); tempAttribute3.min = 0; tmp.attributes.Add (tempAttribute3); #endregion } if (loopCommon.Type == DeviceType.LightRGBandCCT) { #region CCT Attribute tempAttributeCCT = new Attribute (); tempAttributeCCT.key = "cct"; tempAttributeCCT.data_type = "integer"; tempAttributeCCT.value = new List (); //tempAttribute2.value.Add("red"); //tempAttribute2.value.Add("green"); //tempAttribute2.value.Add("blue"); tempAttributeCCT.max = 65535; tempAttributeCCT.min = 0; tmp.attributes.Add (tempAttributeCCT); #endregion } } else if (loopCommon.Type == DeviceType.CurtainModel || loopCommon.Type == DeviceType.CurtainRoller || loopCommon.Type == DeviceType.CurtainTrietex) { //tmp.spk = "curtain.switch"; tmp.spk = SPK.CurtainSwitch; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "on_off"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("on"); tempAttribute.value.Add ("off"); tempAttribute.value.Add ("stop"); tempAttribute.max = 2; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion if (loopCommon.Type == DeviceType.CurtainRoller || loopCommon.Type == DeviceType.CurtainTrietex)//所有卷帘控制器 { tmp.spk = SPK.CurtainTrietex; //tmp.spk = "curtain.trietex"; #region openlevel Attribute tempAttribute1 = new Attribute (); tempAttribute1.key = "percent"; tempAttribute1.data_type = "integer"; tempAttribute1.value = new List (); //tempAttribute1.value.Add("percent"); tempAttribute1.max = 100; tempAttribute1.min = 0; tmp.attributes.Add (tempAttribute1); #endregion } } else if (loopCommon.Type == DeviceType.ACPanel || loopCommon.Type == DeviceType.ACDevice || loopCommon.Type == DeviceType.ACInfrared || loopCommon.Type == DeviceType.ACCoolmaster || loopCommon.Type == DeviceType.CustomAC || loopCommon.Type == DeviceType.HVAC) { //空调类 tmp.spk = SPK.AcStandard; //tmp.spk = "ac.standard"; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "on_off"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("on"); tempAttribute.value.Add ("off"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion #region mode Attribute tempAttribute1 = new Attribute (); tempAttribute1.key = "mode"; tempAttribute1.data_type = "integer"; tempAttribute1.value = new List (); tempAttribute1.value.Add ("cool"); tempAttribute1.value.Add ("heat"); tempAttribute1.value.Add ("fan"); tempAttribute1.value.Add ("auto"); tempAttribute1.value.Add ("dry"); tempAttribute1.max = 4; tempAttribute1.min = 0; tmp.attributes.Add (tempAttribute1); #endregion #region fan Attribute tempAttribute2 = new Attribute (); tempAttribute2.key = "fan"; tempAttribute2.data_type = "integer"; tempAttribute2.value = new List (); tempAttribute2.value.Add ("high"); tempAttribute2.value.Add ("medium"); tempAttribute2.value.Add ("low"); tempAttribute2.value.Add ("auto"); tempAttribute2.max = 3; tempAttribute2.min = 0; tmp.attributes.Add (tempAttribute2); #endregion #region temp Attribute tempAttribute3 = new Attribute (); tempAttribute3.key = "set_temp"; //2020 08 11 hvac 温度控制 1°-> int 0.5°->float //if (HVACModuleDeviceTypeList.HDLHVACwithAcControlHighPrecision.Contains(DevOnLineTmp.DeviceType)) //{ //20201224 设置温度数据类型统一float 伟南后续ai+数据类型网关处理 tempAttribute3.data_type = "float"; //} //else //{ // tempAttribute3.data_type = "integer"; //} tempAttribute3.value = new List (); tempAttribute3.max = 30; tempAttribute3.min = 16; tmp.attributes.Add (tempAttribute3); #endregion #region temp_step Attribute tempAttribute5 = new Attribute (); tempAttribute5.key = "set_temp_step"; tempAttribute5.data_type = "string"; tempAttribute5.value = new List (); tempAttribute5.value.Add ("up"); tempAttribute5.value.Add ("down"); tempAttribute5.max = 1; tempAttribute5.min = 0; tmp.attributes.Add (tempAttribute5); #endregion #region room_temp Attribute tempAttribute6 = new Attribute (); tempAttribute6.key = "room_temp"; tempAttribute6.data_type = "float"; tempAttribute6.value = new List (); tempAttribute6.max = 50; tempAttribute6.min = -50; tmp.attributes.Add (tempAttribute6); #endregion #region swing Attribute tempAttribute4 = new Attribute (); tempAttribute4.key = "swing"; tempAttribute4.data_type = "string"; tempAttribute4.value = new List (); tempAttribute4.value.Add ("up_down"); //tempAttribute4.value.Add("down"); tempAttribute4.value.Add ("left_right"); //tempAttribute4.value.Add("right"); tempAttribute4.value.Add ("stop"); tempAttribute4.max = 3; tempAttribute4.min = 0; tmp.attributes.Add (tempAttribute4); #endregion #region lock #endregion } else if (loopCommon.Type == DeviceType.FoolHeat || loopCommon.Type == DeviceType.FoolHeatPanel) { tmp.spk = SPK.FloorHeatStandard; //tmp.spk = "floorHeat.standard"; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "on_off"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("on"); tempAttribute.value.Add ("off"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion #region mode Attribute tempAttribute1 = new Attribute (); tempAttribute1.key = "mode"; tempAttribute1.data_type = "string"; tempAttribute1.value = new List (); tempAttribute1.value.Add ("day"); tempAttribute1.value.Add ("night"); tempAttribute1.value.Add ("away"); tempAttribute1.value.Add ("normal"); tempAttribute1.value.Add ("timer"); tempAttribute1.max = 4; tempAttribute1.min = 0; tmp.attributes.Add (tempAttribute1); #endregion #region temp Attribute tempAttribute3 = new Attribute (); tempAttribute3.key = "set_temp"; tempAttribute3.data_type = "float"; tempAttribute3.value = new List (); //tempAttribute3.value.Add("up"); //tempAttribute3.value.Add("down"); //tempAttribute3.value.Add("value"); tempAttribute3.max = 35; tempAttribute3.min = 0; tmp.attributes.Add (tempAttribute3); #endregion #region temp Attribute tempAttribute4 = new Attribute (); tempAttribute4.key = "set_temp_step"; tempAttribute4.data_type = "string"; tempAttribute4.value = new List (); tempAttribute4.value.Add ("up"); tempAttribute4.value.Add ("down"); tempAttribute4.max = 1; tempAttribute4.min = 0; tmp.attributes.Add (tempAttribute4); #endregion #region room_temp Attribute tempAttribute5 = new Attribute (); tempAttribute5.key = "room_temp"; tempAttribute5.data_type = "float"; tempAttribute5.value = new List (); tempAttribute5.max = 50; tempAttribute5.min = -50; tmp.attributes.Add (tempAttribute5); #endregion #region lock #endregion } else if (loopCommon.Type == DeviceType.MusicA31 || loopCommon.Type == DeviceType.MusicModel || loopCommon.Type == DeviceType.MusicPanel) { tmp.spk = SPK.MusicStandard; //tmp.spk = "music.standard"; // on_off volume song_step audio list_channel mode song_num special_song volume_level #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "on_off"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("play"); tempAttribute.value.Add ("pause"); //tempAttribute.value.Add("play"); //tempAttribute.value.Add("stop"); //tempAttribute.value.Add("pause"); //play stop pause tempAttribute.max = 2; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion #region volume Attribute tempAttribute1 = new Attribute (); tempAttribute1.key = "volume"; tempAttribute1.data_type = "integer"; tempAttribute1.value = new List (); //tempAttribute1.value.Add("percent"); tempAttribute1.max = 100; tempAttribute1.min = 0; tmp.attributes.Add (tempAttribute1); #endregion #region volume_step Attribute tempAttribute9 = new Attribute (); tempAttribute9.key = "volume_step"; tempAttribute9.data_type = "string"; tempAttribute9.value = new List (); tempAttribute9.value.Add ("up"); tempAttribute9.value.Add ("down"); tempAttribute9.max = 1; tempAttribute9.min = 0; tmp.attributes.Add (tempAttribute9); #endregion #region volume_level Attribute tempAttribute10 = new Attribute (); tempAttribute10.key = "volume_level"; tempAttribute10.data_type = "integer"; tempAttribute10.value = new List (); //tempAttribute1.value.Add("percent"); tempAttribute10.max = 10; tempAttribute10.min = 0; tmp.attributes.Add (tempAttribute10); #endregion #region volume_level_step Attribute tempAttribute11 = new Attribute (); tempAttribute11.key = "volume_level_step"; tempAttribute11.data_type = "string"; tempAttribute11.value = new List (); tempAttribute11.value.Add ("up"); tempAttribute11.value.Add ("down"); tempAttribute11.max = 1; tempAttribute11.min = 0; tmp.attributes.Add (tempAttribute11); #endregion #region treble Attribute tempAttribute14 = new Attribute (); tempAttribute14.key = "treble"; tempAttribute14.data_type = "integer"; tempAttribute14.max = 10; tempAttribute14.min = -10; tmp.attributes.Add (tempAttribute14); #endregion #region treble_step Attribute tempAttribute12 = new Attribute (); tempAttribute12.key = "treble_step"; tempAttribute12.data_type = "string"; tempAttribute12.value = new List (); tempAttribute12.value.Add ("up"); tempAttribute12.value.Add ("down"); tempAttribute12.max = 1; tempAttribute12.min = 0; tmp.attributes.Add (tempAttribute12); #endregion #region bass Attribute tempAttribute15 = new Attribute (); tempAttribute15.key = "bass"; tempAttribute15.data_type = "integer"; tempAttribute15.max = 10; tempAttribute15.min = -10; tmp.attributes.Add (tempAttribute15); #endregion #region bass_step Attribute tempAttribute13 = new Attribute (); tempAttribute13.key = "bass_step"; tempAttribute13.data_type = "string"; tempAttribute13.value = new List (); tempAttribute13.value.Add ("up"); tempAttribute13.value.Add ("down"); tempAttribute13.max = 1; tempAttribute13.min = 0; tmp.attributes.Add (tempAttribute13); #endregion #region mode Attribute tempAttribute5 = new Attribute (); tempAttribute5.key = "mode"; tempAttribute5.data_type = "string"; tempAttribute5.value = new List (); //singel/single_circle/order/all //single/single_cycle/order/list_cycle/random tempAttribute5.value.Add ("single"); tempAttribute5.value.Add ("single_cycle"); tempAttribute5.value.Add ("order"); tempAttribute5.value.Add ("list_cycle"); tempAttribute5.value.Add ("random"); tempAttribute5.max = 3; tempAttribute5.min = 0; tmp.attributes.Add (tempAttribute5); #endregion #region source //1 = SD, 2 = External Input, 3 = FTP, 4 = Radio //sdcard/external_input/ftp/radio Attribute tempAttribute3 = new Attribute (); tempAttribute3.key = "source"; tempAttribute3.data_type = "string"; tempAttribute3.value = new List (); tempAttribute3.value.Add ("sdcard"); tempAttribute3.value.Add ("audio_in"); tempAttribute3.value.Add ("ftp"); tempAttribute3.value.Add ("radio"); tempAttribute3.value.Add ("bluetooth"); tempAttribute3.max = 3; tempAttribute3.min = 0; tmp.attributes.Add (tempAttribute3); #endregion #region song_step Attribute tempAttribute2 = new Attribute (); tempAttribute2.key = "song_step"; tempAttribute2.data_type = "string"; tempAttribute2.value = new List (); tempAttribute2.value.Add ("up"); tempAttribute2.value.Add ("down"); tempAttribute2.max = 1; tempAttribute2.min = 0; tmp.attributes.Add (tempAttribute2); #endregion #region bass Attribute tempAttribute16 = new Attribute (); tempAttribute16.key = "playlist_name"; tempAttribute16.data_type = "string"; tmp.attributes.Add (tempAttribute16); #endregion #region bass Attribute tempAttribute17 = new Attribute (); tempAttribute17.key = "song_name"; tempAttribute17.data_type = "string"; tmp.attributes.Add (tempAttribute17); #endregion #region bass Attribute tempAttribute19 = new Attribute (); tempAttribute19.key = "song_time"; tempAttribute19.data_type = "string"; tmp.attributes.Add (tempAttribute19); #endregion #region bass Attribute tempAttribute20 = new Attribute (); tempAttribute20.key = "playing_time"; tempAttribute20.data_type = "string"; tmp.attributes.Add (tempAttribute20); #endregion } else if (loopCommon.BigClass == 5) { //传感器 if (loopCommon.Type == DeviceType.SensorMobileDetection) { tmp.spk = SPK.SensorPir; //tmp.spk = "sensor.pir"; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "enable"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("true"); tempAttribute.value.Add ("false"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion #region status Attribute tempAttribute1 = new Attribute (); tempAttribute1.key = "status"; tempAttribute1.data_type = "string"; tempAttribute1.value = new List (); tempAttribute1.value.Add ("true"); tempAttribute1.value.Add ("false"); tempAttribute1.max = 1; tempAttribute1.min = 0; tmp.attributes.Add (tempAttribute1); #endregion #region sensitivity Attribute tempAttribute2 = new Attribute (); tempAttribute2.key = "sensitivity"; tempAttribute2.data_type = "integer"; tempAttribute2.max = 100; tempAttribute2.min = 0; tmp.attributes.Add (tempAttribute2); #endregion }else if (loopCommon.Type == DeviceType.SensorTemperature) { tmp.spk = SPK.SensorTemperature; //tmp.spk = "sensor.temperature"; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "enable"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("true"); tempAttribute.value.Add ("false"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion #region temp Attribute tempAttribute1 = new Attribute (); tempAttribute1.key = "value"; //2020 12 22 tempAttribute1.data_type = "float"; tempAttribute1.max = 50; tempAttribute1.min = 0; tmp.attributes.Add (tempAttribute1); #endregion #region type Attribute tempAttribute2 = new Attribute (); tempAttribute2.key = "type"; tempAttribute2.data_type = "string"; tempAttribute2.value = new List (); tempAttribute2.value.Add ("C"); tempAttribute2.value.Add ("F"); tempAttribute2.max = 1; tempAttribute2.min = 0; tmp.attributes.Add (tempAttribute2); #endregion //#region precision //Function tempAttribute3 = new GateWay.Function(); //tempAttribute3.key = "precision"; //tempAttribute3.data_type = "string"; //tempAttribute3.value = new List(); //tempAttribute3.value.Add("0.01"); //tempAttribute3.value.Add("0.1"); //tempAttribute3.value.Add("100"); //tempAttribute3.max = 2; //tempAttribute3.min = 0; //tmp.attributes.Add(tempAttribute3); //#endregion }else if (loopCommon.Type == DeviceType.SensorIllumination) { //tmp.spk = "sensor.light"; tmp.spk = SPK.SensorLight; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "enable"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("true"); tempAttribute.value.Add ("false"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion #region lux Attribute tempAttribute1 = new Attribute (); tempAttribute1.key = "value"; //2020 12 22 tempAttribute1.data_type = "integer"; tmp.attributes.Add (tempAttribute1); #endregion #region error_value Attribute tempAttribute2 = new Attribute (); tempAttribute2.key = "error_value"; tempAttribute2.data_type = "integer"; tmp.attributes.Add (tempAttribute2); #endregion #region precision Attribute tempAttribute3 = new Attribute (); tempAttribute3.key = "precision"; tempAttribute3.data_type = "string"; tempAttribute3.value = new List (); tempAttribute3.value.Add ("0.01"); tempAttribute3.value.Add ("0.1"); tempAttribute3.value.Add ("100"); tempAttribute3.max = 2; tempAttribute3.min = 0; tmp.attributes.Add (tempAttribute3); #endregion } else if (loopCommon.Type == DeviceType.SensorPM25) { //tmp.spk = "sensor.pm25"; tmp.spk = SPK.SensorPm25; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "enable"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("true"); tempAttribute.value.Add ("false"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion #region value Attribute tempAttribute1 = new Attribute (); tempAttribute1.key = "value"; tempAttribute1.data_type = "integer"; tmp.attributes.Add (tempAttribute1); #endregion #region error_value Attribute tempAttribute2 = new Attribute (); tempAttribute2.key = "error_value"; tempAttribute2.data_type = "integer"; tmp.attributes.Add (tempAttribute2); #endregion #region precision Attribute tempAttribute3 = new Attribute (); tempAttribute3.key = "precision"; tempAttribute3.data_type = "string"; tempAttribute3.value = new List (); tempAttribute3.value.Add ("0.01"); tempAttribute3.value.Add ("0.1"); tempAttribute3.value.Add ("100"); tempAttribute3.max = 2; tempAttribute3.min = 0; tmp.attributes.Add (tempAttribute3); #endregion }else if (loopCommon.Type == DeviceType.SensorHumidity) { //tmp.spk = "sensor.humidity"; tmp.spk = SPK.SensorHumidity; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "enable"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("true"); tempAttribute.value.Add ("false"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion #region value Attribute tempAttribute1 = new Attribute (); tempAttribute1.key = "value"; tempAttribute1.data_type = "float"; tempAttribute1.max = 10000; tempAttribute1.min = 0; tmp.attributes.Add (tempAttribute1); #endregion }else if (loopCommon.Type == DeviceType.SensorTVOC) { //tmp.spk = "sensor.tvoc"; tmp.spk = SPK.SensorTVOC; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "enable"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("true"); tempAttribute.value.Add ("false"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion #region value Attribute tempAttribute1 = new Attribute (); tempAttribute1.key = "value"; tempAttribute1.data_type = "integer"; tempAttribute1.max = 10000; tempAttribute1.min = 0; tmp.attributes.Add (tempAttribute1); #endregion }else if (loopCommon.Type == DeviceType.SensorCO2) { //tmp.spk = "sensor.co2"; tmp.spk = SPK.SensorCO2; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "enable"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("true"); tempAttribute.value.Add ("false"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion #region value Attribute tempAttribute1 = new Attribute (); tempAttribute1.key = "value"; tempAttribute1.data_type = "integer"; tempAttribute1.max = 10000; tempAttribute1.min = 0; tmp.attributes.Add (tempAttribute1); #endregion }else if (loopCommon.Type == DeviceType.Sensor) { //tmp.spk = "dryContact.standard"; tmp.spk = SPK.DryContact; #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "enable"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("true"); tempAttribute.value.Add ("false"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion #region status Attribute tempAttribute1 = new Attribute (); tempAttribute1.key = "status"; tempAttribute1.data_type = "string"; tempAttribute1.value = new List (); tempAttribute1.value.Add ("on"); tempAttribute1.value.Add ("off"); tempAttribute1.max = 1; tempAttribute1.min = 0; tmp.attributes.Add (tempAttribute1); #endregion } else { #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "enable"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("true"); tempAttribute.value.Add ("false"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion #region value Attribute tempAttribute1 = new Attribute (); tempAttribute1.key = "value"; tempAttribute1.data_type = "integer"; tempAttribute1.max = 10000; tempAttribute1.min = 0; tmp.attributes.Add (tempAttribute1); #endregion } } else { #region on_off Attribute tempAttribute = new Attribute (); tempAttribute.key = "on_off"; tempAttribute.data_type = "string"; tempAttribute.value = new List (); tempAttribute.value.Add ("on"); tempAttribute.value.Add ("off"); tempAttribute.max = 1; tempAttribute.min = 0; tmp.attributes.Add (tempAttribute); #endregion } } catch { } return tmp; } #endregion #region 获取属性 #endregion //#region 判断类型 ///// ///// 继电器类别 ///// ///// ///// //public bool IsHDLRelayDeviceType (DeviceType deviceType) //{ // return false; //} ///// ///// 调光器类别 ///// ///// ///// //public bool IsHDLDimmerDeviceType (DeviceType deviceType) //{ // return false; //} ///// ///// 遮阳类别(窗帘、卷帘、开合帘) ///// ///// ///// //public bool IsHDLCurtainDeviceType (DeviceType deviceType) //{ // return deviceType == DeviceType.CurtainModel // || deviceType == DeviceType.CurtainRoller // || deviceType == DeviceType.CurtainTrietex; //} ///// ///// 传感器类别 ///// ///// ///// //public bool IsHDLSensorDeviceType (DeviceType deviceType) //{ // return false; //} ///// ///// 网关类别 ///// ///// ///// //public bool IsHDLGatewayDeviceType (DeviceType deviceType) //{ // return false; //} ///// ///// 空调 ///// ///// ///// //public bool IsHDLACDeviceType (DeviceType deviceType) //{ // return false; //} //#endregion } #region ■ 设备列表相关___________________________ [Serializable] public class BaseCloudFeedback { public int code { get; set; } public string timestamp { get; set; } public bool isSuccess { get; set; } public string message { get; set; } } [Serializable] public class Sids { public string homeId { get; set; } public string gatewayId { get; set; } public List devices { get; set; } } [Serializable] public class Oids { public string homeId { get; set; } public string gatewayId { get; set; } public List devices { get; set; } } [Serializable] public class Oid { public string protocolType { get; set; } public string device_name { get; set; } public string oid { get; set; } public string addresses { get; set; } public string device_model { get; set; } public string fw_version { get; set; } public string hw_info { get; set; } public string mac { get; set; } public int deviceType { get; set; } } [Serializable] public class Sid { public string sid { get; set; } public string name { get; set; } public string [] uids { get; set; } public string spk { get; set; } public string oid { get; set; } //设备模块地址 public string omodel { get; set; } //型号 public List attributes { get; set; } //属性列表 } /// /// 属性 /// [Serializable] public class Attribute { //public string name { get; set; } public string key { get; set; } public List value { get; set; } public int max { get; set; } public int min { get; set; } public string data_type { get; set; } } [Serializable] public class SidObject : Sid { } [Serializable] public class IotCloud { public Oids modules { get; set; } //设备列表 public Sids functions { get; set; } //功能列表 } /// /// 设备列表响应data参数 /// public class DevcieFunctionRes { public List list = new List (); //public string totalCount = "0"; //public string totalPage = "0"; //public string pageNo = "0"; //public string pageSize = "0"; } /// /// 功能类能满足数据使用要求,子类只是为了方便使用属性 /// public class Function { public Function () { } #region base info /// /// HDL统一协议格式:14bytes /// 举例: 来源 厂商代码 通讯方式 产品时间戳 产品类别 物模型类 通道号 大小类别 /// 1byte 1byte 1byte 4byte 1byte 2byte 2byte 2byte /// 来源:00 默认原生态系统数据 、01 网关或者其他A设备、02 调试软件、03 APP应用程序、04 第三方网关或者平台 /// 厂商代码:01 HDL /// 通讯方式:01 HDL Bus、02 Zigbee、03 KNX、04 Z-Wave /// 产品时间戳:4bytes 以2020年1月1日算出的时间戳0.1s为单位 /// 产品类别:01 调光器、02 继电器、03 干接点模块、04 传感器、05 面板 /// 物模型类型: /// 01 开关类:01 开关、02 插座、03 /// 02 照明: 01 开关、02 调光、03 色温、04 LED /// 03 遮阳: 01 窗帘电机、02 百叶窗、03 开合帘、04 卷帘 /// 04 恒温器:01 空调、02 地暖、03 毛细空调 /// 05 新风 /// 06 影音 /// 07 音乐 /// 08 能源 /// 09 安防 /// 大类别 1bytes (预留) /// 小类别 1byte (预留) /// public string sid = "0301011234567801012301230123"; /// /// /// public string oid; /// /// 备注 /// public string name; /// /// 设备ID /// 云端负责生成 /// public string deviceId = "0"; /// /// 设备spk /// public string spk = ""; /// /// /// string spk_Prefix; /// /// spk前缀 /// 大类 /// 功能类别 /// 如:空调类、灯光类、窗帘类 /// public string Spk_Prefix { get { if (string.IsNullOrEmpty (spk_Prefix)) { spk_Prefix = spk.Split (".") [0]; } return spk_Prefix; } } string spk_Suffix; /// /// A协议功能的特性 /// 如:是AC功能:特性:on_off,mode,fan,temperature /// attri /// public List attributes = new List (); /// /// 房间ID列表 /// 该功能添加到到房间列表 /// public List roomIds = new List (); /// /// bus协议数据格式 /// 使用A协议控制时,改属性为空 /// public BusData bus; /// /// 是否收藏 /// public bool collect = false; /// /// 是否在线 /// public bool online = true; /// /// 云端数据创建的时间 /// public string createTime = ""; /// /// 云端数据修改的最后时间 /// public string modifyTime = ""; /// /// 删除标记 /// 需要删除数据时,标记为:true /// 由云端删除成功之后,返回数据再清除本地数据 /// public bool DeleteSign = false; #endregion /// /// 延时 /// public int delay = 0; /// /// 最后控制的一次状态 /// [Newtonsoft.Json.JsonIgnore] public string lastState = ""; FunctionAttributes _trait_on_off; [Newtonsoft.Json.JsonIgnore] public FunctionAttributes trait_on_off { get { if (_trait_on_off == null) { _trait_on_off = attributes.Find ((obj) => obj.key == FunctionAttributeKey.OnOff); //找不到属性需要声明一个,防止报错闪退 if (_trait_on_off == null) { _trait_on_off = new FunctionAttributes () { key = "on_off", value = new List { "on", "off" }, max = 1, min = 0, }; _trait_on_off.curValue = "off"; } } if (_trait_on_off.curValue.ToString () != "on" && _trait_on_off.curValue.ToString () != "off") { _trait_on_off.curValue = "off"; } return _trait_on_off; } //set //{ // _trait_on_off = value; //} } /// /// 使用次数 /// public double controlCounter = 0; /// /// 使用频率 /// public double usageFrequency { get { return controlCounter / 7; } } /// /// 固定的序号 /// public int fixedSerialNumber = int.MaxValue; /// /// 大类小类 /// [Newtonsoft.Json.JsonIgnore] public string DeviceTypeString { get { if (!string.IsNullOrEmpty (sid) && sid.Length >= 28) { return sid.Substring (sid.Length - 4, 4); } else { return "0000"; } } } } /// /// 功能属性 /// 属性字段解析:attri :属性内容,value 属性的值,max 最大值 min 最小值 /// [System.Serializable] public class FunctionAttributes { /// /// 属性键名 /// public string key; /// /// 属性的值列表 /// public List value = new List (); /// /// 最大值 /// public int max = 100; /// /// 最小值 /// public int min = 0; /// /// 数据类型 /// public string data_type = ""; /// /// 当前值 /// public object curValue = new object (); } /// /// 功能属性键名列表 /// public static class FunctionAttributeKey { /// /// 开关 /// public const string OnOff = "on_off"; /// /// 亮度 /// public const string Brightness = "brightness"; /// /// 颜色 /// public const string RGB = "rgb"; /// /// 渐变时间 /// public const string FadeTime = "fade_time"; /// /// 模式 /// public const string Mode = "mode"; /// /// 风速 /// public const string FanSpeed = "fan"; /// /// 设置温度 /// public const string SetTemp = "set_temp"; /// /// 延时 /// public const string Delay = "delay"; /// /// 色温 /// public const string CCT = "cct"; /// /// 百分比 /// public const string Percent = "percent"; /// /// 室内温度 /// public const string IndoorTemp = "room_temp"; /// /// value /// public const string Value = "value"; /// /// 风扇档位 /// public const string FanSpeedPercent = "fan_speed_percent"; } /// /// 兼容旧协议控制 /// public class BusData { public string addresses = "FFFF"; [Newtonsoft.Json.JsonIgnore] public byte SubnetID { get { return Convert.ToByte (addresses.Substring (0, 2), 16); } } [Newtonsoft.Json.JsonIgnore] public byte DeviceID { get { return Convert.ToByte (addresses.Substring (2, 2), 16); } } public byte LoopId { get { return Convert.ToByte (loopId, 16); } } public string loopId; } public static class SPK { /// /// (开关灯) /// public const string LightSwitch = "light.switch"; /// /// (调光灯) /// public const string LightDimming = "light.dimming"; /// /// (RGB灯) /// public const string LightRGB = "light.rgb"; /// /// (RGBW灯) /// public const string LightRGBW = "light.rgbw"; /// /// (CCT灯) /// public const string LightCCT = "light.cct"; /// /// (开关窗帘) /// public const string CurtainSwitch = "curtain.switch"; /// /// (开合帘) /// public const string CurtainTrietex = "curtain.trietex"; /// /// (百叶帘) /// public const string CurtainShades = "curtain.shades"; /// /// (卷帘) /// public const string CurtainRoller = "curtain.roller"; /// /// (空调) /// public const string AcStandard = "ac.standard"; /// /// (地热) /// public const string FloorHeatStandard = "floorHeat.standard"; /// /// (新风) /// public const string AirFreshStandard = "airFresh.standard"; /// /// (音乐) /// public const string MusicStandard = "music.standard"; /// /// (亮度传感器) /// public const string SensorLight = "sensor.light"; /// /// (温度传感器) /// public const string SensorTemperature = "sensor.temperature"; /// /// (红外移动传感器) /// public const string SensorPir = "sensor.pir"; /// /// (门窗传感器) /// public const string SensorDoorWindow = "sensor.doorwindow"; /// /// (PM2.5传感器) /// public const string SensorPm25 = "sensor.pm25"; /// /// co2传感器 /// public const string SensorCO2 = "sensor.co2"; /// /// tvoc传感器 /// public const string SensorTVOC = "sensor.tvoc"; /// /// 湿度传感器 /// public const string SensorHumidity = "sensor.humidity"; /// /// (干接点) /// public const string DryContact = "dryContact.standard"; /// /// 家电、插座 /// public const string ElectricSocket = "electrical.socket"; /// /// 家电、电视 /// public const string ElectricTV = "electrical.tv"; /// /// 家电、风扇 /// public const string ElectricFan = "electrical.fan"; /// /// 其它、通用开关 /// public const string UniversalDevice = "other.common"; } /// /// 功能类别 /// public static class FunctionCategory { /// ///(灯) /// public const string Light = "light"; /// /// (窗帘) /// public const string Curtain = "curtain"; /// /// (空调) /// public const string AC = "ac"; /// /// (地热) /// public const string FloorHeat = "floorHeat"; /// /// (新风) /// public const string AirFresh = "airFresh"; /// /// (音乐) /// public const string Music = "music"; /// /// (传感器) /// public const string Sensor = "sensor"; /// /// (干接点) /// public const string DryContact = "dryContact"; /// /// 家电 /// public const string Electric = "electrical"; //Music = 0x09, } ///// ///// 上传Oid列表 ///// //[Serializable] //public class UploadOids //{ // public string homeId { get; set; } //住宅ID // public Oids devices { get; set; } //设备列表 //} ///// ///// 上传Sid列表 ///// //[Serializable] //public class UploadSids //{ // public string homeId { get; set; } //住宅ID // public string gatewayId { get; set; } //网关ID // public Sids devices { get; set; } //设备列表 //} //sid组成部分: //sid //来源 厂商代码 通讯方式 产品时间戳 产品类别 物模型类 通道号 大小类别 //1byte 1byte 1byte 4byte 1byte 2byte 2byte 2byte //oid组成部分: //来源 厂商代码 通讯方式 产品时间戳 产品类别 //1byte 1 byte 1 byte 4 byte 1byte //其中各部分代码列表: //来源 1byte 编号 描述 // 00 默认原生态系统数据 // 01 网关或者其他A设备 // 02 调试软件 // 03 APP应用程序 // 04 第三方网关或者平台 //厂商代码 1byte 编号 描述 // 01 HDL // 02 //通讯方式 1byte 编号 描述 // 01 HDL Bus // 02 Zigbee // 03 KNX // 04 Z-Wave //产品时间戳 4bytes 以2020年1月1日算出的时间戳0.1s为单位 //产品类别 1byte 编号 描述 // 01 调光器 // 02 继电器 // 03 干接点模块 // 04 传感器 // 05 面板 // 06 RCU // 07 网关 // 08 红外发射 // 09 Android屏 // 10 场景 // 11 音乐播放器 // 12 232/485转换器 // 21 自动化 // 22 安防防区 // 14 窗帘模块 // 15 HVAC // 16 地热模块 //物模型类型 2bytes 编号 描述 // 01 开关类 01 开关 // 02 插座 // 03 // 02 照明 01 开关 // 02 调光 // 03 色温(CCT) // 04 RGB // 03 遮阳 01 窗帘控制器 // 02 百叶窗 // 03 开合帘 // 04 卷帘 // 05  推窗器 // 06  投影幕 // 04 面板 01 按键面板 // 05 传感器 01 移动探测 // 02 温度传感器 // 03 湿度传感器 // 04 照度传感器 // 05 TVOC // 06 PM2.5 // 07 CO2 // 08 毫米波传感器 // 09 // 10 // 11 烟雾传感器 // 25 干接点 // 07 恒温器 01 空调 // 02 风扇 // 03 毛细空调 // 08 地热 01 地热模块 // 09 背景音乐 01 音乐播放器 // 02 Sonos // 10 场景 01 场景 // 02 电影场景 // 19 新风 01 新风 //13 能源 01 电表 // 02 水表 // 03 燃气 // 16 电器 01 风扇 // 02 TV // 20 安防 01 安防 // 21 自动化 01 自动化 //大类别 1bytes (预留) //小类别 1byte (预留) #endregion }