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
|
}
|
}
|