xm
2020-07-21 9a4b76398009cf76c508d61f7e48fb6f5cb7ac2d
ZigbeeApp/Shared/Phone/ZigBee/Device/Rollershade.cs
New file
@@ -0,0 +1,555 @@
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
    }
}