From 502d4ff743c1645adb469ab89c24826c4ec38f28 Mon Sep 17 00:00:00 2001 From: 陈嘉乐 <cjl@hdlchina.com.cn> Date: 星期五, 05 二月 2021 15:40:47 +0800 Subject: [PATCH] 2021-2-5-2 --- Crabtree/SmartHome/HDL/Common/HDLLinkUtlis.cs | 854 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 728 insertions(+), 126 deletions(-) diff --git a/Crabtree/SmartHome/HDL/Common/HDLLinkUtlis.cs b/Crabtree/SmartHome/HDL/Common/HDLLinkUtlis.cs index 94eedcd..c55a07d 100644 --- a/Crabtree/SmartHome/HDL/Common/HDLLinkUtlis.cs +++ b/Crabtree/SmartHome/HDL/Common/HDLLinkUtlis.cs @@ -1,8 +1,9 @@ 锘縰sing System; using System.Collections.Generic; using Shared; +using Shared.IO; -namespace SmartHome +namespace Shared { /// <summary> /// HDLLink鍗忚 宸ュ叿绫� @@ -28,6 +29,156 @@ #endregion + + + /// <summary> + /// + /// </summary> + /// <returns></returns> + 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); + 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 { + + } + return res; + } + + /// <summary> + /// + /// </summary> + /// <returns></returns> + public List<Common> GetAllDeviceList () + { + List<Common> TargetList = new List<Common> (); + + //鎵惧嚭闇�瑕佹樉绀虹殑璁惧 + var filesList = FileUtils.ReadFiles ().FindAll ((obj) => { + string [] str = obj.Split ('_'); + return obj.StartsWith ("Equipment_") && str.Length == 5; + }); + var localEquipments = filesList.FindAll ((obj) => { + string typeString = obj.Split ('_') [1]; + return ( + #region light + typeString.ToString () == DeviceType.LightCCT.ToString () || + typeString.ToString () == DeviceType.LightRGB.ToString () || + typeString.ToString () == DeviceType.LightDALI.ToString () || + typeString.ToString () == DeviceType.LightRGBW.ToString () || + typeString.ToString () == DeviceType.LightLogic.ToString () || + typeString.ToString () == DeviceType.LightSwitch.ToString () || + typeString.ToString () == DeviceType.LightDimming.ToString () || + typeString.ToString () == DeviceType.LightMixSwitch.ToString () || + typeString.ToString () == DeviceType.LightRGBandCCT.ToString () || + typeString.ToString () == DeviceType.LightMixDimming.ToString () || + typeString.ToString () == DeviceType.LightEnergySwitch.ToString () || + typeString.ToString () == DeviceType.LightEnergySocket.ToString () || + typeString.ToString () == DeviceType.LightSwitchSocket.ToString () + || typeString.ToString () == DeviceType.DMX48.ToString () + #endregion + #region light + || typeString.ToString () == DeviceType.SensorCH4.ToString () || + typeString.ToString () == DeviceType.SensorCO2.ToString () || + typeString.ToString () == DeviceType.SensorLPG.ToString () || + typeString.ToString () == DeviceType.SensorCOH2.ToString () || + typeString.ToString () == DeviceType.SensorPM25.ToString () || + typeString.ToString () == DeviceType.SensorTVOC.ToString () || + typeString.ToString () == DeviceType.SensorPower.ToString () || + typeString.ToString () == DeviceType.SensorSmoke.ToString () || + typeString.ToString () == DeviceType.SensorWater.ToString () || + typeString.ToString () == DeviceType.SensorWeight.ToString () || + typeString.ToString () == DeviceType.SensorCurrent.ToString () || + typeString.ToString () == DeviceType.SensorVoltage.ToString () + || typeString.ToString () == DeviceType.SensorRainfall.ToString () + || typeString.ToString () == DeviceType.SensorVelocity.ToString () + || typeString.ToString () == DeviceType.SensorMenciAndwindowMagnetic.ToString () + || typeString.ToString () == DeviceType.SensorMobileDetection.ToString () + || typeString.ToString () == DeviceType.SensorLiquidPressure.ToString () + || typeString.ToString () == DeviceType.SensorVibration.ToString () + || typeString.ToString () == DeviceType.SensorLiquidFlow.ToString () + || typeString.ToString () == DeviceType.SensorLiquidDepth.ToString () + || typeString.ToString () == DeviceType.SensorTemperature.ToString () + || typeString.ToString () == DeviceType.SensorHeightLength.ToString () + || typeString.ToString () == DeviceType.SensorIllumination.ToString () + || typeString.ToString () == DeviceType.SensorWindPressure.ToString () + || typeString.ToString () == DeviceType.SensorHumidity.ToString () + #endregion + #region curtain + || typeString.ToString () == DeviceType.CurtainModel.ToString () + || typeString.ToString () == DeviceType.CurtainRoller.ToString () + || typeString.ToString () == DeviceType.CurtainTrietex.ToString () + #endregion + #region ac + || typeString.ToString () == DeviceType.ACPanel.ToString () + || typeString.ToString () == DeviceType.ACDevice.ToString () + || typeString.ToString () == DeviceType.ACInfrared.ToString () + || typeString.ToString () == DeviceType.ACCoolmaster.ToString () + || typeString.ToString () == DeviceType.CustomAC.ToString () + || typeString.ToString () == DeviceType.HVAC.ToString () + #endregion + #region foolheat + || typeString.ToString () == DeviceType.FoolHeat.ToString () + || typeString.ToString () == DeviceType.FoolHeatPanel.ToString () + #endregion + #region + || typeString.ToString () == DeviceType.InfraredMode.ToString () + || typeString.ToString () == DeviceType.DoorLock.ToString () + || typeString.ToString () == DeviceType.FanModule.ToString () + || typeString.ToString () == DeviceType.FreshAir.ToString () + || typeString.ToString () == DeviceType.InfraredTV.ToString () + || typeString.ToString () == DeviceType.UniversalDevice.ToString () + || typeString.ToString () == DeviceType.MusicModel.ToString () + || typeString.ToString () == DeviceType.SecurityModule.ToString () + || typeString.ToString () == DeviceType.LogicModule.ToString () + || typeString.ToString () == DeviceType.SecurityPanel.ToString () + #endregion + ); + }); + + 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<Common> (System.Text.Encoding.UTF8.GetString (commonBytes)); + + if (commonDevice == null) { + continue; + } + + TargetList.Add (commonDevice); + } catch { + + } + } + return TargetList; + } /// <summary> @@ -35,35 +186,24 @@ /// </summary> /// <param name="moduleCommon">妯″潡璁惧</param> /// <returns></returns> - public List<Sid> ConvertToSidListToIotCloud (string sOid, Common moduleCommon) + public List<Sid> ConvertToSidListToIotCloud (string sOid, Common loopCommon) { - List<Sid> tmpResult = new List<Sid> (); + List<Sid> sidList = new List<Sid> (); try { - if (moduleCommon != null && moduleCommon.LoopCount > 0) { - for (int intI = 0; intI < moduleCommon.LoopCount; intI++) { - //byte BigType = moduleCommon.bytSimpleParam [0 + intI * 3]; - //byte SmallType = moduleCommon.bytSimpleParam [1 + intI * 3]; - int Count = moduleCommon.LoopCount; - if (Count > 0) { - for (int j = 1; j <= Count; j++) { - //妯″潡閲岄潰鐨勫崟涓洖璺� - Common deviceCommon = new Common (); - Sid tmpSid = new Sid (); - tmpSid.sid = FormingNewSid (sOid, deviceCommon); - tmpSid.oid = sOid; - tmpSid.name = deviceCommon.Name; + Sid tmpSid = new Sid (); + tmpSid.sid = FormingNewSid (sOid, loopCommon); + tmpSid.oid = sOid; + tmpSid.name = loopCommon.Name; - SidObject tmp = UpdateSidAttributesToDeviceList (deviceCommon, sOid); - tmpSid.attributes = tmp.attributes;//UpdateSidAttributesToDeviceList(onlineDevice.DeviceType, sOid, j, BigType, SmallType, ref spk); - tmpSid.spk = tmp.spk; - tmpResult.Add (tmpSid); - } - } - } - } - return tmpResult; + 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 tmpResult; + return sidList; } } @@ -74,26 +214,18 @@ /// <param name="onlineDevices"></param> /// <param name="gatewayId"></param> /// <param name="currentProject"></param> - public void ConvertOidListToIotStruct (string homeId, string gatewayId, List<Common> moduleCommonList, ref IotCloud currentProject) + public void ConvertOidListToIotStruct (string homeId, string gatewayId, List<Common> loopCommonList, ref IotCloud currentProject) { try { //step 1 杞崲绫诲瀷 Sids functionList = new Sids(); List<Sid> tmpFunction = new List<Sid> (); - //step 2 杞崲绫诲瀷 - Oids mOidList = ConvertToOidListToIotCloud (moduleCommonList, ref tmpFunction); - if (currentProject.modules == null || currentProject.modules.devices == null || currentProject.modules.devices.Count == 0) { - currentProject.modules = mOidList; - } else { - foreach (Oid tmpModule in mOidList.devices) { - Oid tmpFind = currentProject.modules.devices.Find (P => P.mac.Equals (tmpModule.mac)); - if (tmpFind == null) currentProject.modules.devices.Add (tmpModule); - } - } + //step 2 杞崲鐢熸垚Oids鍒楄〃鍜宻id 璁惧鍒楄〃 + Oids mOidList = ConvertToOidListToIotCloud (loopCommonList, ref tmpFunction); mOidList.homeId = homeId; - + //step 3 functionList.devices = new List<Sid> (); functionList.homeId = homeId; functionList.gatewayId = gatewayId; @@ -115,31 +247,46 @@ /// </summary> /// <param name="onlineDevices"></param> /// <returns></returns> - public Oids ConvertToOidListToIotCloud (List<Common> moduleCommonList, ref List<Sid> functionLists) + public Oids ConvertToOidListToIotCloud (List<Common> loopCommonListlolooloopl, ref List<Sid> functionLists) { - Oids tmpResult = new Oids (); + Oids mOidsList = new Oids (); try { - tmpResult.devices = new List<Oid> (); + mOidsList.devices = new List<Oid> (); //HDLSysPF.IniDeviceChannelRemark (); //鏁寸悊鍏ㄩ儴璁惧澶囨敞鍒扮紦瀛樺垪琛� - foreach (Common tmp in moduleCommonList) { - Oid tmpOid = new Oid (); - tmpOid.protocolType = "bus"; - tmpOid.device_name = tmp.Name; - tmpOid.oid = FormingNewOid (tmp.Type); - tmpOid.addresses = string.Format ("{0}{1}", tmp.SubnetID.ToString ("X2"), tmp.DeviceID.ToString ("X2")); - tmpOid.device_model = tmp.Type.ToString (); - tmpOid.fw_version = ""; - tmpOid.deviceType = tmp.Type.ToString (); - tmpOid.hw_info = ""; - tmpOid.mac = tmp.MAC; - tmpResult.devices.Add (tmpOid); + foreach (Common tmp in loopCommonListlolooloopl) { + //1.deviceType鏍囪瘑 浜戠鏄痠nt绫诲瀷 + var deviceType = ((int)tmp.Type); + //2.addresses鏍囪瘑 瀛愮綉鍙枫�佽澶囧彿 + var addresses = string.Format ("{0}{1}", tmp.SubnetID.ToString ("X2"), tmp.DeviceID.ToString ("X2")); + //3.鍒ゆ柇褰撳墠鍥炶矾璁惧涔嬪墠鏄惁鐢熸垚杩囩浉鍚屾ā鍧楃殑oid锛屽瓨鍦ㄥ垯鍙栦箣鍓嶇殑oid 娌℃湁鍒欏垱寤烘柊澧炴柊鐨刼id + var deviceOid = mOidsList.devices.Find (o => o.deviceType == deviceType && o.addresses == addresses); + if (deviceOid == null) { + //3.1娌℃湁鍒欏垱寤烘柊澧炴柊鐨刼id + Oid tmpOid = new Oid (); + tmpOid.protocolType = "bus"; + tmpOid.device_name = tmp.Type.ToString (); + tmpOid.oid = FormingNewOid (tmp.Type); + 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)); + functionLists.AddRange (ConvertToSidListToIotCloud (tmpOid.oid, tmp)); + + Utlis.WriteLine ("鏂扮殑妯″潡锛屾柊鐨勭殑OID锛�" + tmpOid.addresses + " deviceType:" + tmpOid.deviceType); + } else { + //3.2瀛樺湪鍒欏彇涔嬪墠鐨刼id + functionLists.AddRange (ConvertToSidListToIotCloud (deviceOid.oid, tmp)); + Utlis.WriteLine ("鐩稿悓鐨勬ā鍧楋紝鍙栦箣鍓嶇殑OID锛�" + deviceOid.addresses + " deviceType:" + deviceOid.deviceType); + } + } - return tmpResult; + return mOidsList; } catch (Exception ex) { - return tmpResult; - //throw; + return mOidsList; } } @@ -432,7 +579,7 @@ tmp.oid = sOid; tmp.sid = sSid; tmp.name = loopCommon.Name; - tmp.attributes = new List<Function> (); + tmp.attributes = new List<FunctionSid> (); tmp.omodel = loopCommon.Type.ToString (); //缁х數鍣ㄥ紑鍏崇被 if (loopCommon.Type == DeviceType.LightSwitch @@ -442,7 +589,7 @@ || loopCommon.Type == DeviceType.LightMixSwitch) { tmp.spk = "light.switch"; #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "on_off"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -458,7 +605,7 @@ //璋冨厜绫� tmp.spk = "light.dimming"; #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "on_off"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -470,7 +617,7 @@ #endregion #region brightness - Function tempFunction1 = new Function (); + FunctionSid tempFunction1 = new FunctionSid (); tempFunction1.key = "brightness"; tempFunction1.data_type = "integer"; tempFunction1.value = new List<string> (); @@ -481,7 +628,7 @@ #endregion #region fade_time - Function tempFunction3 = new Function (); + FunctionSid tempFunction3 = new FunctionSid (); tempFunction3.key = "fade_time"; tempFunction3.data_type = "integer"; tempFunction3.value = new List<string> (); @@ -499,7 +646,7 @@ { tmp.spk = "light.cct"; #region cct - Function tempFunction2 = new Function (); + FunctionSid tempFunction2 = new FunctionSid (); tempFunction2.key = "cct"; tempFunction2.data_type = "integer"; tempFunction2.value = new List<string> (); @@ -518,7 +665,7 @@ tmp.spk = "light.rgb"; #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "on_off"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -530,7 +677,7 @@ #endregion #region brightness - Function tempFunction2 = new Function (); + FunctionSid tempFunction2 = new FunctionSid (); tempFunction2.key = "brightness"; tempFunction2.data_type = "integer"; tempFunction2.value = new List<string> (); @@ -544,7 +691,7 @@ if (loopCommon.Type == DeviceType.LightRGBW) { tmp.spk = "light.rgbw"; #region color - Function tempFunction3 = new Function (); + FunctionSid tempFunction3 = new FunctionSid (); tempFunction3.key = "rgb"; tempFunction3.data_type = "integer"; tempFunction3.value = new List<string> (); @@ -557,7 +704,7 @@ #endregion } else { #region color - Function tempFunction3 = new Function (); + FunctionSid tempFunction3 = new FunctionSid (); tempFunction3.key = "rgb"; tempFunction3.data_type = "integer"; tempFunction3.value = new List<string> (); @@ -569,7 +716,7 @@ if (loopCommon.Type == DeviceType.LightRGBandCCT) { #region CCT - Function tempFunctionCCT = new Function (); + FunctionSid tempFunctionCCT = new FunctionSid (); tempFunctionCCT.key = "cct"; tempFunctionCCT.data_type = "integer"; tempFunctionCCT.value = new List<string> (); @@ -585,7 +732,7 @@ } else if (loopCommon.Type == DeviceType.CurtainModel || loopCommon.Type == DeviceType.CurtainRoller || loopCommon.Type == DeviceType.CurtainTrietex) { tmp.spk = "curtain.switch"; #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "on_off"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -600,7 +747,7 @@ { tmp.spk = "curtain.trietex"; #region openlevel - Function tempFunction1 = new Function (); + FunctionSid tempFunction1 = new FunctionSid (); tempFunction1.key = "percent"; tempFunction1.data_type = "integer"; tempFunction1.value = new List<string> (); @@ -620,7 +767,7 @@ //绌鸿皟绫� tmp.spk = "ac.standard"; #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "on_off"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -632,7 +779,7 @@ #endregion #region mode - Function tempFunction1 = new Function (); + FunctionSid tempFunction1 = new FunctionSid (); tempFunction1.key = "mode"; tempFunction1.data_type = "integer"; tempFunction1.value = new List<string> (); @@ -648,7 +795,7 @@ #endregion #region fan - Function tempFunction2 = new Function (); + FunctionSid tempFunction2 = new FunctionSid (); tempFunction2.key = "fan"; tempFunction2.data_type = "integer"; tempFunction2.value = new List<string> (); @@ -662,7 +809,7 @@ #endregion #region temp - Function tempFunction3 = new Function (); + FunctionSid tempFunction3 = new FunctionSid (); tempFunction3.key = "set_temp"; //2020 08 11 hvac 娓╁害鎺у埗 1掳-> int 0.5掳->float //if (HVACModuleDeviceTypeList.HDLHVACwithAcControlHighPrecision.Contains(DevOnLineTmp.DeviceType)) @@ -681,7 +828,7 @@ #endregion #region temp_step - Function tempFunction5 = new Function (); + FunctionSid tempFunction5 = new FunctionSid (); tempFunction5.key = "set_temp_step"; tempFunction5.data_type = "string"; tempFunction5.value = new List<string> (); @@ -693,7 +840,7 @@ #endregion #region room_temp - Function tempFunction6 = new Function (); + FunctionSid tempFunction6 = new FunctionSid (); tempFunction6.key = "room_temp"; tempFunction6.data_type = "float"; tempFunction6.value = new List<string> (); @@ -703,7 +850,7 @@ #endregion #region swing - Function tempFunction4 = new Function (); + FunctionSid tempFunction4 = new FunctionSid (); tempFunction4.key = "swing"; tempFunction4.data_type = "string"; tempFunction4.value = new List<string> (); @@ -725,7 +872,7 @@ || loopCommon.Type == DeviceType.FoolHeatPanel) { tmp.spk = "floorHeat.standard"; #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "on_off"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -737,7 +884,7 @@ #endregion #region mode - Function tempFunction1 = new Function (); + FunctionSid tempFunction1 = new FunctionSid (); tempFunction1.key = "mode"; tempFunction1.data_type = "string"; tempFunction1.value = new List<string> (); @@ -752,7 +899,7 @@ #endregion #region temp - Function tempFunction3 = new Function (); + FunctionSid tempFunction3 = new FunctionSid (); tempFunction3.key = "set_temp"; tempFunction3.data_type = "float"; tempFunction3.value = new List<string> (); @@ -765,7 +912,7 @@ #endregion #region temp - Function tempFunction4 = new Function (); + FunctionSid tempFunction4 = new FunctionSid (); tempFunction4.key = "set_temp_step"; tempFunction4.data_type = "string"; tempFunction4.value = new List<string> (); @@ -777,7 +924,7 @@ #endregion #region room_temp - Function tempFunction5 = new Function (); + FunctionSid tempFunction5 = new FunctionSid (); tempFunction5.key = "room_temp"; tempFunction5.data_type = "float"; tempFunction5.value = new List<string> (); @@ -796,7 +943,7 @@ tmp.spk = "music.standard"; // on_off volume song_step audio list_channel mode song_num special_song volume_level #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "on_off"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -813,7 +960,7 @@ #endregion #region volume - Function tempFunction1 = new Function (); + FunctionSid tempFunction1 = new FunctionSid (); tempFunction1.key = "volume"; tempFunction1.data_type = "integer"; tempFunction1.value = new List<string> (); @@ -824,7 +971,7 @@ #endregion #region volume_step - Function tempFunction9 = new Function (); + FunctionSid tempFunction9 = new FunctionSid (); tempFunction9.key = "volume_step"; tempFunction9.data_type = "string"; tempFunction9.value = new List<string> (); @@ -837,7 +984,7 @@ #region volume_level - Function tempFunction10 = new Function (); + FunctionSid tempFunction10 = new FunctionSid (); tempFunction10.key = "volume_level"; tempFunction10.data_type = "integer"; tempFunction10.value = new List<string> (); @@ -848,7 +995,7 @@ #endregion #region volume_level_step - Function tempFunction11 = new Function (); + FunctionSid tempFunction11 = new FunctionSid (); tempFunction11.key = "volume_level_step"; tempFunction11.data_type = "string"; tempFunction11.value = new List<string> (); @@ -860,7 +1007,7 @@ #endregion #region treble - Function tempFunction14 = new Function (); + FunctionSid tempFunction14 = new FunctionSid (); tempFunction14.key = "treble"; tempFunction14.data_type = "integer"; tempFunction14.max = 10; @@ -869,7 +1016,7 @@ #endregion #region treble_step - Function tempFunction12 = new Function (); + FunctionSid tempFunction12 = new FunctionSid (); tempFunction12.key = "treble_step"; tempFunction12.data_type = "string"; tempFunction12.value = new List<string> (); @@ -882,7 +1029,7 @@ #region bass - Function tempFunction15 = new Function (); + FunctionSid tempFunction15 = new FunctionSid (); tempFunction15.key = "bass"; tempFunction15.data_type = "integer"; tempFunction15.max = 10; @@ -891,7 +1038,7 @@ #endregion #region bass_step - Function tempFunction13 = new Function (); + FunctionSid tempFunction13 = new FunctionSid (); tempFunction13.key = "bass_step"; tempFunction13.data_type = "string"; tempFunction13.value = new List<string> (); @@ -903,7 +1050,7 @@ #endregion #region mode - Function tempFunction5 = new Function (); + FunctionSid tempFunction5 = new FunctionSid (); tempFunction5.key = "mode"; tempFunction5.data_type = "string"; tempFunction5.value = new List<string> (); @@ -922,7 +1069,7 @@ #region source //1 = SD, 2 = External Input, 3 = FTP, 4 = Radio //sdcard/external_input/ftp/radio - Function tempFunction3 = new Function (); + FunctionSid tempFunction3 = new FunctionSid (); tempFunction3.key = "source"; tempFunction3.data_type = "string"; tempFunction3.value = new List<string> (); @@ -937,7 +1084,7 @@ #endregion #region song_step - Function tempFunction2 = new Function (); + FunctionSid tempFunction2 = new FunctionSid (); tempFunction2.key = "song_step"; tempFunction2.data_type = "string"; tempFunction2.value = new List<string> (); @@ -949,28 +1096,28 @@ #endregion #region bass - Function tempFunction16 = new Function (); + FunctionSid tempFunction16 = new FunctionSid (); tempFunction16.key = "playlist_name"; tempFunction16.data_type = "string"; tmp.attributes.Add (tempFunction16); #endregion #region bass - Function tempFunction17 = new Function (); + FunctionSid tempFunction17 = new FunctionSid (); tempFunction17.key = "song_name"; tempFunction17.data_type = "string"; tmp.attributes.Add (tempFunction17); #endregion #region bass - Function tempFunction19 = new Function (); + FunctionSid tempFunction19 = new FunctionSid (); tempFunction19.key = "song_time"; tempFunction19.data_type = "string"; tmp.attributes.Add (tempFunction19); #endregion #region bass - Function tempFunction20 = new Function (); + FunctionSid tempFunction20 = new FunctionSid (); tempFunction20.key = "playing_time"; tempFunction20.data_type = "string"; tmp.attributes.Add (tempFunction20); @@ -980,7 +1127,7 @@ if (loopCommon.Type == DeviceType.SensorMobileDetection) { tmp.spk = "sensor.pir"; #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "enable"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -992,7 +1139,7 @@ #endregion #region status - Function tempFunction1 = new Function (); + FunctionSid tempFunction1 = new FunctionSid (); tempFunction1.key = "status"; tempFunction1.data_type = "string"; tempFunction1.value = new List<string> (); @@ -1004,7 +1151,7 @@ #endregion #region sensitivity - Function tempFunction2 = new Function (); + FunctionSid tempFunction2 = new FunctionSid (); tempFunction2.key = "sensitivity"; tempFunction2.data_type = "integer"; tempFunction2.max = 100; @@ -1014,7 +1161,7 @@ }else if (loopCommon.Type == DeviceType.SensorTemperature) { tmp.spk = "sensor.temperature"; #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "enable"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -1026,7 +1173,7 @@ #endregion #region temp - Function tempFunction1 = new Function (); + FunctionSid tempFunction1 = new FunctionSid (); tempFunction1.key = "value"; //2020 12 22 tempFunction1.data_type = "float"; tempFunction1.max = 50; @@ -1035,7 +1182,7 @@ #endregion #region type - Function tempFunction2 = new Function (); + FunctionSid tempFunction2 = new FunctionSid (); tempFunction2.key = "type"; tempFunction2.data_type = "string"; tempFunction2.value = new List<string> (); @@ -1061,7 +1208,7 @@ }else if (loopCommon.Type == DeviceType.SensorIllumination) { tmp.spk = "sensor.light"; #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "enable"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -1073,21 +1220,21 @@ #endregion #region lux - Function tempFunction1 = new Function (); + FunctionSid tempFunction1 = new FunctionSid (); tempFunction1.key = "value"; //2020 12 22 tempFunction1.data_type = "integer"; tmp.attributes.Add (tempFunction1); #endregion #region error_value - Function tempFunction2 = new Function (); + FunctionSid tempFunction2 = new FunctionSid (); tempFunction2.key = "error_value"; tempFunction2.data_type = "integer"; tmp.attributes.Add (tempFunction2); #endregion #region precision - Function tempFunction3 = new Function (); + FunctionSid tempFunction3 = new FunctionSid (); tempFunction3.key = "precision"; tempFunction3.data_type = "string"; tempFunction3.value = new List<string> (); @@ -1101,7 +1248,7 @@ } else if (loopCommon.Type == DeviceType.SensorPM25) { tmp.spk = "sensor.pm25"; #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "enable"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -1113,21 +1260,21 @@ #endregion #region value - Function tempFunction1 = new Function (); + FunctionSid tempFunction1 = new FunctionSid (); tempFunction1.key = "value"; tempFunction1.data_type = "integer"; tmp.attributes.Add (tempFunction1); #endregion #region error_value - Function tempFunction2 = new Function (); + FunctionSid tempFunction2 = new FunctionSid (); tempFunction2.key = "error_value"; tempFunction2.data_type = "integer"; tmp.attributes.Add (tempFunction2); #endregion #region precision - Function tempFunction3 = new Function (); + FunctionSid tempFunction3 = new FunctionSid (); tempFunction3.key = "precision"; tempFunction3.data_type = "string"; tempFunction3.value = new List<string> (); @@ -1141,7 +1288,7 @@ }else if (loopCommon.Type == DeviceType.SensorHumidity) { tmp.spk = "sensor.humidity"; #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "enable"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -1152,7 +1299,7 @@ tmp.attributes.Add (tempFunction); #endregion #region value - Function tempFunction1 = new Function (); + FunctionSid tempFunction1 = new FunctionSid (); tempFunction1.key = "value"; tempFunction1.data_type = "float"; tempFunction1.max = 10000; @@ -1162,7 +1309,7 @@ }else if (loopCommon.Type == DeviceType.SensorTVOC) { tmp.spk = "sensor.tvoc"; #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "enable"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -1173,7 +1320,7 @@ tmp.attributes.Add (tempFunction); #endregion #region value - Function tempFunction1 = new Function (); + FunctionSid tempFunction1 = new FunctionSid (); tempFunction1.key = "value"; tempFunction1.data_type = "integer"; tempFunction1.max = 10000; @@ -1183,7 +1330,7 @@ }else if (loopCommon.Type == DeviceType.SensorCO2) { tmp.spk = "sensor.co2"; #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "enable"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -1194,7 +1341,7 @@ tmp.attributes.Add (tempFunction); #endregion #region value - Function tempFunction1 = new Function (); + FunctionSid tempFunction1 = new FunctionSid (); tempFunction1.key = "value"; tempFunction1.data_type = "integer"; tempFunction1.max = 10000; @@ -1204,7 +1351,7 @@ }else if (loopCommon.Type == DeviceType.Sensor) { tmp.spk = "dryContact.standard"; #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "enable"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -1216,7 +1363,7 @@ #endregion #region status - Function tempFunction1 = new Function (); + FunctionSid tempFunction1 = new FunctionSid (); tempFunction1.key = "status"; tempFunction1.data_type = "string"; tempFunction1.value = new List<string> (); @@ -1228,7 +1375,7 @@ #endregion } else { #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "enable"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -1239,7 +1386,7 @@ tmp.attributes.Add (tempFunction); #endregion #region value - Function tempFunction1 = new Function (); + FunctionSid tempFunction1 = new FunctionSid (); tempFunction1.key = "value"; tempFunction1.data_type = "integer"; tempFunction1.max = 10000; @@ -1252,7 +1399,7 @@ } else { #region on_off - Function tempFunction = new Function (); + FunctionSid tempFunction = new FunctionSid (); tempFunction.key = "on_off"; tempFunction.data_type = "string"; tempFunction.value = new List<string> (); @@ -1407,7 +1554,7 @@ public string fw_version { get; set; } public string hw_info { get; set; } public string mac { get; set; } - public string deviceType { get; set; } + public int deviceType { get; set; } } [Serializable] @@ -1420,12 +1567,12 @@ public string oid { get; set; } //璁惧妯″潡鍦板潃 public string omodel { get; set; } //鍨嬪彿 - public List<Function> attributes { get; set; } //灞炴�у垪琛� + public List<FunctionSid> attributes { get; set; } //灞炴�у垪琛� } [Serializable] - public class Function + public class FunctionSid { //public string name { get; set; } public string key { get; set; } @@ -1448,6 +1595,461 @@ public Sids functions { get; set; } //鍔熻兘鍒楄〃 } + /// <summary> + /// 璁惧鍒楄〃鍝嶅簲data鍙傛暟 + /// </summary> + public class DevcieFunctionRes + { + public List<Function> list = new List<Function> (); + + //public string totalCount = "0"; + + //public string totalPage = "0"; + + //public string pageNo = "0"; + + //public string pageSize = "0"; + + } + + /// <summary> + /// 鍔熻兘绫昏兘婊¤冻鏁版嵁浣跨敤瑕佹眰锛屽瓙绫诲彧鏄负浜嗘柟渚夸娇鐢ㄥ睘鎬� + /// </summary> + public class Function + { + public Function () + { + } + + #region base info + /// <summary> + /// HDL缁熶竴鍗忚鏍煎紡锛�14bytes + /// 涓句緥锛� 鏉ユ簮 鍘傚晢浠g爜 閫氳鏂瑰紡 浜у搧鏃堕棿鎴� 浜у搧绫诲埆 鐗╂ā鍨嬬被 閫氶亾鍙� 澶у皬绫诲埆 + /// 1byte 1byte 1byte 4byte 1byte 2byte 2byte 2byte + /// 鏉ユ簮锛�00 榛樿鍘熺敓鎬佺郴缁熸暟鎹� 銆�01 缃戝叧鎴栬�呭叾浠朅璁惧銆�02 璋冭瘯杞欢銆�03 APP搴旂敤绋嬪簭銆�04 绗笁鏂圭綉鍏虫垨鑰呭钩鍙� + /// 鍘傚晢浠g爜锛�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 锛堥鐣欙級 + /// </summary> + public string sid = "0301011234567801012301230123"; + /// <summary> + /// + /// </summary> + public string oid; + /// <summary> + /// 澶囨敞 + /// </summary> + public string name; + /// <summary> + /// 璁惧ID + /// 浜戠璐熻矗鐢熸垚 + /// </summary> + public string deviceId = "0"; + /// <summary> + /// 璁惧spk + /// </summary> + public string spk = ""; + /// <summary> + /// + /// </summary> + string spk_Prefix; + /// <summary> + /// spk鍓嶇紑 + /// 澶х被 + /// 鍔熻兘绫诲埆 + /// 濡傦細绌鸿皟绫汇�佺伅鍏夌被銆佺獥甯樼被 + /// </summary> + public string Spk_Prefix { + get { + if (string.IsNullOrEmpty (spk_Prefix)) { + spk_Prefix = spk.Split (".") [0]; + } + return spk_Prefix; + } + } + string spk_Suffix; + + /// <summary> + /// A鍗忚鍔熻兘鐨勭壒鎬� + /// 濡傦細鏄疉C鍔熻兘锛氱壒鎬э細on_off,mode,fan,temperature + /// attri + /// </summary> + public List<FunctionAttributes> attributes = new List<FunctionAttributes> (); + + /// <summary> + /// 鎴块棿ID鍒楄〃 + /// 璇ュ姛鑳芥坊鍔犲埌鍒版埧闂村垪琛� + /// </summary> + public List<string> roomIds = new List<string> (); + + /// <summary> + /// bus鍗忚鏁版嵁鏍煎紡 + /// 浣跨敤A鍗忚鎺у埗鏃讹紝鏀瑰睘鎬т负绌� + /// </summary> + public BusData bus; + /// <summary> + /// 鏄惁鏀惰棌 + /// </summary> + public bool collect = false; + /// <summary> + /// 鏄惁鍦ㄧ嚎 + /// </summary> + public bool online = true; + /// <summary> + /// 浜戠鏁版嵁鍒涘缓鐨勬椂闂� + /// </summary> + public string createTime = ""; + /// <summary> + /// 浜戠鏁版嵁淇敼鐨勬渶鍚庢椂闂� + /// </summary> + public string modifyTime = ""; + /// <summary> + /// 鍒犻櫎鏍囪 + /// 闇�瑕佸垹闄ゆ暟鎹椂锛屾爣璁颁负锛歵rue + /// 鐢变簯绔垹闄ゆ垚鍔熶箣鍚庯紝杩斿洖鏁版嵁鍐嶆竻闄ゆ湰鍦版暟鎹� + /// </summary> + public bool DeleteSign = false; + + #endregion + /// <summary> + /// 寤舵椂 + /// </summary> + public int delay = 0; + /// <summary> + /// 鏈�鍚庢帶鍒剁殑涓�娆$姸鎬� + /// </summary> + [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); + //鎵句笉鍒板睘鎬ч渶瑕佸0鏄庝竴涓紝闃叉鎶ラ敊闂�� + if (_trait_on_off == null) { + _trait_on_off = new FunctionAttributes () { + key = "on_off", + value = new List<string> { "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; + //} + } + + /// <summary> + /// 浣跨敤娆℃暟 + /// </summary> + public double controlCounter = 0; + /// <summary> + /// 浣跨敤棰戠巼 + /// </summary> + public double usageFrequency { + get { + return controlCounter / 7; + } + } + /// <summary> + /// 鍥哄畾鐨勫簭鍙� + /// </summary> + public int fixedSerialNumber = int.MaxValue; + } + + + /// <summary> + /// 鍔熻兘灞炴�� + /// 灞炴�у瓧娈佃В鏋愶細attri :灞炴�у唴瀹癸紝value 灞炴�х殑鍊硷紝max 鏈�澶у�� min 鏈�灏忓�� + /// </summary> + [System.Serializable] + public class FunctionAttributes + { + /// <summary> + /// 灞炴�ч敭鍚� + /// </summary> + public string key; + /// <summary> + /// 灞炴�х殑鍊煎垪琛� + /// </summary> + public List<string> value = new List<string> (); + /// <summary> + /// 鏈�澶у�� + /// </summary> + public int max = 100; + /// <summary> + /// 鏈�灏忓�� + /// </summary> + public int min = 0; + /// <summary> + /// 鏁版嵁绫诲瀷 + /// </summary> + public string data_type = ""; + /// <summary> + /// 褰撳墠鍊� + /// </summary> + public object curValue = new object (); + + } + + + /// <summary> + /// 鍔熻兘灞炴�ч敭鍚嶅垪琛� + /// </summary> + public static class FunctionAttributeKey + { + /// <summary> + /// 寮�鍏� + /// </summary> + public const string OnOff = "on_off"; + /// <summary> + /// 浜害 + /// </summary> + public const string Brightness = "brightness"; + /// <summary> + /// 棰滆壊 + /// </summary> + public const string RGB = "rgb"; + /// <summary> + /// 娓愬彉鏃堕棿 + /// </summary> + public const string FadeTime = "fade_time"; + /// <summary> + /// 妯″紡 + /// </summary> + public const string Mode = "mode"; + /// <summary> + /// 椋庨�� + /// </summary> + public const string FanSpeed = "fan"; + /// <summary> + /// 璁剧疆娓╁害 + /// </summary> + public const string SetTemp = "set_temp"; + /// <summary> + /// 寤舵椂 + /// </summary> + public const string Delay = "delay"; + /// <summary> + /// 鑹叉俯 + /// </summary> + public const string CCT = "cct"; + /// <summary> + /// 鐧惧垎姣� + /// </summary> + public const string Percent = "percent"; + /// <summary> + /// 瀹ゅ唴娓╁害 + /// </summary> + public const string IndoorTemp = "room_temp"; + /// <summary> + /// value + /// </summary> + public const string Value = "value"; + } + + /// <summary> + /// 鍏煎鏃у崗璁帶鍒� + /// </summary> + 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 + { + /// <summary> + /// 锛堝紑鍏崇伅锛� + /// </summary> + public const string LightSwitch = "light.switch"; + /// <summary> + /// 锛堣皟鍏夌伅锛� + /// </summary> + public const string LightDimming = "light.dimming"; + /// <summary> + /// 锛圧GB鐏級 + /// </summary> + public const string LightRGB = "light.rgb"; + /// <summary> + /// 锛圧GBW鐏級 + /// </summary> + public const string LightRGBW = "light.rgbw"; + /// <summary> + /// 锛圕CT鐏級 + /// </summary> + public const string LightCCT = "light.cct"; + /// <summary> + /// 锛堝紑鍏崇獥甯橈級 + /// </summary> + public const string CurtainSwitch = "curtain.switch"; + /// <summary> + /// 锛堝紑鍚堝笜锛� + /// </summary> + public const string CurtainTrietex = "curtain.trietex"; + /// <summary> + /// 锛堢櫨鍙跺笜锛� + /// </summary> + public const string CurtainShades = "curtain.shades"; + /// <summary> + /// 锛堝嵎甯橈級 + /// </summary> + public const string CurtainRoller = "curtain.roller"; + /// <summary> + /// 锛堢┖璋冿級 + /// </summary> + public const string AcStandard = "ac.standard"; + /// <summary> + /// 锛堝湴鐑級 + /// </summary> + public const string FloorHeatStandard = "floorHeat.standard"; + /// <summary> + /// 锛堟柊椋庯級 + /// </summary> + public const string AirFreshStandard = "airFresh.standard"; + /// <summary> + /// 锛堥煶涔愶級 + /// </summary> + public const string MusicStandard = "music.standard"; + /// <summary> + /// 锛堜寒搴︿紶鎰熷櫒锛� + /// </summary> + public const string SensorLight = "sensor.light"; + /// <summary> + /// 锛堟俯搴︿紶鎰熷櫒锛� + /// </summary> + public const string SensorTemperature = "sensor.temperature"; + /// <summary> + /// (绾㈠绉诲姩浼犳劅鍣�) + /// </summary> + public const string SensorPir = "sensor.pir"; + /// <summary> + /// 锛堥棬绐椾紶鎰熷櫒锛� + /// </summary> + public const string SensorDoorWindow = "sensor.doorwindow"; + /// <summary> + /// 锛圥M2.5浼犳劅鍣級 + /// </summary> + public const string SensorPm25 = "sensor.pm25"; + /// <summary> + /// co2浼犳劅鍣� + /// </summary> + public const string SensorCO2 = "sensor.co2"; + /// <summary> + /// tvoc浼犳劅鍣� + /// </summary> + public const string SensorTVOC = "sensor.tvoc"; + /// <summary> + /// 婀垮害浼犳劅鍣� + /// </summary> + public const string SensorHumidity = "sensor.humidity"; + /// <summary> + /// 锛堝共鎺ョ偣锛� + /// </summary> + public const string DryContact = "dryContact.standard"; + /// <summary> + /// 瀹剁數銆佹彃搴� + /// </summary> + public const string ElectricSocket = "electrical.socket"; + /// <summary> + /// 瀹剁數銆佺數瑙� + /// </summary> + public const string ElectricTV = "electrical.tv"; + /// <summary> + /// 瀹剁數銆侀鎵� + /// </summary> + public const string ElectricFan = "electrical.fan"; + + } + + + /// <summary> + /// 鍔熻兘绫诲埆 + /// </summary> + public static class FunctionCategory + { + /// <summary> + ///锛堢伅锛� + /// </summary> + public const string Light = "light"; + /// <summary> + /// 锛堢獥甯橈級 + /// </summary> + public const string Curtain = "curtain"; + /// <summary> + /// 锛堢┖璋冿級 + /// </summary> + public const string AC = "ac"; + /// <summary> + /// 锛堝湴鐑級 + /// </summary> + public const string FloorHeat = "floorHeat"; + /// <summary> + /// 锛堟柊椋庯級 + /// </summary> + public const string AirFresh = "airFresh"; + /// <summary> + /// 锛堥煶涔愶級 + /// </summary> + public const string Music = "music"; + /// <summary> + /// 锛堜紶鎰熷櫒锛� + /// </summary> + public const string Sensor = "sensor"; + /// <summary> + /// 锛堝共鎺ョ偣锛� + /// </summary> + public const string DryContact = "dryContact"; + /// <summary> + /// 瀹剁數 + /// </summary> + public const string Electric = "electrical"; + + //Music = 0x09, + } + + ///// <summary> ///// 涓婁紶Oid鍒楄〃 ///// </summary> -- Gitblit v1.8.0