diff --git a/Zway/Devices/CommandClasses/Alarm.cs b/Zway/Devices/CommandClasses/Alarm.cs new file mode 100644 index 0000000..1baf3b2 --- /dev/null +++ b/Zway/Devices/CommandClasses/Alarm.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using BlubbFish.IoT.Zway.Events; +using BlubbFish.IoT.Zway.Interfaces; +using BlubbFish.IoT.Zway.lib; +using LitJson; + +namespace BlubbFish.IoT.Zway.Devices.CommandClasses { + /// + /// 135 = Indicator + /// + class Alarm : ACommandClass { + public override event UpdatedValue Update; + + public Int32 Level { get; private set; } + public Int32 AlarmType { get; private set; } + + public Alarm(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + this.InitComplex(json); + } + + private void InitComplex(JsonData json) { + if (json.Keys.Contains("data") && json["data"].Keys.Contains("V1event") && + json["data"]["V1event"].Keys.Contains("alarmType") && json["data"]["V1event"]["alarmType"].Keys.Contains("value") && + json["data"]["V1event"].Keys.Contains("level") && json["data"]["V1event"]["level"].Keys.Contains("value")) { + this.AlarmType = Int32.Parse(json["data"]["V1event"]["alarmType"]["value"].ToString()); + this.Level = Int32.Parse(json["data"]["V1event"]["level"]["value"].ToString()); + } + } + + internal override void SetUpdate(JsonData json, Match match) { + if(match.Groups[4].Value == ".data.V1event") { + if (json.Keys.Contains("alarmType") && json["alarmType"].Keys.Contains("value") && + json.Keys.Contains("level") && json["level"].Keys.Contains("value") && + this.CheckSetUpdateTime(json)) { + this.AlarmType = Int32.Parse(json["alarmType"]["value"].ToString()); + this.Level = Int32.Parse(json["level"]["value"].ToString()); + this.Update?.Invoke(this, new DeviceUpdateEvent(new Tuple(this.AlarmType, this.Level), this.LastUpdate, this)); + } + } else { + Helper.WriteError("Kenne in " + this.Name + " [" + this.Id + "] " + match.Groups[4].Value + " nicht!"); + } + } + + public override String ToString() { + return "Alarm " + this.Name + " [" + this.Id + "]: " + this.AlarmType + " " + this.Level; + } + + internal override void Poll() => this.PollNone(); + + public override Dictionary ToDictionary() { + return new Dictionary { + { "AlarmType", this.AlarmType }, + { "Level", this.Level }, + }; + } + } +} diff --git a/Zway/Devices/CommandClasses/CommandClassSubs/SceneControllerConfSub.cs b/Zway/Devices/CommandClasses/CommandClassSubs/SceneControllerConfSub.cs new file mode 100644 index 0000000..c89b7d7 --- /dev/null +++ b/Zway/Devices/CommandClasses/CommandClassSubs/SceneControllerConfSub.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using BlubbFish.IoT.Zway.Events; +using BlubbFish.IoT.Zway.Interfaces; +using BlubbFish.IoT.Zway.lib; +using LitJson; + +namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { + public class Scenecontrollerconfsub : ACommandClass { + public override event UpdatedValue Update; + + public Int32 Scene { get; private set; } + public Int32 Duration { get; private set; } + public Scenecontrollerconfsub(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + this.IsSub = true; + InitComplex(json); + } + + private void InitComplex(JsonData json) { + if (json.Keys.Contains("scene") && json["scene"].Keys.Contains("value") && + json.Keys.Contains("duration") && json["duration"].Keys.Contains("value")) { + this.Scene = Int32.Parse(json["scene"]["value"].ToString()); + this.Duration = Int32.Parse(json["duration"]["value"].ToString()); + } + } + + internal override void SetUpdate(JsonData json, Match match) { + if (json.Keys.Contains("scene") && json["scene"].Keys.Contains("value") && + json.Keys.Contains("duration") && json["duration"].Keys.Contains("value") && + this.CheckSetUpdateTime(json)) { + this.Scene = Int32.Parse(json["scene"]["value"].ToString()); + this.Duration = Int32.Parse(json["duration"]["value"].ToString()); + this.Update?.Invoke(this, new DeviceUpdateEvent(new Tuple(this.Scene, this.Duration), this.LastUpdate, this)); + } + } + + public override String ToString() { + return "SceneControllerConf " + this.Name + " [" + this.Id + "]: " + this.Scene + " " + this.Duration; + } + + internal override void Poll() => this.PollSub(); + + public override Dictionary ToDictionary() { + return new Dictionary { + { "Scene", this.Scene }, + { "Duration", this.Duration } + }; + } + } +} \ No newline at end of file diff --git a/Zway/Devices/CommandClasses/CommandClassSubs/SensorBinarySub.cs b/Zway/Devices/CommandClasses/CommandClassSubs/SensorBinarySub.cs index 99c2f9f..120e989 100644 --- a/Zway/Devices/CommandClasses/CommandClassSubs/SensorBinarySub.cs +++ b/Zway/Devices/CommandClasses/CommandClassSubs/SensorBinarySub.cs @@ -13,7 +13,6 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { public String Type { get; private set; } public Boolean Level { get; private set; } public Sensorbinarysub(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { - this.HasReset = true; this.IsSub = true; InitComplex(json); } diff --git a/Zway/Devices/CommandClasses/SceneControllerConf.cs b/Zway/Devices/CommandClasses/SceneControllerConf.cs new file mode 100644 index 0000000..ee0ab33 --- /dev/null +++ b/Zway/Devices/CommandClasses/SceneControllerConf.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Text.RegularExpressions; +using BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs; +using BlubbFish.IoT.Zway.Events; +using BlubbFish.IoT.Zway.Interfaces; +using BlubbFish.IoT.Zway.lib; +using LitJson; + +namespace BlubbFish.IoT.Zway.Devices.CommandClasses { + /// + /// 50 = Meter + /// + public class Scenecontrollerconf : ACommandClass { + public override event UpdatedValue Update; + + public Scenecontrollerconf(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + this.HasSub = true; + this.InitComplex(json); + foreach (KeyValuePair item in this.Sub) { + item.Value.Update += this.DeviceUpdate; + } + } + + private void DeviceUpdate(Object sender, DeviceUpdateEvent e) { + this.Update?.Invoke(this, e); + } + + internal override void SetUpdate(JsonData json, Match match) { + if (match.Groups[4].Value.StartsWith(".data.")) { + Int32 subid = Int32.Parse(match.Groups[5].Value); + if (this.Sub.ContainsKey(subid)) { + this.Sub[subid].SetUpdate(json, match); + } + } else { + Helper.WriteError("Kenne in " + this.Name + " [" + this.Id + "] " + match.Groups[4].Value + " nicht!"); + } + } + + private void InitComplex(JsonData json) { + if (json.Keys.Contains("data")) { + JsonData data = json["data"]; + Dictionary subs = new Dictionary(); + foreach (String item in data.Keys) { + if (Int32.TryParse(item, out Int32 subid) && + data[item].Keys.Contains("scene") && + data[item].Keys.Contains("duration")) { + subs.Add(subid, new Scenecontrollerconfsub(data[item], new Tuple(this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling)); + } + } + this.Sub = new ReadOnlyDictionary(subs); + } + } + + internal override void Poll() => this.PollPerSub(); + + public override Dictionary ToDictionary() => this.ToDictionarySub(); + } +} diff --git a/Zway/Devices/CommandClasses/Wakeup.cs b/Zway/Devices/CommandClasses/Wakeup.cs index 509505b..2ec79bb 100644 --- a/Zway/Devices/CommandClasses/Wakeup.cs +++ b/Zway/Devices/CommandClasses/Wakeup.cs @@ -34,7 +34,9 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { } public Int32 WakeupMin { get; private set; } public Int32 WakeupMax { get; private set; } + public Boolean HasMinMax { get; private set; } public Int32 WakeupDefault { get; private set; } + public Boolean HasDefault { get; private set; } public DateTime LastWakeup { get; private set; } public DateTime LastSleep { get; private set; } @@ -51,19 +53,24 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { if (data.Keys.Contains("nodeId") && data["nodeId"].Keys.Contains("value")) { this._againstNode = Int32.Parse(data["nodeId"]["value"].ToString()); } - if (data.Keys.Contains("min") && data["min"].Keys.Contains("value")) { + this.HasMinMax = false; + if (data.Keys.Contains("min") && data["min"].Keys.Contains("value") && data["min"]["value"] != null) { this.WakeupMin = Int32.Parse(data["min"]["value"].ToString()); + this.HasMinMax = true; } - if (data.Keys.Contains("max") && data["max"].Keys.Contains("value")) { + if (data.Keys.Contains("max") && data["max"].Keys.Contains("value") && data["max"]["value"] != null) { this.WakeupMax = Int32.Parse(data["max"]["value"].ToString()); + this.HasMinMax = true; } - if (data.Keys.Contains("default") && data["default"].Keys.Contains("value")) { + this.HasDefault = false; + if (data.Keys.Contains("default") && data["default"].Keys.Contains("value") && data["default"]["value"] != null) { this.WakeupDefault = Int32.Parse(data["default"]["value"].ToString()); + this.HasDefault = true; } - if (data.Keys.Contains("lastWakeup") && data["lastWakeup"].Keys.Contains("value")) { + if (data.Keys.Contains("lastWakeup") && data["lastWakeup"].Keys.Contains("value") && data["lastWakeup"]["value"] != null) { this.LastWakeup = DateTimeOffset.FromUnixTimeSeconds(Int64.Parse(data["lastWakeup"]["value"].ToString())).DateTime.ToLocalTime(); } - if (data.Keys.Contains("lastSleep") && data["lastSleep"].Keys.Contains("value")) { + if (data.Keys.Contains("lastSleep") && data["lastSleep"].Keys.Contains("value") && data["lastSleep"]["value"] != null) { this.LastSleep = DateTimeOffset.FromUnixTimeSeconds(Int64.Parse(data["lastSleep"]["value"].ToString())).DateTime.ToLocalTime(); } } @@ -90,23 +97,28 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { this._againstNode = Int32.Parse(json["nodeId"]["value"].ToString()); success = true; } - if (json.Keys.Contains("min") && json["min"].Keys.Contains("value")) { + this.HasMinMax = false; + if (json.Keys.Contains("min") && json["min"].Keys.Contains("value") && json["min"]["value"] != null) { this.WakeupMin = Int32.Parse(json["min"]["value"].ToString()); success = true; + this.HasMinMax = true; } - if (json.Keys.Contains("max") && json["max"].Keys.Contains("value")) { + if (json.Keys.Contains("max") && json["max"].Keys.Contains("value") && json["max"]["value"] != null) { this.WakeupMax = Int32.Parse(json["max"]["value"].ToString()); success = true; + this.HasMinMax = true; } - if (json.Keys.Contains("default") && json["default"].Keys.Contains("value")) { + this.HasDefault = false; + if (json.Keys.Contains("default") && json["default"].Keys.Contains("value") && json["default"]["value"] != null) { this.WakeupDefault = Int32.Parse(json["default"]["value"].ToString()); success = true; + this.HasDefault = true; } - if (json.Keys.Contains("lastWakeup") && json["lastWakeup"].Keys.Contains("value")) { + if (json.Keys.Contains("lastWakeup") && json["lastWakeup"].Keys.Contains("value") && json["lastWakeup"]["value"] != null) { this.LastWakeup = DateTimeOffset.FromUnixTimeSeconds(Int64.Parse(json["lastWakeup"]["value"].ToString())).DateTime.ToLocalTime(); success = true; } - if (json.Keys.Contains("lastSleep") && json["lastSleep"].Keys.Contains("value")) { + if (json.Keys.Contains("lastSleep") && json["lastSleep"].Keys.Contains("value") && json["lastSleep"]["value"] != null) { this.LastSleep = DateTimeOffset.FromUnixTimeSeconds(Int64.Parse(json["lastSleep"]["value"].ToString())).DateTime.ToLocalTime(); success = true; } @@ -128,7 +140,9 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { { "AgainstNode", this.AgainstNode }, { "WakeupMin", this.WakeupMin }, { "WakeupMax", this.WakeupMax }, + { "HasMinMax", this.HasMinMax }, { "WakeupDefault", this.WakeupDefault }, + { "HasDefault", this.HasDefault }, { "LastWakeup", this.LastWakeup.ToString() }, { "LastSleep", this.LastSleep.ToString() } }; diff --git a/Zway/Interfaces/ACommandClass.cs b/Zway/Interfaces/ACommandClass.cs index 5071e5f..8cf10bf 100644 --- a/Zway/Interfaces/ACommandClass.cs +++ b/Zway/Interfaces/ACommandClass.cs @@ -16,11 +16,16 @@ namespace BlubbFish.IoT.Zway.Interfaces { Basic = 32, ControllerReplication = 33, ApplicationStatus = 34, - SensorBinary = 48, + SwitchAll = 39, + SceneActivation = 43, SwitchColor = 51, MeterPulse = 53, + CRC16 = 86, + AssociationGroupInformation = 89, + DeviceResetLocally = 90, + ZWavePlusInfo = 94, MultiChannel = 96, - Alarm = 113, + DoorLock = 98, ManufacturerSpecific = 114, PowerLevel = 115, Protection = 117, @@ -28,19 +33,25 @@ namespace BlubbFish.IoT.Zway.Interfaces { FirmwareUpdate = 122, Association = 133, Version = 134, + Proprietary = 136, MultiChannelAssociation = 142, - MultiCmd = 143 + MultiCmd = 143, + Security = 152, + AlarmSensor = 156 // } public enum Classes : Int32 { SwitchBinary = 37, SwitchMultilevel = 38, + SceneControllerConf = 45, + SensorBinary = 48, SensorMultilevel = 49, Meter = 50, ThermostatMode = 64, ThermostatSetPoint = 67, CentralScene = 91, Configuration = 112, + Alarm = 113, Battery = 128, Wakeup = 132, Indicator = 135