using System; using Newtonsoft.Json.Linq; namespace ZigBee.Device { [System.Serializable] public class Rollershade : CurtainBase { public Rollershade() { this.Type = DeviceType.WindowCoveringDevice; } /// ///窗帘当前模式. /// WcdType=4:开合帘 /// WcdType=0:卷帘 /// public int WcdType = -1; /// /// 当前窗帘所在的位置(百分比). /// [Newtonsoft.Json.JsonIgnore] public int WcdCurrentPositionLiftPercentage = 0; /// /// 读取当前窗帘的模式 /// AttriButeId=0 (先调用发现属性接口,查看设备是否支持该接口的属性) /// public new void ReadWcdType() { ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.WindowCoveringType); } /// /// 读取当前窗帘模式 /// /// /// public static void ReadWcdTypeAction(CommonDevice commonDevice, Action action) { new System.Threading.Thread(() => { (commonDevice as Rollershade).ReadWcdType(); var dateTime = DateTime.Now; while ((DateTime.Now - dateTime).TotalSeconds < 10) { System.Threading.Thread.Sleep(100); if ((commonDevice as Rollershade).WcdType != -1) { break; } } action?.Invoke(); }) { IsBackground = true }.Start(); } /// /// 窗帘当前倾斜度,单位:0.1° /// AttriButeId=3 (先调用发现属性接口,查看设备是否支持该接口的属性) /// public void ReadWcdCurrentPositionLift() { ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.CurrentPositionLift); } /// /// 读取当前窗帘所在的位置(百分比) /// AttriButeId=8 (先调用发现属性接口,查看设备是否支持该接口的属性) /// public void ReadWcdCurrentPositionLiftPercentage() { ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.CurrentPositionLiftPercentage); } /// /// 窗帘全开所在的位置,单位:cm /// AttriButeId=16 (先调用发现属性接口,查看设备是否支持该接口的属性) /// public void ReadWcdInstalledOpenLimitLift() { ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.InstalledOpenLimitLift); } /// /// 窗帘全开所在的角度,单位:0.1° /// AttriButeId=17 (先调用发现属性接口,查看设备是否支持该接口的属性) /// public void ReadWcdInstalledClosedLimitLift() { ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.InstalledClosedLimitLift); } /// /// 窗帘全关所在的位置,单位:cm /// AttriButeId=18 (先调用发现属性接口,查看设备是否支持该接口的属性) /// public void ReadWcdInstalledOpenLimitTilt() { ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.InstalledOpenLimitTilt); } /// /// 窗帘全关所在的角度,单位:0.1° /// AttriButeId=19 (先调用发现属性接口,查看设备是否支持该接口的属性) /// public void ReadWcdInstalledClosedLimitTilt() { ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.InstalledClosedLimitTilt); } /// /// 读取当前窗帘的模式 /// AttriButeId=23 (先调用发现属性接口,查看设备是否支持该接口的属性) /// public void ReadWcdCurrentMode() { ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.WindowCoveringMode); } /// /// 读取开合帘电机方向/维护模式 /// public void ReadCurtainDirectionAndMode() { ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.WindowCoveringMode); } /// /// 读取开合帘限位开(上)限位 /// 窗帘全开所在的位置,单位:cm /// public void ReadWcdInstalOpenLimit() { ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.InstalledOpenLimitLift); } /// /// 读取开合帘总长 /// 窗帘总的长度,单位:cm /// public void ReadWcdLength() { ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.WindowCoveringLength); } /// /// 读取开合帘限位关(下)限位 /// 窗帘全关所在的位置,单位:cm /// public void ReadWcdInstalCloseLimit() { ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.InstalledClosedLimitLift); } /// ///窗帘设备调整到指定高度. /// comand=4 (先调用设备发现命令接口,查看设备是否支持该接口命令) ///value:窗帘要调整到的高度值处 /// 参数长度(占用的字节数):2 /// public void WcdGoToLiftValue(int value) { var jObject = new JObject { { "DeviceAddr", DeviceAddr}, { "Epoint", DeviceEpoint}, { "Cluster_ID", 258 }, { "Command", 4}, { "SendMode", 2 } }; var data = new JObject { { "Value", value } }; jObject.Add("Data", data); Gateway?.Send("DeviceControl", jObject.ToString()); } /// ///将窗帘调整到指定的百分比处的位置. /// comand=5 (先调用设备发现命令接口,查看设备是否支持该接口命令) ///窗帘要调整到的百分比处,范围:0~100表示 0-100% ///参数长度(占用的字节数):1 /// public void WcdGoToTiltValue(int value) { var jObject = new JObject { { "DeviceAddr", DeviceAddr}, { "Epoint", DeviceEpoint}, { "Cluster_ID",258}, { "Command", 5}, { "SendMode", 2 } }; var data = new JObject { { "Value", value } }; jObject.Add("Data", data); Gateway?.Send("DeviceControl", jObject.ToString()); } /// ///让窗帘设备将窗帘调整到指定的倾斜角 /// comand=7 (先调用设备发现命令接口,查看设备是否支持该接口命令) ///value:窗帘要调整到的倾斜角处 单位(0.1°) /// 参数长度(占用的字节数):2 /// public void WcdGoToLiftPercentpage(int value) { var jObject = new JObject { { "DeviceAddr", DeviceAddr}, { "Epoint", DeviceEpoint}, { "Cluster_ID", 258 }, { "Command", 7}, { "SendMode", 2 } }; var data = new JObject { { "Value", value } }; jObject.Add("Data", data); Gateway?.Send("DeviceControl", jObject.ToString()); } /// ///让窗帘设备将窗帘调整到指定的百分比倾斜度 /// comand=8 (先调用设备发现命令接口,查看设备是否支持该接口命令) ///value:窗帘要调整到的百分比倾斜度 ///范围:0-100表示0-100% /// 参数长度(占用的字节数):1 /// public void WcdGoToTiltPercentpage(int value) { var jObject = new JObject { { "DeviceAddr", DeviceAddr}, { "Epoint", DeviceEpoint}, { "Cluster_ID", 258}, { "Command", 8}, { "SendMode", 2 } }; var data = new JObject { { "Value", value } }; jObject.Add("Data", data); Gateway?.Send("DeviceControl", jObject.ToString()); } #region 设置开合帘限位参数. /// /// 设置开合帘上下限位 /// public async System.Threading.Tasks.Task SetCurtainInstalledLimitAsync(CurtainPrivateInstalledLimi installedLimit) { if (Gateway == null) { return null; } return await System.Threading.Tasks.Task.Run(async () => { SetWritableValueResponAllData d = null; Action action = (topic, message) => { var gatewayID = topic.Split('/')[0]; var jobject = Newtonsoft.Json.Linq.JObject.Parse(message); if (topic == gatewayID + "/" + "Error_Respon") { var temp = Newtonsoft.Json.JsonConvert.DeserializeObject(jobject["Data"].ToString()); if (temp == null) { d = new SetWritableValueResponAllData { errorMessageBase = "网关错误回复,且数据是空" }; } else { d = new SetWritableValueResponAllData { errorResponData = temp, errorMessageBase = ErrorMess(temp.Error) }; } } if (topic == gatewayID + "/" + "SetWritableValue_Respon") { var tempData = Newtonsoft.Json.JsonConvert.DeserializeObject(jobject["Data"].ToString()); if (tempData == null) { d = new SetWritableValueResponAllData { errorMessageBase = "网关返回的数据为空" }; } else { d = new SetWritableValueResponAllData { setWritableValueResponData = tempData }; System.Console.WriteLine($"UI收到通知后的主题_{ topic}"); } } }; Gateway.Actions += action; System.Console.WriteLine("SetWritableValue_Actions 启动" + "_" + System.DateTime.Now.ToString()); try { int tempLimit = 0; switch (installedLimit) { case CurtainPrivateInstalledLimi.UpLimit: tempLimit = 2; break; case CurtainPrivateInstalledLimi.DownLimit: tempLimit = 1; break; } var jObject = new JObject { { "DeviceAddr", DeviceAddr }, { "Epoint", DeviceEpoint }, { "Cluster_ID", 258 }, { "Command", 120 } }; var data = new JObject { { "Undivided", 0 }, { "AttributeId", 0xea01 }, { "AttributeDataType", 32 }, { "AttributeData", tempLimit } }; jObject.Add("Data", data); Gateway.Send("SetWritableValue", jObject.ToString()); } catch { } var dateTime = DateTime.Now; while ((DateTime.Now - dateTime).TotalMilliseconds < WaitReceiveDataTime) { await System.Threading.Tasks.Task.Delay(10); if (d != null) { break; } } if ((DateTime.Now - dateTime).TotalMilliseconds > WaitReceiveDataTime) { d = new SetWritableValueResponAllData { errorMessageBase = " 回复超时,请重新操作" }; } Gateway.Actions -= action; System.Console.WriteLine("SetWritableValue_Actions 退出" + System.DateTime.Now.ToString()); return d; }); } /// /// 开合帘限位 /// public enum CurtainPrivateInstalledLimi { /// /// 窗帘全开所在的位置(上限位) /// UpLimit = 2, /// /// 窗帘全关所在的位置(下限位) /// DownLimit = 1, } #endregion #region 设置恢复窗帘行程限位. /// /// 设置恢复窗帘行程限位 /// public async System.Threading.Tasks.Task RestoreCurtainLimitAsync() { if (Gateway == null) { return null; } return await System.Threading.Tasks.Task.Run(async () => { SetWritableValueResponAllData d = null; Action action = (topic, message) => { var gatewayID = topic.Split('/')[0]; var jobject = Newtonsoft.Json.Linq.JObject.Parse(message); if (topic == gatewayID + "/" + "Error_Respon") { var temp = Newtonsoft.Json.JsonConvert.DeserializeObject(jobject["Data"].ToString()); if (temp == null) { d = new SetWritableValueResponAllData { errorMessageBase = "网关错误回复,且数据是空" }; } else { d = new SetWritableValueResponAllData { errorResponData = temp, errorMessageBase = ErrorMess(temp.Error) }; } } if (topic == gatewayID + "/" + "SetWritableValue_Respon") { var tempData = Newtonsoft.Json.JsonConvert.DeserializeObject(jobject["Data"].ToString()); if (tempData == null) { d = new SetWritableValueResponAllData { errorMessageBase = "网关返回的数据为空" }; } else { d = new SetWritableValueResponAllData { setWritableValueResponData = tempData }; System.Console.WriteLine($"UI收到通知后的主题_{ topic}"); } } }; Gateway.Actions += action; System.Console.WriteLine("SetWritableValue_Actions 启动" + "_" + System.DateTime.Now.ToString()); try { var jObject = new JObject { { "DeviceAddr", DeviceAddr }, { "Epoint", DeviceEpoint }, { "Cluster_ID", 258 }, { "Command", 120 } }; var data = new JObject { { "Undivided", 0 }, { "AttributeId", 0xea02 }, { "AttributeDataType", 32 }, { "AttributeData", 1 } }; jObject.Add("Data", data); Gateway.Send("SetWritableValue", jObject.ToString()); } catch { } var dateTime = DateTime.Now; while ((DateTime.Now - dateTime).TotalMilliseconds < WaitReceiveDataTime) { await System.Threading.Tasks.Task.Delay(10); if (d != null) { break; } } if ((DateTime.Now - dateTime).TotalMilliseconds > WaitReceiveDataTime) { d = new SetWritableValueResponAllData { errorMessageBase = " 回复超时,请重新操作" }; } Gateway.Actions -= action; System.Console.WriteLine("SetWritableValue_Actions 退出" + System.DateTime.Now.ToString()); return d; }); } /// /// 开合帘限位 /// enum CurtainPrivateAttribute { /// /// 窗帘行程限位 /// AttributeLimit = 0xea01, /// /// 设置恢复窗帘行程限位 /// RestoreLimit = 0xea02, } #endregion #region 删除窗帘限位 /// /// 删除窗帘限位 /// public async System.Threading.Tasks.Task DeleteCurtainLimitsAsync(LimiType limiType) { if (Gateway == null) { return null; } return await System.Threading.Tasks.Task.Run(async () => { SetWritableValueResponAllData d = null; Action action = (topic, message) => { var gatewayID = topic.Split('/')[0]; var jobject = Newtonsoft.Json.Linq.JObject.Parse(message); if (topic == gatewayID + "/" + "Error_Respon") { var temp = Newtonsoft.Json.JsonConvert.DeserializeObject(jobject["Data"].ToString()); if (temp == null) { d = new SetWritableValueResponAllData { errorMessageBase = "网关错误回复,且数据是空" }; } else { d = new SetWritableValueResponAllData { errorResponData = temp, errorMessageBase = ErrorMess(temp.Error) }; } } if (topic == gatewayID + "/" + "SetWritableValue_Respon") { var tempData = Newtonsoft.Json.JsonConvert.DeserializeObject(jobject["Data"].ToString()); if (tempData == null) { d = new SetWritableValueResponAllData { errorMessageBase = "网关返回的数据为空" }; } else { d = new SetWritableValueResponAllData { setWritableValueResponData = tempData }; System.Console.WriteLine($"UI收到通知后的主题_{ topic}"); } } }; Gateway.Actions += action; System.Console.WriteLine("SetWritableValue_Actions 启动" + "_" + System.DateTime.Now.ToString()); try { int tempLimit = 0; switch (limiType) { case LimiType.DownLimit: tempLimit = 2; break; case LimiType.UpLimit: tempLimit = 8; break; } var jObject = new JObject { { "DeviceAddr", DeviceAddr }, { "Epoint", DeviceEpoint }, { "Cluster_ID", 258 }, { "Command", 120 } }; var data = new JObject { { "Undivided", 0 }, { "AttributeId", 0xea02 }, { "AttributeDataType", 32 }, { "AttributeData", tempLimit } }; jObject.Add("Data", data); Gateway.Send("SetWritableValue", jObject.ToString()); } catch { } var dateTime = DateTime.Now; while ((DateTime.Now - dateTime).TotalMilliseconds < WaitReceiveDataTime) { await System.Threading.Tasks.Task.Delay(10); if (d != null) { break; } } if ((DateTime.Now - dateTime).TotalMilliseconds > WaitReceiveDataTime) { d = new SetWritableValueResponAllData { errorMessageBase = " 回复超时,请重新操作" }; } Gateway.Actions -= action; System.Console.WriteLine("SetWritableValue_Actions 退出" + System.DateTime.Now.ToString()); return d; }); } /// /// 删除窗帘开合帘限位 /// public enum LimiType { /// /// 删除窗帘上限位 /// UpLimit = 0x08, /// /// 删除窗帘下限位 /// DownLimit = 0x02, } #endregion } }