New file |
| | |
| | | using System; |
| | | using Newtonsoft.Json.Linq; |
| | | |
| | | namespace ZigBee.Device |
| | | { |
| | | [System.Serializable] |
| | | public class Rollershade : CurtainBase |
| | | { |
| | | public Rollershade() |
| | | { |
| | | this.Type = DeviceType.WindowCoveringDevice; |
| | | } |
| | | |
| | | /// <summary> |
| | | ///窗帘当前模式. |
| | | /// WcdType=4:开合帘 |
| | | /// WcdType=0:卷帘 |
| | | /// </summary> |
| | | public int WcdType = -1; |
| | | /// <summary> |
| | | /// 当前窗帘所在的位置(百分比). |
| | | /// </summary> |
| | | [Newtonsoft.Json.JsonIgnore] |
| | | public int WcdCurrentPositionLiftPercentage = 0; |
| | | |
| | | /// <summary> |
| | | /// 读取当前窗帘的模式 |
| | | /// <para>AttriButeId=0 (先调用发现属性接口,查看设备是否支持该接口的属性)</para> |
| | | /// </summary> |
| | | public new void ReadWcdType() |
| | | { |
| | | ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.WindowCoveringType); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 读取当前窗帘模式 |
| | | /// </summary> |
| | | /// <param name="commonDevice"></param> |
| | | /// <param name="action"></param> |
| | | 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(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 窗帘当前倾斜度,单位:0.1° |
| | | /// <para>AttriButeId=3 (先调用发现属性接口,查看设备是否支持该接口的属性)</para> |
| | | /// </summary> |
| | | public void ReadWcdCurrentPositionLift() |
| | | { |
| | | ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.CurrentPositionLift); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 读取当前窗帘所在的位置(百分比) |
| | | /// <para>AttriButeId=8 (先调用发现属性接口,查看设备是否支持该接口的属性)</para> |
| | | /// </summary> |
| | | public void ReadWcdCurrentPositionLiftPercentage() |
| | | { |
| | | ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.CurrentPositionLiftPercentage); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 窗帘全开所在的位置,单位:cm |
| | | /// <para>AttriButeId=16 (先调用发现属性接口,查看设备是否支持该接口的属性)</para> |
| | | /// </summary> |
| | | public void ReadWcdInstalledOpenLimitLift() |
| | | { |
| | | ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.InstalledOpenLimitLift); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 窗帘全开所在的角度,单位:0.1° |
| | | /// <para>AttriButeId=17 (先调用发现属性接口,查看设备是否支持该接口的属性)</para> |
| | | /// </summary> |
| | | public void ReadWcdInstalledClosedLimitLift() |
| | | { |
| | | ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.InstalledClosedLimitLift); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 窗帘全关所在的位置,单位:cm |
| | | /// <para>AttriButeId=18 (先调用发现属性接口,查看设备是否支持该接口的属性)</para> |
| | | /// </summary> |
| | | public void ReadWcdInstalledOpenLimitTilt() |
| | | { |
| | | ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.InstalledOpenLimitTilt); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 窗帘全关所在的角度,单位:0.1° |
| | | /// <para>AttriButeId=19 (先调用发现属性接口,查看设备是否支持该接口的属性)</para> |
| | | /// </summary> |
| | | public void ReadWcdInstalledClosedLimitTilt() |
| | | { |
| | | ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.InstalledClosedLimitTilt); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 读取当前窗帘的模式 |
| | | /// <para>AttriButeId=23 (先调用发现属性接口,查看设备是否支持该接口的属性)</para> |
| | | /// </summary> |
| | | public void ReadWcdCurrentMode() |
| | | { |
| | | ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.WindowCoveringMode); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 读取开合帘电机方向/维护模式 |
| | | /// </summary> |
| | | public void ReadCurtainDirectionAndMode() |
| | | { |
| | | ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.WindowCoveringMode); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 读取开合帘限位开(上)限位 |
| | | /// <para>窗帘全开所在的位置,单位:cm</para> |
| | | /// </summary> |
| | | public void ReadWcdInstalOpenLimit() |
| | | { |
| | | ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.InstalledOpenLimitLift); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 读取开合帘总长 |
| | | /// <para>窗帘总的长度,单位:cm</para> |
| | | /// </summary> |
| | | public void ReadWcdLength() |
| | | { |
| | | ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.WindowCoveringLength); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 读取开合帘限位关(下)限位 |
| | | /// <para>窗帘全关所在的位置,单位:cm</para> |
| | | /// </summary> |
| | | public void ReadWcdInstalCloseLimit() |
| | | { |
| | | ReadAttri(Device.Cluster_ID.WindowCovering, AttriButeId.InstalledClosedLimitLift); |
| | | } |
| | | |
| | | ///<summary > |
| | | ///窗帘设备调整到指定高度. |
| | | /// <para>comand=4 (先调用设备发现命令接口,查看设备是否支持该接口命令)</para> |
| | | ///<para>value:窗帘要调整到的高度值处</para> |
| | | ///<para> 参数长度(占用的字节数):2</para> |
| | | /// </summary> |
| | | 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()); |
| | | } |
| | | |
| | | ///<summary > |
| | | ///将窗帘调整到指定的百分比处的位置. |
| | | /// <para>comand=5 (先调用设备发现命令接口,查看设备是否支持该接口命令)</para> |
| | | ///<para>窗帘要调整到的百分比处,范围:0~100表示 0-100%</para> |
| | | ///<para>参数长度(占用的字节数):1</para> |
| | | /// </summary> |
| | | 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()); |
| | | } |
| | | |
| | | ///<summary > |
| | | ///让窗帘设备将窗帘调整到指定的倾斜角 |
| | | /// <para>comand=7 (先调用设备发现命令接口,查看设备是否支持该接口命令)</para> |
| | | ///<para>value:窗帘要调整到的倾斜角处 单位(0.1°)</para> |
| | | ///<para> 参数长度(占用的字节数):2</para> |
| | | /// </summary> |
| | | 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()); |
| | | } |
| | | |
| | | ///<summary > |
| | | ///让窗帘设备将窗帘调整到指定的百分比倾斜度 |
| | | /// <para>comand=8 (先调用设备发现命令接口,查看设备是否支持该接口命令)</para> |
| | | ///<para>value:窗帘要调整到的百分比倾斜度</para> |
| | | ///<para>范围:0-100表示0-100%</para> |
| | | /// <para>参数长度(占用的字节数):1</para> |
| | | /// </summary> |
| | | 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 设置开合帘限位参数. |
| | | /// <summary> |
| | | /// 设置开合帘上下限位 |
| | | /// </summary> |
| | | public async System.Threading.Tasks.Task<SetWritableValueResponAllData> SetCurtainInstalledLimitAsync(CurtainPrivateInstalledLimi installedLimit) |
| | | { |
| | | if (Gateway == null) |
| | | { |
| | | return null; |
| | | } |
| | | return await System.Threading.Tasks.Task.Run(async () => |
| | | { |
| | | SetWritableValueResponAllData d = null; |
| | | Action<string, string> 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<CommonDevice.ErrorResponData>(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<SetWritableValueResponData>(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; |
| | | }); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 开合帘限位 |
| | | /// </summary> |
| | | public enum CurtainPrivateInstalledLimi |
| | | { |
| | | /// <summary> |
| | | /// 窗帘全开所在的位置(上限位) |
| | | /// </summary> |
| | | UpLimit = 2, |
| | | /// <summary> |
| | | /// 窗帘全关所在的位置(下限位) |
| | | /// </summary> |
| | | DownLimit = 1, |
| | | |
| | | } |
| | | #endregion |
| | | |
| | | #region 设置恢复窗帘行程限位. |
| | | /// <summary> |
| | | /// 设置恢复窗帘行程限位 |
| | | /// </summary> |
| | | public async System.Threading.Tasks.Task<SetWritableValueResponAllData> RestoreCurtainLimitAsync() |
| | | { |
| | | if (Gateway == null) |
| | | { |
| | | return null; |
| | | } |
| | | return await System.Threading.Tasks.Task.Run(async () => |
| | | { |
| | | SetWritableValueResponAllData d = null; |
| | | Action<string, string> 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<CommonDevice.ErrorResponData>(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<SetWritableValueResponData>(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; |
| | | }); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 开合帘限位 |
| | | /// </summary> |
| | | enum CurtainPrivateAttribute |
| | | { |
| | | /// <summary> |
| | | /// 窗帘行程限位 |
| | | /// </summary> |
| | | AttributeLimit = 0xea01, |
| | | /// <summary> |
| | | /// 设置恢复窗帘行程限位 |
| | | /// </summary> |
| | | RestoreLimit = 0xea02, |
| | | |
| | | } |
| | | #endregion |
| | | |
| | | #region 删除窗帘限位 |
| | | /// <summary> |
| | | /// 删除窗帘限位 |
| | | /// </summary> |
| | | public async System.Threading.Tasks.Task<SetWritableValueResponAllData> DeleteCurtainLimitsAsync(LimiType limiType) |
| | | { |
| | | if (Gateway == null) |
| | | { |
| | | return null; |
| | | } |
| | | return await System.Threading.Tasks.Task.Run(async () => |
| | | { |
| | | SetWritableValueResponAllData d = null; |
| | | Action<string, string> 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<CommonDevice.ErrorResponData>(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<SetWritableValueResponData>(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; |
| | | }); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 删除窗帘开合帘限位 |
| | | /// </summary> |
| | | public enum LimiType |
| | | { |
| | | /// <summary> |
| | | /// 删除窗帘上限位 |
| | | /// </summary> |
| | | UpLimit = 0x08, |
| | | /// <summary> |
| | | /// 删除窗帘下限位 |
| | | /// </summary> |
| | | DownLimit = 0x02, |
| | | |
| | | }
|
| | | #endregion |
| | | } |
| | | } |