diff --git a/Zway/Devices/CommandClass.cs b/Zway/Devices/CommandClass.cs index 612ed9c..b2449fb 100644 --- a/Zway/Devices/CommandClass.cs +++ b/Zway/Devices/CommandClass.cs @@ -1,15 +1,18 @@ 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 { - public abstract class CommandClass { + public abstract class CommandClass : ICommandClass { protected HttpConnection http; + + public abstract event UpdatedValue Update; private enum Ignored { Basic = 32, - Configuration = 112, ManufacturerSpecific = 114, PowerLevel = 115, Protection = 117, @@ -24,17 +27,22 @@ namespace BlubbFish.IoT.Zway.Devices { public Int32 DeviceId { get; } public Int32 Instance { get; } public Int32 Commandclass { get; } - public String Name { get; } - + public String Id { get; } public DateTime LastUpdate { get; private set; } + public String Name { get; } + public Boolean Polling { get; set; } - protected CommandClass(JsonData json, HttpConnection http, Tuple id) { + protected CommandClass(JsonData json, HttpConnection http, Tuple id, Boolean polling) { this.DeviceId = id.Item1; this.Instance = id.Item2; this.Commandclass = id.Item3; - this.Name = this.DeviceId + "-" + this.Instance + "-" + this.Commandclass; this.http = http; this.LastUpdate = DateTime.Now; + this.Polling = polling; + this.Id = this.DeviceId + "-" + this.Instance + "-" + this.Commandclass; + if (ZwayController.namelist.ContainsKey(this.Id)) { + this.Name = ZwayController.namelist[this.Id]; + } } protected Boolean CheckSetUpdateTime(JsonData json) { @@ -51,7 +59,7 @@ namespace BlubbFish.IoT.Zway.Devices { } } - internal static CommandClass CreateInstance(JsonData json, Tuple id, HttpConnection http) { + internal static CommandClass CreateInstance(JsonData json, Tuple id, HttpConnection http, Boolean polling) { if (json.Keys.Contains("name") && json.Keys.Contains("data") && json["data"].Keys.Contains("supported") && @@ -60,12 +68,12 @@ namespace BlubbFish.IoT.Zway.Devices { !Enum.IsDefined(typeof(Ignored), id.Item3)) { String name = json["name"].ToString(); String objectName = "BlubbFish.IoT.Zway.Devices.CommandClasses." + name[0].ToString().ToUpper() + name.Substring(1).ToLower(); - return GetInstanceConcrete(objectName, json, http, id); + return GetInstanceConcrete(objectName, json, http, id, polling); } return null; } - private static CommandClass GetInstanceConcrete(String objectName, JsonData json, HttpConnection http, Tuple id) { + private static CommandClass GetInstanceConcrete(String objectName, JsonData json, HttpConnection http, Tuple id, Boolean polling) { Type t = null; try { t = Type.GetType(objectName, true); @@ -73,17 +81,15 @@ namespace BlubbFish.IoT.Zway.Devices { Console.Error.WriteLine("Konnte Type " + objectName + " nicht laden!"); return null; } - return (CommandClass)t.GetConstructor(new Type[] { typeof(JsonData), typeof(HttpConnection), typeof(Tuple) }).Invoke(new Object[] { json, http, id }); + return (CommandClass)t.GetConstructor(new Type[] { typeof(JsonData), typeof(HttpConnection), typeof(Tuple), typeof(Boolean) }).Invoke(new Object[] { json, http, id, polling }); } - protected abstract void InitComplex(JsonData json); internal abstract void SetUpdate(JsonData json, Match match); - public delegate void UpdatedValue(Object sender, DeviceUpdateEvent e); - public abstract event UpdatedValue Update; - internal virtual void Poll() { - this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + this.Commandclass + "].Get()"); + if(this.Polling) { + this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + this.Commandclass + "].Get()"); + } } protected void SetInt(Int32 value) { diff --git a/Zway/Devices/CommandClassSub.cs b/Zway/Devices/CommandClassSub.cs index 891fbd9..708a4fd 100644 --- a/Zway/Devices/CommandClassSub.cs +++ b/Zway/Devices/CommandClassSub.cs @@ -1,31 +1,35 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Text.RegularExpressions; -using System.Threading.Tasks; -using BlubbFish.IoT.Zway.Events; +using BlubbFish.IoT.Zway.Interfaces; using BlubbFish.IoT.Zway.lib; using LitJson; namespace BlubbFish.IoT.Zway.Devices { - public abstract class CommandClassSub { + public abstract class CommandClassSub : ICommandClass { protected HttpConnection http; + public abstract event UpdatedValue Update; + public String Id { get; } public Int32 DeviceId { get; } public Int32 Instance { get; } public Int32 Commandclass { get; } public Int32 SensorId { get; } public String Name { get; } public DateTime LastUpdate { get; private set; } + public Boolean Polling { get; set; } - protected CommandClassSub(JsonData json, Tuple id, HttpConnection http) { + protected CommandClassSub(JsonData json, Tuple id, HttpConnection http, Boolean polling) { this.DeviceId = id.Item1; this.Instance = id.Item2; this.Commandclass = id.Item3; this.SensorId = id.Item4; this.http = http; - this.Name = this.DeviceId + "-" + this.Instance + "-" + this.Commandclass + "-" + this.SensorId; + this.LastUpdate = DateTime.Now; + this.Polling = polling; + this.Id = this.DeviceId + "-" + this.Instance + "-" + this.Commandclass + "-" + this.SensorId; + if (ZwayController.namelist.ContainsKey(this.Id)) { + this.Name = ZwayController.namelist[this.Id]; + } } protected Boolean CheckSetUpdateTime(JsonData json) { @@ -41,11 +45,8 @@ namespace BlubbFish.IoT.Zway.Devices { return true; } } - - protected abstract void InitComplex(JsonData json); internal abstract void SetUpdate(JsonData json, Match match); - public delegate void UpdatedValue(Object sender, DeviceUpdateEvent e); - public abstract event UpdatedValue Update; + internal abstract void Poll(); } } diff --git a/Zway/Devices/CommandClasses/Battery.cs b/Zway/Devices/CommandClasses/Battery.cs index 93bd69f..9b18f83 100644 --- a/Zway/Devices/CommandClasses/Battery.cs +++ b/Zway/Devices/CommandClasses/Battery.cs @@ -1,17 +1,21 @@ using System; 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 { + /// + /// 128 = Battery + /// public class Battery : CommandClass { public Single Level { get; private set; } public override event UpdatedValue Update; - public Battery(JsonData json, HttpConnection http, Tuple id) : base(json, http, id) { + public Battery(JsonData json, HttpConnection http, Tuple id, Boolean polling) : base(json, http, id, polling) { this.InitComplex(json); } @@ -30,21 +34,21 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { } else if (match.Groups[4].Value.StartsWith(".data.history.")) { } else if (match.Groups[4].Value == ".data.lastChange") { } else { - throw new NotImplementedException(); + Helper.WriteError("Kenne in "+this.Name+" ["+this.Id+"] "+ match.Groups[4].Value+" nicht!"); } if (success && this.CheckSetUpdateTime(json)) { this.Update?.Invoke(this, new DeviceUpdateEvent(this.Level, this.LastUpdate)); } } - protected override void InitComplex(JsonData json) { - if(json.Keys.Contains("data") && json["data"].Keys.Contains("last") && json["data"]["last"].Keys.Contains("value")) { + private void InitComplex(JsonData json) { + if (json.Keys.Contains("data") && json["data"].Keys.Contains("last") && json["data"]["last"].Keys.Contains("value")) { this.Level = Single.Parse(json["data"]["last"]["value"].ToString()); } } public override String ToString() { - return "Battery " + this.Name + ": " + this.Level; + return "Battery " + this.Name + " [" + this.Id + "]: " + this.Level; } } } diff --git a/Zway/Devices/CommandClasses/CentralScene.cs b/Zway/Devices/CommandClasses/CentralScene.cs index aa68df4..74eea93 100644 --- a/Zway/Devices/CommandClasses/CentralScene.cs +++ b/Zway/Devices/CommandClasses/CentralScene.cs @@ -3,10 +3,14 @@ using System.Collections.Generic; using System.Collections.ObjectModel; 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 { + /// + /// 91 = CentralScene + /// public class Centralscene : CommandClass { public override event UpdatedValue Update; @@ -14,7 +18,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { public Int32 Scene { get; private set; } public Int32 Key { get; private set; } - public Centralscene(JsonData json, HttpConnection http, Tuple id) : base(json, http, id) { + public Centralscene(JsonData json, HttpConnection http, Tuple id, Boolean polling) : base(json, http, id, polling) { this.ValidScenesModes = new ReadOnlyDictionary>(new Dictionary>()); this.InitComplex(json); } @@ -30,11 +34,11 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { this.Update?.Invoke(this, new DeviceUpdateEvent(new Tuple(this.Scene, this.Key), this.LastUpdate)); } } else { - throw new NotImplementedException(); + Helper.WriteError("Kenne in " + this.Name + " [" + this.Id + "] " + match.Groups[4].Value + " nicht!"); } } - protected override void InitComplex(JsonData json) { + private void InitComplex(JsonData json) { if (json.Keys.Contains("data")) { JsonData data = json["data"]; if(data.Keys.Contains("sceneSupportedKeyAttributesMask")) { @@ -67,7 +71,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { } public override String ToString() { - return "CentralScene " + this.Name + ": "+this.Scene+"-"+this.Key; + return "CentralScene " + this.Name + " [" + this.Id + "]: " + this.Scene+"-"+this.Key; } internal override void Poll() { diff --git a/Zway/Devices/CommandClasses/CommandClassSubs/Configurationsub.cs b/Zway/Devices/CommandClasses/CommandClassSubs/Configurationsub.cs new file mode 100644 index 0000000..b91b3d8 --- /dev/null +++ b/Zway/Devices/CommandClasses/CommandClassSubs/Configurationsub.cs @@ -0,0 +1,65 @@ +using System; +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 { + class Configurationsub : CommandClassSub { + private Int64 _level; + + public override event UpdatedValue Update; + + public Int64 Level { + get { + return this._level; + } + set { + if (this.Size == 1 && Int16.TryParse(value.ToString(), out Int16 value16)) { + this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + this.Commandclass + "].Set(" + this.SensorId + "," + value16 + ",1)"); + } else if(this.Size == 2 && Int32.TryParse(value.ToString(), out Int32 value32)) { + this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + this.Commandclass + "].Set(" + this.SensorId + "," + value32 + ",2)"); + } else if(this.Size == 4) { + this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + this.Commandclass + "].Set(" + this.SensorId + "," + value + ",4)"); + } + } + } + public Int32 Size { get; private set; } + + public Configurationsub(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + InitComplex(json); + } + + private void InitComplex(JsonData json) { + if (json.Keys.Contains("val") && + json["val"].Keys.Contains("value") && + json["val"]["value"] != null && + json.Keys.Contains("size") && + json["size"].Keys.Contains("value")) { + this._level = Int64.Parse(json["val"]["value"].ToString()); + this.Size = Int32.Parse(json["size"]["value"].ToString()); + } + } + + internal override void Poll() { + if(this.Polling) { + this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + this.Commandclass + "].Get("+this.SensorId+")"); + } + } + + internal override void SetUpdate(JsonData json, Match match) { + if (json.Keys.Contains("val") && json["val"].Keys.Contains("value") && json["val"]["value"] != null && + json.Keys.Contains("size") && json["size"].Keys.Contains("value") && + this.CheckSetUpdateTime(json)) { + this._level = Int64.Parse(json["val"]["value"].ToString()); + this.Size = Int32.Parse(json["size"]["value"].ToString()); + this.Update?.Invoke(this, new DeviceUpdateEvent(new Tuple(this.Level, this.Size), this.LastUpdate)); + } + } + + public override String ToString() { + return "Configuration " + this.Name + " [" + this.Id + "]: " + this.Level; + } + } +} \ No newline at end of file diff --git a/Zway/Devices/CommandClasses/CommandClassSubs/MeterSub.cs b/Zway/Devices/CommandClasses/CommandClassSubs/MeterSub.cs index 8c87280..6f7bc9f 100644 --- a/Zway/Devices/CommandClasses/CommandClassSubs/MeterSub.cs +++ b/Zway/Devices/CommandClasses/CommandClassSubs/MeterSub.cs @@ -1,6 +1,7 @@ using System; using System.Text.RegularExpressions; using BlubbFish.IoT.Zway.Events; +using BlubbFish.IoT.Zway.Interfaces; using BlubbFish.IoT.Zway.lib; using LitJson; @@ -11,7 +12,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { public String Type { get; private set; } public Single Level { get; private set; } public String Scale { get; private set; } - public Metersub(JsonData json, Tuple id, HttpConnection http) : base(json, id, http) { + public Metersub(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { InitComplex(json); } @@ -19,7 +20,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + this.Commandclass + "].Reset()"); } - protected override void InitComplex(JsonData json) { + private void InitComplex(JsonData json) { if (json.Keys.Contains("sensorTypeString") && json["sensorTypeString"].Keys.Contains("value") && json.Keys.Contains("val") && @@ -45,7 +46,9 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { } public override String ToString() { - return "Meter " + this.Name + ": " + this.Type + " " + this.Level + "" + this.Scale; + return "Meter " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.Level + "" + this.Scale; } + + internal override void Poll() { } } } \ No newline at end of file diff --git a/Zway/Devices/CommandClasses/CommandClassSubs/SensorMultilevelSub.cs b/Zway/Devices/CommandClasses/CommandClassSubs/SensorMultilevelSub.cs index d19150a..e7b9a31 100644 --- a/Zway/Devices/CommandClasses/CommandClassSubs/SensorMultilevelSub.cs +++ b/Zway/Devices/CommandClasses/CommandClassSubs/SensorMultilevelSub.cs @@ -1,6 +1,7 @@ using System; using System.Text.RegularExpressions; using BlubbFish.IoT.Zway.Events; +using BlubbFish.IoT.Zway.Interfaces; using BlubbFish.IoT.Zway.lib; using LitJson; @@ -11,13 +12,11 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { public Single Level { get; private set; } public String Scale { get; private set; } - public Sensormultilevelsub(JsonData json, Tuple id, HttpConnection http) : base(json, id, http) { + public Sensormultilevelsub(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { InitComplex(json); } - - - protected override void InitComplex(JsonData json) { + private void InitComplex(JsonData json) { if (json.Keys.Contains("sensorTypeString") && json["sensorTypeString"].Keys.Contains("value") && json.Keys.Contains("val") && @@ -43,7 +42,9 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { } public override String ToString() { - return "SensorMultilevel " + this.Name + ": " + this.Type + " " + this.Level + "" + this.Scale; + return "SensorMultilevel " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.Level + "" + this.Scale; } + + internal override void Poll() { } } } \ No newline at end of file diff --git a/Zway/Devices/CommandClasses/CommandClassSubs/ThermostatSetPointSub.cs b/Zway/Devices/CommandClasses/CommandClassSubs/ThermostatSetPointSub.cs index 6a00477..7b1dc41 100644 --- a/Zway/Devices/CommandClasses/CommandClassSubs/ThermostatSetPointSub.cs +++ b/Zway/Devices/CommandClasses/CommandClassSubs/ThermostatSetPointSub.cs @@ -1,6 +1,7 @@ using System; using System.Text.RegularExpressions; using BlubbFish.IoT.Zway.Events; +using BlubbFish.IoT.Zway.Interfaces; using BlubbFish.IoT.Zway.lib; using LitJson; @@ -27,11 +28,11 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { public Boolean HasMinMax { get; private set; } public String Type { get; private set; } - public Thermostatsetpointsub(JsonData json, Tuple id, HttpConnection http) : base(json, id, http) { + public Thermostatsetpointsub(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { InitComplex(json); } - protected override void InitComplex(JsonData json) { + private void InitComplex(JsonData json) { if (json.Keys.Contains("modeName") && json["modeName"].Keys.Contains("value") && json.Keys.Contains("val") && json["val"].Keys.Contains("value") && json.Keys.Contains("deviceScaleString") && json["deviceScaleString"].Keys.Contains("value")) { @@ -74,7 +75,13 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { } public override String ToString() { - return "ThermostatSetPoint " + this.Name + ": " + this.Type + " " + this.Level + "" + this.Scale + " [" + this.TempMin + "," + this.TempMax + "," + this.HasMinMax + "]"; + return "ThermostatSetPoint " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.Level + "" + this.Scale + " [" + this.TempMin + "," + this.TempMax + "," + this.HasMinMax + "]"; + } + + internal override void Poll() { + if (this.Polling) { + this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + this.Commandclass + "].Get(" + this.SensorId + ")"); + } } } } \ No newline at end of file diff --git a/Zway/Devices/CommandClasses/Configuration.cs b/Zway/Devices/CommandClasses/Configuration.cs new file mode 100644 index 0000000..d4bdfcf --- /dev/null +++ b/Zway/Devices/CommandClasses/Configuration.cs @@ -0,0 +1,64 @@ +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 { + /// + /// 112 = Configuration + /// + class Configuration : CommandClass { + public override event UpdatedValue Update; + + public ReadOnlyDictionary Sub { get; private set; } + public Configuration(JsonData json, HttpConnection http, Tuple id, Boolean polling) : base(json, http, id, polling) { + this.InitComplex(json); + foreach (KeyValuePair item in this.Sub) { + item.Value.Update += this.DeviceUpdate; + } + } + + private void DeviceUpdate(Object sender, DeviceUpdateEvent e) { + this.Update?.Invoke(sender, e); + } + + 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("size") && + data[item].Keys.Contains("val") && + data[item]["val"].Keys.Contains("value") && + data[item]["val"]["value"] != null) { + subs.Add(subid, new Configurationsub(data[item], new Tuple(this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling)); + } + } + this.Sub = new ReadOnlyDictionary(subs); + } + } + + 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!"); + } + } + + internal override void Poll() { + foreach (KeyValuePair item in this.Sub) { + item.Value.Poll(); + } + } + } +} diff --git a/Zway/Devices/CommandClasses/Indicator.cs b/Zway/Devices/CommandClasses/Indicator.cs index e69d497..b25ef32 100644 --- a/Zway/Devices/CommandClasses/Indicator.cs +++ b/Zway/Devices/CommandClasses/Indicator.cs @@ -1,10 +1,14 @@ using System; 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 Indicator : CommandClass { private Boolean _level; @@ -18,12 +22,12 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { } } - public Indicator(JsonData json, HttpConnection http, Tuple id) : base(json, http, id) { + public Indicator(JsonData json, HttpConnection http, Tuple id, Boolean polling) : base(json, http, id, polling) { this.InitComplex(json); } - protected override void InitComplex(JsonData json) { - if(json.Keys.Contains("data") && json["data"].Keys.Contains("stat") && json["data"]["stat"].Keys.Contains("value")) { + private void InitComplex(JsonData json) { + if (json.Keys.Contains("data") && json["data"].Keys.Contains("stat") && json["data"]["stat"].Keys.Contains("value")) { this._level = Int32.Parse(json["data"]["stat"]["value"].ToString()) == 255; } } @@ -35,12 +39,12 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { this.Update?.Invoke(this, new DeviceUpdateEvent(this.Level, this.LastUpdate)); } } else { - throw new NotImplementedException(); + Helper.WriteError("Kenne in " + this.Name + " [" + this.Id + "] " + match.Groups[4].Value + " nicht!"); } } public override String ToString() { - return "Indicator " + this.Name + ": " + this.Level; + return "Indicator " + this.Name + " [" + this.Id + "]: " + this.Level; } } } diff --git a/Zway/Devices/CommandClasses/Meter.cs b/Zway/Devices/CommandClasses/Meter.cs index 588d03c..f27f987 100644 --- a/Zway/Devices/CommandClasses/Meter.cs +++ b/Zway/Devices/CommandClasses/Meter.cs @@ -4,17 +4,21 @@ 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 Meter : CommandClass { public override event UpdatedValue Update; public ReadOnlyDictionary Sub { get; private set; } - public Meter(JsonData json, HttpConnection http, Tuple id) : base(json, http, id) { + public Meter(JsonData json, HttpConnection http, Tuple id, Boolean polling) : base(json, http, id, polling) { this.InitComplex(json); foreach (KeyValuePair item in this.Sub) { item.Value.Update += this.DeviceUpdate; @@ -32,11 +36,11 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { this.Sub[subid].SetUpdate(json, match); } } else { - throw new NotImplementedException(); + Helper.WriteError("Kenne in " + this.Name + " [" + this.Id + "] " + match.Groups[4].Value + " nicht!"); } } - protected override void InitComplex(JsonData json) { + private void InitComplex(JsonData json) { if (json.Keys.Contains("data")) { JsonData data = json["data"]; Dictionary subs = new Dictionary(); @@ -45,11 +49,23 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { data[item].Keys.Contains("sensorTypeString") && data[item].Keys.Contains("val") && data[item].Keys.Contains("scaleString")) { - subs.Add(subid, new Metersub(data[item], new Tuple(this.DeviceId, this.Instance, this.Commandclass, subid), this.http)); + subs.Add(subid, new Metersub(data[item], new Tuple(this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling)); } } this.Sub = new ReadOnlyDictionary(subs); } } + + internal override void Poll() { + Boolean poll = false; + foreach (KeyValuePair item in this.Sub) { + if (item.Value.Polling) { + poll = true; + } + } + if (poll) { + this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + this.Commandclass + "].Get()"); + } + } } } diff --git a/Zway/Devices/CommandClasses/SensorMultilevel.cs b/Zway/Devices/CommandClasses/SensorMultilevel.cs index 9592ba3..0022d59 100644 --- a/Zway/Devices/CommandClasses/SensorMultilevel.cs +++ b/Zway/Devices/CommandClasses/SensorMultilevel.cs @@ -4,17 +4,21 @@ 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 { + /// + /// 49 = SensorMultilevel + /// public class Sensormultilevel : CommandClass { public override event UpdatedValue Update; public ReadOnlyDictionary Sub { get; private set; } - public Sensormultilevel(JsonData json, HttpConnection http, Tuple id) : base(json, http, id) { + public Sensormultilevel(JsonData json, HttpConnection http, Tuple id, Boolean polling) : base(json, http, id, polling) { this.InitComplex(json); foreach (KeyValuePair item in this.Sub) { item.Value.Update += this.DeviceUpdate; @@ -32,11 +36,11 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { this.Sub[subid].SetUpdate(json, match); } } else { - throw new NotImplementedException(); + Helper.WriteError("Kenne in " + this.Name + " [" + this.Id + "] " + match.Groups[4].Value + " nicht!"); } } - protected override void InitComplex(JsonData json) { + private void InitComplex(JsonData json) { if (json.Keys.Contains("data")) { JsonData data = json["data"]; Dictionary subs = new Dictionary(); @@ -45,11 +49,23 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { data[item].Keys.Contains("sensorTypeString") && data[item].Keys.Contains("val") && data[item].Keys.Contains("scaleString")) { - subs.Add(subid, new Sensormultilevelsub(data[item], new Tuple(this.DeviceId, this.Instance, this.Commandclass, subid), this.http)); + subs.Add(subid, new Sensormultilevelsub(data[item], new Tuple(this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling)); } } this.Sub = new ReadOnlyDictionary(subs); } } + + internal override void Poll() { + Boolean poll = false; + foreach (KeyValuePair item in this.Sub) { + if (item.Value.Polling) { + poll = true; + } + } + if (poll) { + this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + this.Commandclass + "].Get()"); + } + } } } diff --git a/Zway/Devices/CommandClasses/SwitchBinary.cs b/Zway/Devices/CommandClasses/SwitchBinary.cs index 10a00fe..b3d195c 100644 --- a/Zway/Devices/CommandClasses/SwitchBinary.cs +++ b/Zway/Devices/CommandClasses/SwitchBinary.cs @@ -1,10 +1,14 @@ using System; 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 { + /// + /// 37 = SwitchBinary + /// public class Switchbinary : CommandClass { private Boolean _level; @@ -19,7 +23,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { } } - public Switchbinary(JsonData json, HttpConnection http, Tuple id) : base(json, http, id) { + public Switchbinary(JsonData json, HttpConnection http, Tuple id, Boolean polling) : base(json, http, id, polling) { this.InitComplex(json); } @@ -30,18 +34,18 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { this.Update?.Invoke(this, new DeviceUpdateEvent(this.Level, this.LastUpdate)); } } else { - throw new NotImplementedException(); + Helper.WriteError("Kenne in " + this.Name + " [" + this.Id + "] " + match.Groups[4].Value + " nicht!"); } } - protected override void InitComplex(JsonData json) { + private void InitComplex(JsonData json) { if (json.Keys.Contains("data") && json["data"].Keys.Contains("level") && json["data"]["level"].Keys.Contains("value") && json["data"]["level"]["value"].IsBoolean) { this._level = (Boolean)json["data"]["level"]["value"]; } } public override String ToString() { - return "SwitchBinary " + this.Name + ": " + this.Level; + return "SwitchBinary " + this.Name + " [" + this.Id + "]: " + this.Level; } } } diff --git a/Zway/Devices/CommandClasses/SwitchMultilevel.cs b/Zway/Devices/CommandClasses/SwitchMultilevel.cs index f941077..3f3e571 100644 --- a/Zway/Devices/CommandClasses/SwitchMultilevel.cs +++ b/Zway/Devices/CommandClasses/SwitchMultilevel.cs @@ -1,10 +1,14 @@ using System; 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 { + /// + /// 38 = SwitchMultilevel + /// public class Switchmultilevel : CommandClass { private Int32 _level; @@ -21,7 +25,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { } } - public Switchmultilevel(JsonData json, HttpConnection http, Tuple id) : base(json, http, id) { + public Switchmultilevel(JsonData json, HttpConnection http, Tuple id, Boolean polling) : base(json, http, id, polling) { this.InitComplex(json); } @@ -33,18 +37,18 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { } } else if (match.Groups[4].Value == ".data.prevLevel") { } else { - throw new NotImplementedException(); + Helper.WriteError("Kenne in " + this.Name + " [" + this.Id + "] " + match.Groups[4].Value + " nicht!"); } } - protected override void InitComplex(JsonData json) { - if(json.Keys.Contains("data") && json["data"].Keys.Contains("level") && json["data"]["level"].Keys.Contains("value")) { + private void InitComplex(JsonData json) { + if (json.Keys.Contains("data") && json["data"].Keys.Contains("level") && json["data"]["level"].Keys.Contains("value")) { this._level = Int32.Parse(json["data"]["level"]["value"].ToString()); } } public override String ToString() { - return "SwitchMultilevel " + this.Name + ": " + this.Level; + return "SwitchMultilevel " + this.Name + " [" + this.Id + "]: " + this.Level; } } } diff --git a/Zway/Devices/CommandClasses/ThermostatMode.cs b/Zway/Devices/CommandClasses/ThermostatMode.cs index feb0745..423a1bd 100644 --- a/Zway/Devices/CommandClasses/ThermostatMode.cs +++ b/Zway/Devices/CommandClasses/ThermostatMode.cs @@ -3,10 +3,14 @@ using System.Collections.Generic; using System.Collections.ObjectModel; 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 { + /// + /// 64 = ThermostatMode + /// public class Thermostatmode : CommandClass { private Int32 _level; @@ -22,7 +26,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { } } - public Thermostatmode(JsonData json, HttpConnection http, Tuple id) : base(json, http, id) { + public Thermostatmode(JsonData json, HttpConnection http, Tuple id, Boolean polling) : base(json, http, id, polling) { this.ValidModes = new ReadOnlyDictionary(new Dictionary()); this.InitComplex(json); } @@ -34,11 +38,11 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { this.Update?.Invoke(this, new DeviceUpdateEvent(this.Level, this.LastUpdate)); } } else { - throw new NotImplementedException(); + Helper.WriteError("Kenne in " + this.Name + " [" + this.Id + "] " + match.Groups[4].Value + " nicht!"); } } - protected override void InitComplex(JsonData json) { + private void InitComplex(JsonData json) { if (json.Keys.Contains("data")) { JsonData data = json["data"]; Dictionary modes = new Dictionary(); @@ -58,7 +62,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { } public override String ToString() { - return "ThermostatMode " + this.Name + ": " + this.ValidModes[this.Level]; + return "ThermostatMode " + this.Name + " [" + this.Id + "]: " + this.ValidModes[this.Level]; } } } diff --git a/Zway/Devices/CommandClasses/ThermostatSetPoint.cs b/Zway/Devices/CommandClasses/ThermostatSetPoint.cs index b532a42..d1080c4 100644 --- a/Zway/Devices/CommandClasses/ThermostatSetPoint.cs +++ b/Zway/Devices/CommandClasses/ThermostatSetPoint.cs @@ -4,16 +4,20 @@ 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 { + /// + /// 67 = ThermostatSetPoint + /// public class Thermostatsetpoint : CommandClass { public override event UpdatedValue Update; public ReadOnlyDictionary Sub { get; private set; } - public Thermostatsetpoint(JsonData json, HttpConnection http, Tuple id) : base(json, http, id) { + public Thermostatsetpoint(JsonData json, HttpConnection http, Tuple id, Boolean polling) : base(json, http, id, polling) { this.InitComplex(json); foreach (KeyValuePair item in this.Sub) { item.Value.Update += this.DeviceUpdate; @@ -31,11 +35,11 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { this.Sub[subid].SetUpdate(json, match); } } else { - throw new NotImplementedException(); + Helper.WriteError("Kenne in " + this.Name + " [" + this.Id + "] " + match.Groups[4].Value + " nicht!"); } } - protected override void InitComplex(JsonData json) { + private void InitComplex(JsonData json) { if (json.Keys.Contains("data")) { JsonData data = json["data"]; Dictionary subs = new Dictionary(); @@ -44,7 +48,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { data[item].Keys.Contains("modeName") && data[item].Keys.Contains("val") && data[item].Keys.Contains("deviceScaleString")) { - subs.Add(subid, new Thermostatsetpointsub(data[item], new Tuple(this.DeviceId, this.Instance, this.Commandclass, subid), this.http)); + subs.Add(subid, new Thermostatsetpointsub(data[item], new Tuple(this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling)); } } this.Sub = new ReadOnlyDictionary(subs); @@ -53,7 +57,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { internal override void Poll() { foreach (KeyValuePair item in this.Sub) { - this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + this.Commandclass + "].Get(" + item.Key + ")"); + item.Value.Poll(); } } } diff --git a/Zway/Devices/CommandClasses/Wakeup.cs b/Zway/Devices/CommandClasses/Wakeup.cs index 1399dc1..9c2e77f 100644 --- a/Zway/Devices/CommandClasses/Wakeup.cs +++ b/Zway/Devices/CommandClasses/Wakeup.cs @@ -1,14 +1,14 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Text.RegularExpressions; -using System.Threading.Tasks; using BlubbFish.IoT.Zway.Events; +using BlubbFish.IoT.Zway.Interfaces; using BlubbFish.IoT.Zway.lib; using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses { + /// + /// 132 = Wakeup + /// class Wakeup : CommandClass { private Int32 _interval; private Int32 _againstNode; @@ -37,12 +37,12 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { public DateTime LastWakeup { get; private set; } public DateTime LastSleep { get; private set; } - public Wakeup(JsonData json, HttpConnection http, Tuple id) : base(json, http, id) { + public Wakeup(JsonData json, HttpConnection http, Tuple id, Boolean polling) : base(json, http, id, polling) { this.InitComplex(json); } - protected override void InitComplex(JsonData json) { - if(json.Keys.Contains("data")) { + private void InitComplex(JsonData json) { + if (json.Keys.Contains("data")) { JsonData data = json["data"]; if(data.Keys.Contains("interval") && data["interval"].Keys.Contains("value")) { this._interval = Int32.Parse(data["interval"]["value"].ToString()); @@ -110,7 +110,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { success = true; } } else { - throw new NotImplementedException(); + Helper.WriteError("Kenne in " + this.Name + " [" + this.Id + "] " + match.Groups[4].Value + " nicht!"); } if (success && this.CheckSetUpdateTime(json)) { this.Update?.Invoke(this, new DeviceUpdateEvent(0, this.LastUpdate)); @@ -118,7 +118,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { } public override String ToString() { - return "Wakeup " + this.Name + ": " + this.LastWakeup + "-" + this.LastSleep + " " + this.Interval + " [" + this.WakeupMin + "," + this.WakeupMax + "," + this.WakeupDefault + "," + this.AgainstNode + "]"; + return "Wakeup " + this.Name + " [" + this.Id + "]: " + this.LastWakeup + "-" + this.LastSleep + " " + this.Interval + " [" + this.WakeupMin + "," + this.WakeupMax + "," + this.WakeupDefault + "," + this.AgainstNode + "]"; } } } diff --git a/Zway/Devices/Device.cs b/Zway/Devices/Device.cs index d077ca5..3db3d91 100644 --- a/Zway/Devices/Device.cs +++ b/Zway/Devices/Device.cs @@ -1,30 +1,27 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.ObjectModel; using System.Text.RegularExpressions; -using System.Threading.Tasks; using BlubbFish.IoT.Zway.Events; using BlubbFish.IoT.Zway.lib; using LitJson; namespace BlubbFish.IoT.Zway.Devices { - class Device { - private Dictionary _instances = new Dictionary(); + public class Device { + private Boolean polling; public delegate void UpdatedDevice(Object sender, DeviceUpdateEvent e); public event UpdatedDevice Update; public String Name { get; } public Int32 Id { get; } - public Dictionary Instances { get { return this._instances; } } + public ReadOnlyDictionary Instances { get; private set; } public DateTime LastUpdate { get; private set; } - private Device(JsonData json, Tuple id, HttpConnection http) { + private Device(JsonData json, Tuple id, HttpConnection http, Boolean polling) { this.Id = id.Item1; - foreach (String instanceid in json["instances"].Keys) { - this.CreateInstances(Int32.Parse(instanceid), json["instances"][instanceid], http); - } + this.polling = polling; + this.CreateInstances(json["instances"], http); if (json["data"].Keys.Contains("givenName") && json["data"]["givenName"].Keys.Contains("value")) { this.Name = json["data"]["givenName"]["value"].ToString(); } else { @@ -53,30 +50,34 @@ namespace BlubbFish.IoT.Zway.Devices { this.Update?.Invoke(sender, e); } - private void CreateInstances(Int32 instanceid, JsonData json, HttpConnection http) { - Instance i = Instance.CreateInstance(json, new Tuple(this.Id, instanceid), http); - if (i != null) { - this._instances.Add(instanceid, i); + private void CreateInstances(JsonData json, HttpConnection http) { + Dictionary instances = new Dictionary(); + foreach (String instanceid in json.Keys) { + Instance i = Instance.CreateInstance(json[instanceid], new Tuple(this.Id, Int32.Parse(instanceid)), http, this.polling); + if (i != null) { + instances.Add(Int32.Parse(instanceid), i); + } } + this.Instances = new ReadOnlyDictionary(instances); } - internal static Device CreateDevice(JsonData json, Tuple id, HttpConnection http) { + internal static Device CreateDevice(JsonData json, Tuple id, HttpConnection http, Boolean polling) { if(json.Keys.Contains("instances") && json["instances"].Count > 0 && json.Keys.Contains("data") && id.Item1 != 1) { - return new Device(json, id, http); + return new Device(json, id, http, polling); } return null; } public override String ToString() { - return this.Name+"_"+this.Id+" ["+this._instances.Count+"]"; + return this.Name+"_"+this.Id+" ["+this.Instances.Count+"]"; } internal void SetUpdate(JsonData json, Match match) { if (match.Groups[2].Value == "data.lastReceived") { if (this.CheckSetUpdateTime(json)) { - this.Update?.Invoke(this, new DeviceUpdateEvent(this.LastUpdate, this.LastUpdate)); + //this.Update?.Invoke(this, new DeviceUpdateEvent(this.LastUpdate, this.LastUpdate)); } } } diff --git a/Zway/Devices/Instance.cs b/Zway/Devices/Instance.cs index 892e03d..9e70fee 100644 --- a/Zway/Devices/Instance.cs +++ b/Zway/Devices/Instance.cs @@ -1,26 +1,28 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using BlubbFish.IoT.Zway.Devices.CommandClasses; using BlubbFish.IoT.Zway.Events; using BlubbFish.IoT.Zway.lib; using LitJson; namespace BlubbFish.IoT.Zway.Devices { - class Instance { - private Dictionary _commands = new Dictionary(); + public class Instance { private DateTime nextwakeup; + private Boolean polling; public delegate void UpdatedInstance(Object sender, DeviceUpdateEvent e); public event UpdatedInstance Update; - public Dictionary CommandClasses { get { return this._commands; } } + public Int32 DeviceId { get; } + public Int32 InstanceId { get; } + public ReadOnlyDictionary CommandClasses { get; private set; } - private Instance(JsonData json, Tuple id, HttpConnection http) { - this.Id = id.Item1; - this.Instanceid = id.Item2; - foreach (String commandid in json["commandClasses"].Keys) { - this.CreateInstances(Int32.Parse(commandid), json["commandClasses"][commandid], http); - } + private Instance(JsonData json, Tuple id, HttpConnection http, Boolean polling) { + this.DeviceId = id.Item1; + this.InstanceId = id.Item2; + this.polling = polling; + this.CreateInstances(json["commandClasses"], http); foreach (KeyValuePair item in this.CommandClasses) { item.Value.Update += this.ClassUpdate; } @@ -39,27 +41,28 @@ namespace BlubbFish.IoT.Zway.Devices { this.Update?.Invoke(sender, e); } - private void CreateInstances(Int32 commandid, JsonData json, HttpConnection http) { - CommandClass c = CommandClass.CreateInstance(json, new Tuple(this.Id, this.Instanceid, commandid), http); - if (c != null) { - this._commands.Add(commandid, c); + private void CreateInstances(JsonData json, HttpConnection http) { + Dictionary commands = new Dictionary(); + foreach (String commandid in json.Keys) { + CommandClass c = CommandClass.CreateInstance(json[commandid], new Tuple(this.DeviceId, this.InstanceId, Int32.Parse(commandid)), http, this.polling); + if (c != null) { + commands.Add(Int32.Parse(commandid), c); + } } + this.CommandClasses = new ReadOnlyDictionary(commands); } - public Int32 Id { get; } - public Int32 Instanceid { get; } - - internal static Instance CreateInstance(JsonData json, Tuple id, HttpConnection http) { + internal static Instance CreateInstance(JsonData json, Tuple id, HttpConnection http, Boolean polling) { if (json.Keys.Contains("commandClasses") && json["commandClasses"].Count > 0 && json.Keys.Contains("data")) { - return new Instance(json, id, http); + return new Instance(json, id, http, polling); } return null; } public override String ToString() { - return "Instance: " + this.Id + "-" + this.Instanceid + " [" + this._commands.Count + "]"; + return "Instance: " + this.DeviceId + "-" + this.InstanceId + " [" + this.CommandClasses.Count + "]"; } internal void Poll() { diff --git a/Zway/Events/DeviceUpdateEvent.cs b/Zway/Events/DeviceUpdateEvent.cs index 9365702..ab6f92d 100644 --- a/Zway/Events/DeviceUpdateEvent.cs +++ b/Zway/Events/DeviceUpdateEvent.cs @@ -15,8 +15,8 @@ namespace BlubbFish.IoT.Zway.Events { this.UpdateTime = time; } - public DeviceUpdateEvent(Boolean level, DateTime time) { - this.GetBoolean = level; + public DeviceUpdateEvent(Boolean value, DateTime time) { + this.GetBoolean = value; this.UpdateTime = time; } @@ -39,10 +39,16 @@ namespace BlubbFish.IoT.Zway.Events { this.UpdateTime = time; } + public DeviceUpdateEvent(Tuple value, DateTime time) { + this.GetLongIntegerTuple = value; + this.UpdateTime = time; + } + public Single GetSingle { get; } public DateTime GetDate { get; } public Tuple GetStringStringSingleTuple { get; } public Tuple GetStringStringSingleSingleSingleSingleBooleanTuple { get; } + public Tuple GetLongIntegerTuple { get; } public DateTime UpdateTime { get; } public Boolean GetBoolean { get; } public Tuple GetIntegerTuple { get; } diff --git a/Zway/Exceptions/ZwayExceptions.cs b/Zway/Exceptions/ZwayExceptions.cs index 861305e..14a3e11 100644 --- a/Zway/Exceptions/ZwayExceptions.cs +++ b/Zway/Exceptions/ZwayExceptions.cs @@ -1,11 +1,8 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Runtime.Serialization; -using System.Text; -using System.Threading.Tasks; namespace BlubbFish.IoT.Zway.Exceptions { + [Serializable] public class ConnectionException : Exception { public ConnectionException() { } public ConnectionException(String message) : base(message) { } diff --git a/Zway/Interfaces/ICommandClass.cs b/Zway/Interfaces/ICommandClass.cs new file mode 100644 index 0000000..33e31df --- /dev/null +++ b/Zway/Interfaces/ICommandClass.cs @@ -0,0 +1,14 @@ +using System; +using BlubbFish.IoT.Zway.Events; + +namespace BlubbFish.IoT.Zway.Interfaces { + public delegate void UpdatedValue(Object sender, DeviceUpdateEvent e); + public interface ICommandClass { + String Name { get; } + String Id { get; } + DateTime LastUpdate { get; } + Boolean Polling { get; set; } + + event UpdatedValue Update; + } +} diff --git a/Zway/Zway.csproj b/Zway/Zway.csproj index b8405fd..bb32775 100644 --- a/Zway/Zway.csproj +++ b/Zway/Zway.csproj @@ -45,7 +45,9 @@ + + @@ -53,6 +55,7 @@ + @@ -62,6 +65,7 @@ + diff --git a/Zway/ZwayController.cs b/Zway/ZwayController.cs index aa13d5a..40e1742 100644 --- a/Zway/ZwayController.cs +++ b/Zway/ZwayController.cs @@ -1,28 +1,38 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Globalization; +using System.Reflection; using System.Text.RegularExpressions; using System.Threading; using BlubbFish.IoT.Zway.Devices; using BlubbFish.IoT.Zway.Events; +using BlubbFish.IoT.Zway.Interfaces; using BlubbFish.IoT.Zway.lib; using LitJson; namespace BlubbFish.IoT.Zway { public class ZwayController : IDisposable { private HttpConnection http; - private Dictionary devices = new Dictionary(); private Thread updatethread; private Thread pollthread; + public static ReadOnlyDictionary namelist; + private Boolean polling; public delegate void DataUpdate(Object sender, DeviceUpdateEvent e); public event DataUpdate Update; - public ZwayController(String server, String user, String pass) { + public ReadOnlyDictionary Devices { get; private set; } + + public ZwayController(String server, String user, String pass, Dictionary names, Boolean enablePoll = true) { + namelist = new ReadOnlyDictionary(names); + this.polling = enablePoll; this.Connect(server, user, pass); } - public ZwayController(Dictionary settings) { + public ZwayController(Dictionary settings, Dictionary names, Boolean enablePoll = true) { + namelist = new ReadOnlyDictionary(names); + this.polling = enablePoll; this.Connect(settings["server"], settings["user"], settings["pass"]); } @@ -34,12 +44,12 @@ namespace BlubbFish.IoT.Zway { CultureInfo.DefaultThreadCurrentUICulture = info; Thread.CurrentThread.CurrentCulture = info; Thread.CurrentThread.CurrentUICulture = info; - this.ParseNamespace(this.http.GetJson("ZWaveAPI/Run/devices")); + this.CreateDevices(this.http.GetJson("ZWaveAPI/Run/devices")); this.updatethread = new Thread(this.Updater); this.updatethread.Start(); this.pollthread = new Thread(this.Poll); this.pollthread.Start(); - foreach (KeyValuePair item in this.devices) { + foreach (KeyValuePair item in this.Devices) { item.Value.Update += this.DeviceUpdate; } } @@ -56,13 +66,37 @@ namespace BlubbFish.IoT.Zway { Thread.CurrentThread.CurrentCulture = info; Thread.CurrentThread.CurrentUICulture = info; while(true) { - foreach (KeyValuePair item in this.devices) { + foreach (KeyValuePair item in this.Devices) { item.Value.Poll(); } Thread.Sleep(1000); } } + public ICommandClass GetCommandClass(Int32 deviceid, Int32 instanceid, Int32 classid) { + if(this.Devices.ContainsKey(deviceid) && this.Devices[deviceid].Instances.ContainsKey(instanceid) && this.Devices[deviceid].Instances[instanceid].CommandClasses.ContainsKey(classid)) { + return this.Devices[deviceid].Instances[instanceid].CommandClasses[classid]; + } + return null; + } + + public ICommandClass GetCommandClassSub(Int32 deviceid, Int32 instanceid, Int32 classid, Int32 subcid) { + ICommandClass comandclass = this.GetCommandClass(deviceid, instanceid, classid); + if (comandclass != null) { + foreach (PropertyInfo item in comandclass.GetType().GetProperties()) { + if (item.Name == "Sub") { + if (comandclass.GetType().GetProperty("Sub").PropertyType == typeof(ReadOnlyDictionary)) { + ReadOnlyDictionary commandclasssub = (ReadOnlyDictionary)comandclass.GetType().GetProperty("Sub").GetValue(comandclass); + if (commandclasssub.ContainsKey(subcid)) { + return commandclasssub[subcid]; + } + } + } + } + } + return null; + } + private void Updater() { CultureInfo info = new CultureInfo("de-DE"); info.NumberFormat.NumberDecimalSeparator = "."; @@ -79,8 +113,8 @@ namespace BlubbFish.IoT.Zway { Int32 deviceid = Int32.Parse(match.Groups[1].Value); Int32 instanceid = Int32.Parse(match.Groups[2].Value); Int32 commandid = Int32.Parse(match.Groups[3].Value); - if (this.devices.ContainsKey(deviceid) && this.devices[deviceid].Instances.ContainsKey(instanceid) && this.devices[deviceid].Instances[instanceid].CommandClasses.ContainsKey(commandid)) { - this.devices[deviceid].Instances[instanceid].CommandClasses[commandid].SetUpdate(notifications[item], match); + if (this.Devices.ContainsKey(deviceid) && this.Devices[deviceid].Instances.ContainsKey(instanceid) && this.Devices[deviceid].Instances[instanceid].CommandClasses.ContainsKey(commandid)) { + this.Devices[deviceid].Instances[instanceid].CommandClasses[commandid].SetUpdate(notifications[item], match); } } /*else { if(item.StartsWith("controller.")) { } @@ -95,8 +129,8 @@ namespace BlubbFish.IoT.Zway { match = new Regex("^devices\\.([0-9]+)\\.(data.*)", RegexOptions.IgnoreCase).Match(item); if(match.Success) { Int32 deviceid = Int32.Parse(match.Groups[1].Value); - if (this.devices.ContainsKey(deviceid)) { - this.devices[deviceid].SetUpdate(notifications[item], match); + if (this.Devices.ContainsKey(deviceid)) { + this.Devices[deviceid].SetUpdate(notifications[item], match); } } } @@ -104,22 +138,20 @@ namespace BlubbFish.IoT.Zway { } } - private void ParseNamespace(JsonData json) { + private void CreateDevices(JsonData json) { + Dictionary devices = new Dictionary(); foreach (String deviceid in json.Keys) { - this.CreateDevices(Int32.Parse(deviceid), json[deviceid]); - } - } - - private void CreateDevices(Int32 deviceid, JsonData json) { - Device d = Device.CreateDevice(json, new Tuple(deviceid), this.http); - if(d != null) { - this.devices.Add(deviceid, d); + Device d = Device.CreateDevice(json[deviceid], new Tuple(Int32.Parse(deviceid)), this.http, this.polling); + if (d != null) { + devices.Add(Int32.Parse(deviceid), d); + } } + this.Devices = new ReadOnlyDictionary(devices); } public List GetCommandClasses() { List ret = new List(); - foreach (KeyValuePair device in this.devices) { + foreach (KeyValuePair device in this.Devices) { foreach (KeyValuePair instance in device.Value.Instances) { foreach (KeyValuePair commandclass in instance.Value.CommandClasses) { if (commandclass.Value is T) { @@ -142,7 +174,7 @@ namespace BlubbFish.IoT.Zway { } this.updatethread = null; this.pollthread = null; - this.devices.Clear(); + this.Devices = null; this.disposedValue = true; } } @@ -151,7 +183,7 @@ namespace BlubbFish.IoT.Zway { Dispose(false); } - void IDisposable.Dispose() { + public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } diff --git a/Zway/lib/Helper.cs b/Zway/lib/Helper.cs new file mode 100644 index 0000000..1477cf0 --- /dev/null +++ b/Zway/lib/Helper.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlubbFish.IoT.Zway.lib { + class Helper { + internal static void WriteError(String text) { + Console.ForegroundColor = ConsoleColor.Red; + Console.Error.WriteLine("ERROR: "+text); + Console.ResetColor(); + } + } +} diff --git a/Zway/lib/HttpClient.cs b/Zway/lib/HttpClient.cs index 09a1a51..f14becf 100644 --- a/Zway/lib/HttpClient.cs +++ b/Zway/lib/HttpClient.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Linq; using System.Net; -using System.Runtime.CompilerServices; using System.Text; -using System.Threading.Tasks; using LitJson; namespace BlubbFish.IoT.Zway.lib { @@ -26,6 +22,9 @@ namespace BlubbFish.IoT.Zway.lib { internal JsonData GetJson(String v) { String text = this.GetString(v); + if(text == null) { + return new JsonData(); + } try { return JsonMapper.ToObject(text); } catch(Exception) { @@ -55,8 +54,9 @@ namespace BlubbFish.IoT.Zway.lib { } } } catch (Exception e) { - Console.Error.WriteLine("Konnte keine Verbindung zum Razzbery Server herstellen: " + e.Message); - throw new Exceptions.ConnectionException("Konnte keine Verbindung zum Razzbery Server herstellen: " + e.Message); + Helper.WriteError("Konnte keine Verbindung zum Razzbery Server herstellen. Resource: \"" + this.server + v + "\" Fehler: " + e.Message); + return null; + //throw new Exceptions.ConnectionException("Konnte keine Verbindung zum Razzbery Server herstellen: " + e.Message); } } return ret;