From 329375b7cb29b61cb7c1b6d50a11708a761c2721 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Mon, 18 Dec 2017 23:30:48 +0100 Subject: [PATCH] Change a lot stuff --- .gitignore | 32 +++ IoT-Bot/IoT-Bot.sln | 6 + IoT-Bot/IoT-Bot/Condition/ACondition.cs | 50 +++- IoT-Bot/IoT-Bot/Condition/Edge.cs | 8 + IoT-Bot/IoT-Bot/Condition/TelegramBot.cs | 93 +++++++ IoT-Bot/IoT-Bot/Condition/Trigger.cs | 27 ++ IoT-Bot/IoT-Bot/ConditionWorker.cs | 14 +- IoT-Bot/IoT-Bot/IoT-Bot.csproj | 10 +- IoT-Bot/IoT-Bot/Program.cs | 14 +- Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard.sln | 8 +- .../Mqtt-SWB-Dashboard/MainWindow.xaml.cs | 4 +- .../Mqtt-SWB-Dashboard.csproj | 5 + Utils/IoT.sln | 20 +- Utils/IoT/Connector/ADataBackend.cs | 5 +- Utils/IoT/Connector/AUserBackend.cs | 6 +- .../Mosquitto/ConnectorDataMosquitto.csproj | 53 ++++ .../Data/{ => Mosquitto}/Mosquitto.cs | 8 +- .../Data/Mosquitto/Properties/AssemblyInfo.cs | 36 +++ .../bin/Release/ConnectorDataMosquitto.dll | Bin 0 -> 8192 bytes .../Data/Mosquitto/bin/Release/LitJson.dll | Bin 0 -> 54272 bytes .../Data/Mosquitto/bin/Release/Utils-IoT.dll | Bin 0 -> 14336 bytes .../Data/Mqtt/ConnectorDataMqtt.csproj | 59 +++++ Utils/IoT/Connector/Data/{ => Mqtt}/Mqtt.cs | 11 +- .../Data/Mqtt/Properties/AssemblyInfo.cs | 36 +++ .../Mqtt/bin/Release/ConnectorDataMqtt.dll | Bin 0 -> 6656 bytes .../Data/Mqtt/bin/Release/LitJson.dll | Bin 0 -> 54272 bytes .../Data/Mqtt/bin/Release/M2Mqtt.Net.dll | Bin 0 -> 52224 bytes .../Data/Mqtt/bin/Release/Utils-IoT.dll | Bin 0 -> 14336 bytes Utils/IoT/Connector/Data/Mqtt/packages.config | 4 + Utils/IoT/Connector/Helper.cs | 4 - .../Telegram/ConnectorUserTelegram.csproj | 119 +++++++++ .../User/Telegram/Properties/AssemblyInfo.cs | 36 +++ .../Connector/User/{ => Telegram}/Telegram.cs | 24 +- .../{ => Connector/User/Telegram}/app.config | 2 +- .../bin/Release/ConnectorUserTelegram.dll | Bin 0 -> 8704 bytes .../User/Telegram/bin/Release/LitJson.dll | Bin 0 -> 54272 bytes .../Release/Microsoft.Win32.Primitives.dll | Bin 0 -> 22768 bytes .../Telegram/bin/Release/Newtonsoft.Json.dll | Bin 0 -> 653824 bytes .../bin/Release/System.AppContext.dll | Bin 0 -> 20168 bytes .../Telegram/bin/Release/System.Console.dll | Bin 0 -> 34496 bytes .../System.Diagnostics.DiagnosticSource.dll | Bin 0 -> 35760 bytes .../System.Globalization.Calendars.dll | Bin 0 -> 23296 bytes .../Release/System.IO.Compression.ZipFile.dll | Bin 0 -> 24824 bytes .../bin/Release/System.IO.Compression.dll | Bin 0 -> 111984 bytes .../System.IO.FileSystem.Primitives.dll | Bin 0 -> 22784 bytes .../bin/Release/System.IO.FileSystem.dll | Bin 0 -> 22736 bytes .../Telegram/bin/Release/System.Net.Http.dll | Bin 0 -> 265048 bytes .../bin/Release/System.Net.Sockets.dll | Bin 0 -> 46280 bytes ...ime.InteropServices.RuntimeInformation.dll | Bin 0 -> 33256 bytes ...ystem.Security.Cryptography.Algorithms.dll | Bin 0 -> 39872 bytes .../System.Security.Cryptography.Encoding.dll | Bin 0 -> 23480 bytes ...ystem.Security.Cryptography.Primitives.dll | Bin 0 -> 22816 bytes ...Security.Cryptography.X509Certificates.dll | Bin 0 -> 38872 bytes .../bin/Release/System.Xml.ReaderWriter.dll | Bin 0 -> 23264 bytes .../Telegram/bin/Release/Telegram.Bot.dll | Bin 0 -> 153088 bytes .../User/Telegram/bin/Release/Utils-IoT.dll | Bin 0 -> 14336 bytes .../Connector/User/Telegram/packages.config | 51 ++++ Utils/IoT/Utils-IoT.csproj | 69 +----- Utils/IoT/bin/Release/Utils-IoT.dll | Bin 22016 -> 14336 bytes Utils/IoT/packages.config | 49 ---- Utils/Utils/bin/Release/Utils.dll | Bin 24576 -> 24576 bytes Zway-Bot/Zway-Bot.sln | 55 +++++ Zway-Bot/Zway-Bot/Events.cs | 81 ++++++ Zway-Bot/Zway-Bot/Helper.cs | 63 +++++ Zway-Bot/Zway-Bot/Interfaces/IForceLoad.cs | 4 + Zway-Bot/Zway-Bot/Moduls/AModul.cs | 25 ++ Zway-Bot/Zway-Bot/Moduls/CronJob.cs | 186 ++++++++++++++ Zway-Bot/Zway-Bot/Moduls/Flex4Grid.cs | 187 ++++++++++++++ Zway-Bot/Zway-Bot/Moduls/Mqtt.cs | 62 +++++ Zway-Bot/Zway-Bot/Moduls/Overtaker.cs | 96 ++++++++ Zway-Bot/Zway-Bot/Moduls/StatusPolling.cs | 58 +++++ Zway-Bot/Zway-Bot/Program.cs | 92 +++++++ Zway-Bot/Zway-Bot/Properties/AssemblyInfo.cs | 40 +++ .../Zway-Bot/Properties/Resources.Designer.cs | 73 ++++++ Zway-Bot/Zway-Bot/Properties/Resources.resx | 124 ++++++++++ Zway-Bot/Zway-Bot/Resources/Icon.ico | Bin 0 -> 3446 bytes Zway-Bot/Zway-Bot/Resources/icon.svg | 1 + Zway-Bot/Zway-Bot/Zway-Bot.csproj | 109 ++++++++ .../bin/Release/ConnectorDataMosquitto.dll | Bin 0 -> 8192 bytes .../bin/Release/ConnectorDataMqtt.dll | Bin 0 -> 6656 bytes Zway-Bot/Zway-Bot/bin/Release/LitJson.dll | Bin 0 -> 54272 bytes Zway-Bot/Zway-Bot/bin/Release/M2Mqtt.Net.dll | Bin 0 -> 52224 bytes Zway-Bot/Zway-Bot/bin/Release/Utils-IoT.dll | Bin 0 -> 14336 bytes Zway-Bot/Zway-Bot/bin/Release/Utils.dll | Bin 0 -> 24576 bytes Zway-Bot/Zway-Bot/bin/Release/Zway-Bot.exe | Bin 0 -> 34816 bytes Zway-Bot/Zway-Bot/bin/Release/Zway.dll | Bin 0 -> 49664 bytes Zway-Bot/Zway-Bot/packages.config | 4 + Zway/Zway.sln | 25 ++ Zway/Zway/Devices/CommandClasses/Battery.cs | 61 +++++ .../Devices/CommandClasses/CentralScene.cs | 86 +++++++ .../CommandClassSubs/Configurationsub.cs | 69 ++++++ .../CommandClassSubs/MeterSub.cs | 61 +++++ .../CommandClassSubs/SensorMultilevelSub.cs | 61 +++++ .../CommandClassSubs/ThermostatSetPointSub.cs | 94 +++++++ .../Devices/CommandClasses/Configuration.cs | 62 +++++ Zway/Zway/Devices/CommandClasses/Indicator.cs | 57 +++++ Zway/Zway/Devices/CommandClasses/Meter.cs | 61 +++++ .../CommandClasses/SensorMultilevel.cs | 61 +++++ .../Devices/CommandClasses/SwitchBinary.cs | 58 +++++ .../CommandClasses/SwitchMultilevel.cs | 61 +++++ .../Devices/CommandClasses/ThermostatMode.cs | 80 ++++++ .../CommandClasses/ThermostatSetPoint.cs | 61 +++++ Zway/Zway/Devices/CommandClasses/Wakeup.cs | 137 ++++++++++ Zway/Zway/Devices/Device.cs | 91 +++++++ Zway/Zway/Devices/Instance.cs | 78 ++++++ Zway/Zway/Events/DeviceUpdateEvent.cs | 64 +++++ Zway/Zway/Exceptions/ZwayExceptions.cs | 12 + Zway/Zway/Interfaces/ACommandClass.cs | 233 ++++++++++++++++++ Zway/Zway/Properties/AssemblyInfo.cs | 36 +++ Zway/Zway/Zway.csproj | 76 ++++++ Zway/Zway/ZwayController.cs | 193 +++++++++++++++ Zway/Zway/bin/Release/LitJson.dll | Bin 0 -> 54272 bytes Zway/Zway/bin/Release/Zway.dll | Bin 0 -> 49664 bytes Zway/Zway/lib/Helper.cs | 15 ++ Zway/Zway/lib/HttpClient.cs | 65 +++++ Zway/Zway/packages.config | 4 + 116 files changed, 3936 insertions(+), 149 deletions(-) create mode 100644 IoT-Bot/IoT-Bot/Condition/TelegramBot.cs create mode 100644 IoT-Bot/IoT-Bot/Condition/Trigger.cs create mode 100644 Utils/IoT/Connector/Data/Mosquitto/ConnectorDataMosquitto.csproj rename Utils/IoT/Connector/Data/{ => Mosquitto}/Mosquitto.cs (94%) create mode 100644 Utils/IoT/Connector/Data/Mosquitto/Properties/AssemblyInfo.cs create mode 100644 Utils/IoT/Connector/Data/Mosquitto/bin/Release/ConnectorDataMosquitto.dll create mode 100644 Utils/IoT/Connector/Data/Mosquitto/bin/Release/LitJson.dll create mode 100644 Utils/IoT/Connector/Data/Mosquitto/bin/Release/Utils-IoT.dll create mode 100644 Utils/IoT/Connector/Data/Mqtt/ConnectorDataMqtt.csproj rename Utils/IoT/Connector/Data/{ => Mqtt}/Mqtt.cs (85%) create mode 100644 Utils/IoT/Connector/Data/Mqtt/Properties/AssemblyInfo.cs create mode 100644 Utils/IoT/Connector/Data/Mqtt/bin/Release/ConnectorDataMqtt.dll create mode 100644 Utils/IoT/Connector/Data/Mqtt/bin/Release/LitJson.dll create mode 100644 Utils/IoT/Connector/Data/Mqtt/bin/Release/M2Mqtt.Net.dll create mode 100644 Utils/IoT/Connector/Data/Mqtt/bin/Release/Utils-IoT.dll create mode 100644 Utils/IoT/Connector/Data/Mqtt/packages.config create mode 100644 Utils/IoT/Connector/User/Telegram/ConnectorUserTelegram.csproj create mode 100644 Utils/IoT/Connector/User/Telegram/Properties/AssemblyInfo.cs rename Utils/IoT/Connector/User/{ => Telegram}/Telegram.cs (56%) rename Utils/IoT/{ => Connector/User/Telegram}/app.config (86%) create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/ConnectorUserTelegram.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/LitJson.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/Microsoft.Win32.Primitives.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/Newtonsoft.Json.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.AppContext.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.Console.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.Diagnostics.DiagnosticSource.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.Globalization.Calendars.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.IO.Compression.ZipFile.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.IO.Compression.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.IO.FileSystem.Primitives.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.IO.FileSystem.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.Net.Http.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.Net.Sockets.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.Runtime.InteropServices.RuntimeInformation.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.Security.Cryptography.Algorithms.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.Security.Cryptography.Encoding.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.Security.Cryptography.Primitives.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.Security.Cryptography.X509Certificates.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/System.Xml.ReaderWriter.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/Telegram.Bot.dll create mode 100644 Utils/IoT/Connector/User/Telegram/bin/Release/Utils-IoT.dll create mode 100644 Utils/IoT/Connector/User/Telegram/packages.config create mode 100644 Zway-Bot/Zway-Bot.sln create mode 100644 Zway-Bot/Zway-Bot/Events.cs create mode 100644 Zway-Bot/Zway-Bot/Helper.cs create mode 100644 Zway-Bot/Zway-Bot/Interfaces/IForceLoad.cs create mode 100644 Zway-Bot/Zway-Bot/Moduls/AModul.cs create mode 100644 Zway-Bot/Zway-Bot/Moduls/CronJob.cs create mode 100644 Zway-Bot/Zway-Bot/Moduls/Flex4Grid.cs create mode 100644 Zway-Bot/Zway-Bot/Moduls/Mqtt.cs create mode 100644 Zway-Bot/Zway-Bot/Moduls/Overtaker.cs create mode 100644 Zway-Bot/Zway-Bot/Moduls/StatusPolling.cs create mode 100644 Zway-Bot/Zway-Bot/Program.cs create mode 100644 Zway-Bot/Zway-Bot/Properties/AssemblyInfo.cs create mode 100644 Zway-Bot/Zway-Bot/Properties/Resources.Designer.cs create mode 100644 Zway-Bot/Zway-Bot/Properties/Resources.resx create mode 100644 Zway-Bot/Zway-Bot/Resources/Icon.ico create mode 100644 Zway-Bot/Zway-Bot/Resources/icon.svg create mode 100644 Zway-Bot/Zway-Bot/Zway-Bot.csproj create mode 100644 Zway-Bot/Zway-Bot/bin/Release/ConnectorDataMosquitto.dll create mode 100644 Zway-Bot/Zway-Bot/bin/Release/ConnectorDataMqtt.dll create mode 100644 Zway-Bot/Zway-Bot/bin/Release/LitJson.dll create mode 100644 Zway-Bot/Zway-Bot/bin/Release/M2Mqtt.Net.dll create mode 100644 Zway-Bot/Zway-Bot/bin/Release/Utils-IoT.dll create mode 100644 Zway-Bot/Zway-Bot/bin/Release/Utils.dll create mode 100644 Zway-Bot/Zway-Bot/bin/Release/Zway-Bot.exe create mode 100644 Zway-Bot/Zway-Bot/bin/Release/Zway.dll create mode 100644 Zway-Bot/Zway-Bot/packages.config create mode 100644 Zway/Zway.sln create mode 100644 Zway/Zway/Devices/CommandClasses/Battery.cs create mode 100644 Zway/Zway/Devices/CommandClasses/CentralScene.cs create mode 100644 Zway/Zway/Devices/CommandClasses/CommandClassSubs/Configurationsub.cs create mode 100644 Zway/Zway/Devices/CommandClasses/CommandClassSubs/MeterSub.cs create mode 100644 Zway/Zway/Devices/CommandClasses/CommandClassSubs/SensorMultilevelSub.cs create mode 100644 Zway/Zway/Devices/CommandClasses/CommandClassSubs/ThermostatSetPointSub.cs create mode 100644 Zway/Zway/Devices/CommandClasses/Configuration.cs create mode 100644 Zway/Zway/Devices/CommandClasses/Indicator.cs create mode 100644 Zway/Zway/Devices/CommandClasses/Meter.cs create mode 100644 Zway/Zway/Devices/CommandClasses/SensorMultilevel.cs create mode 100644 Zway/Zway/Devices/CommandClasses/SwitchBinary.cs create mode 100644 Zway/Zway/Devices/CommandClasses/SwitchMultilevel.cs create mode 100644 Zway/Zway/Devices/CommandClasses/ThermostatMode.cs create mode 100644 Zway/Zway/Devices/CommandClasses/ThermostatSetPoint.cs create mode 100644 Zway/Zway/Devices/CommandClasses/Wakeup.cs create mode 100644 Zway/Zway/Devices/Device.cs create mode 100644 Zway/Zway/Devices/Instance.cs create mode 100644 Zway/Zway/Events/DeviceUpdateEvent.cs create mode 100644 Zway/Zway/Exceptions/ZwayExceptions.cs create mode 100644 Zway/Zway/Interfaces/ACommandClass.cs create mode 100644 Zway/Zway/Properties/AssemblyInfo.cs create mode 100644 Zway/Zway/Zway.csproj create mode 100644 Zway/Zway/ZwayController.cs create mode 100644 Zway/Zway/bin/Release/LitJson.dll create mode 100644 Zway/Zway/bin/Release/Zway.dll create mode 100644 Zway/Zway/lib/Helper.cs create mode 100644 Zway/Zway/lib/HttpClient.cs create mode 100644 Zway/Zway/packages.config diff --git a/.gitignore b/.gitignore index 34c17c7..1bbf276 100644 --- a/.gitignore +++ b/.gitignore @@ -131,3 +131,35 @@ /Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/Newtonsoft.Json.xml /Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/Utils-IoT.dll.config /Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/Utils-IoT.pdb +/Zway/.vs/Zway/v15 +/Zway/Zway/obj/Debug +/Zway/Zway/bin/Debug +/IoT-Bot/.vs/config +/Zway-Bot/.vs +/Zway-Bot/packages +/Zway-Bot/Zway-Bot/obj +/Zway-Bot/Zway-Bot/bin/Debug +/Zway-Bot/Zway-Bot/bin/Release/ConnectorDataMosquitto.pdb +/Zway-Bot/Zway-Bot/bin/Release/ConnectorDataMqtt.pdb +/Zway-Bot/Zway-Bot/bin/Release/M2Mqtt.Net.pdb +/Zway-Bot/Zway-Bot/bin/Release/Utils-IoT.pdb +/Zway-Bot/Zway-Bot/bin/Release/Utils.pdb +/Zway-Bot/Zway-Bot/bin/Release/Zway-Bot.pdb +/Zway-Bot/Zway-Bot/bin/Release/Zway.pdb +/Zway/Zway/bin/Release/Zway.pdb +/Zway/Zway/obj/Release +/Utils/IoT/Connector/User/Telegram/obj/Release +/Utils/IoT/Connector/User/Telegram/bin/Release/ConnectorUserTelegram.dll.config +/Utils/IoT/Connector/User/Telegram/bin/Release/ConnectorUserTelegram.pdb +/Utils/IoT/Connector/User/Telegram/bin/Release/Newtonsoft.Json.xml +/Utils/IoT/Connector/User/Telegram/bin/Release/System.Diagnostics.DiagnosticSource.xml +/Utils/IoT/Connector/User/Telegram/bin/Release/Utils-IoT.pdb +/Utils/IoT/Connector/Data/Mqtt/obj +/Utils/IoT/Connector/Data/Mqtt/bin/Debug +/Utils/IoT/Connector/Data/Mqtt/bin/Release/ConnectorDataMqtt.pdb +/Utils/IoT/Connector/Data/Mqtt/bin/Release/M2Mqtt.Net.pdb +/Utils/IoT/Connector/Data/Mqtt/bin/Release/Utils-IoT.pdb +/Utils/IoT/Connector/Data/Mosquitto/obj +/Utils/IoT/Connector/Data/Mosquitto/bin/Debug +/Utils/IoT/Connector/Data/Mosquitto/bin/Release/ConnectorDataMosquitto.pdb +/Utils/IoT/Connector/Data/Mosquitto/bin/Release/Utils-IoT.pdb diff --git a/IoT-Bot/IoT-Bot.sln b/IoT-Bot/IoT-Bot.sln index 0c2eb85..3eb7bd9 100644 --- a/IoT-Bot/IoT-Bot.sln +++ b/IoT-Bot/IoT-Bot.sln @@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils-IoT", "..\Utils\IoT\U EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "..\Utils\Utils\Utils.csproj", "{FAC8CE64-BF13-4ECE-8097-AEB5DD060098}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Zway", "..\Zway\Zway\Zway.csproj", "{166258ED-CB3D-43F5-8E8D-3A993B64D022}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +29,10 @@ Global {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Debug|Any CPU.Build.0 = Debug|Any CPU {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Release|Any CPU.ActiveCfg = Release|Any CPU {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Release|Any CPU.Build.0 = Release|Any CPU + {166258ED-CB3D-43F5-8E8D-3A993B64D022}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {166258ED-CB3D-43F5-8E8D-3A993B64D022}.Debug|Any CPU.Build.0 = Debug|Any CPU + {166258ED-CB3D-43F5-8E8D-3A993B64D022}.Release|Any CPU.ActiveCfg = Release|Any CPU + {166258ED-CB3D-43F5-8E8D-3A993B64D022}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/IoT-Bot/IoT-Bot/Condition/ACondition.cs b/IoT-Bot/IoT-Bot/Condition/ACondition.cs index ca83a93..7262316 100644 --- a/IoT-Bot/IoT-Bot/Condition/ACondition.cs +++ b/IoT-Bot/IoT-Bot/Condition/ACondition.cs @@ -7,20 +7,68 @@ namespace IoTBot.Condition { abstract class ACondition { protected ASensor sensor; protected Dictionary settings; + protected String name; protected ADataBackend data; protected AUserBackend user; protected ACondition(String name, Dictionary settings, ASensor sensor, ADataBackend data, AUserBackend user) { this.settings = settings; + this.name = name; this.data = data; this.user = user; this.sensor = sensor; } public void Attach() { - this.sensor.Update += this.Sensor_Update; + if(this.sensor != null) { + this.sensor.Update += this.Sensor_Update; + } + switch (this.settings["source"].ToLower()) { + case "user": + if(this.user != null) { + this.user.MessageIncomming += this.User_Update; + } + break; + case "data": + if(this.data != null) { + this.data.MessageIncomming += this.Data_Update; + } + break; + case "both": + if (this.user != null) { + this.user.MessageIncomming += this.User_Update; + } + if (this.data != null) { + this.data.MessageIncomming += this.Data_Update; + } + break; + } } + protected void Send(String message = "", String topic = "") { + if(message == "") { + message = this.settings["target_message"]; + } + if(topic == "") { + topic = this.settings["target_topic"]; + } + switch (this.settings["target"].ToLower()) { + case "user": + this.user.Send(message); + break; + case "data": + this.data.Send(topic, message); + break; + case "sensor": + //this.sensor.Set(message); + break; + } + } + + protected abstract void Data_Update(Object sender, MqttEventArgs e); + + protected abstract void User_Update(Object sender, UserMessageEventArgs e); + protected abstract void Sensor_Update(Object sender, EventArgs e); public static ACondition GetInstance(String name, Dictionary settings, ASensor sensor, ADataBackend data, AUserBackend user) { diff --git a/IoT-Bot/IoT-Bot/Condition/Edge.cs b/IoT-Bot/IoT-Bot/Condition/Edge.cs index becced0..fc2e6db 100644 --- a/IoT-Bot/IoT-Bot/Condition/Edge.cs +++ b/IoT-Bot/IoT-Bot/Condition/Edge.cs @@ -9,6 +9,10 @@ namespace IoTBot.Condition { public Edge(String name, Dictionary settings, ASensor sensor, ADataBackend data, AUserBackend user) : base(name, settings, sensor, data, user) { } + protected override void Data_Update(Object sender, MqttEventArgs e) { + //throw new NotImplementedException(); + } + protected override void Sensor_Update(Object sender, EventArgs e) { if(this.sensor.Datatypes == ASensor.Types.Bool) { if(this.sensor.GetBool == Boolean.Parse(this.settings["sensor_value"]) && this.histBool != this.sensor.GetBool) { @@ -19,5 +23,9 @@ namespace IoTBot.Condition { } } } + + protected override void User_Update(Object sender, UserMessageEventArgs e) { + //throw new NotImplementedException(); + } } } diff --git a/IoT-Bot/IoT-Bot/Condition/TelegramBot.cs b/IoT-Bot/IoT-Bot/Condition/TelegramBot.cs new file mode 100644 index 0000000..57dd2ff --- /dev/null +++ b/IoT-Bot/IoT-Bot/Condition/TelegramBot.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using BlubbFish.IoT.Zway; +using BlubbFish.IoT.Zway.Devices.CommandClasses; +using BlubbFish.Utils.IoT.Connector; +using BlubbFish.Utils.IoT.Sensor; + +namespace IoTBot.Condition { + class Telegrambot : ACondition { + private ZwayController zw; + + public Telegrambot(String name, Dictionary settings, ASensor sensor, ADataBackend data, AUserBackend user) : base(name, settings, sensor, data, user) { + this.zw = new ZwayController("10.100.0.214", "admin", ""); + this.zw.Update += this.Zw_Update; + } + + private void Zw_Update(Object sender, BlubbFish.IoT.Zway.Events.DeviceUpdateEvent e) { + Console.WriteLine("-> ZW: "+sender.ToString()); + } + + protected override void Data_Update(Object sender, MqttEventArgs e) { + //throw new NotImplementedException(); + } + + protected override void Sensor_Update(Object sender, EventArgs e) { + //throw new NotImplementedException(); + } + + protected override void User_Update(Object sender, UserMessageEventArgs e) { + if(e.Message == "/start") { + this.Send("Hallo zurück! Ich kann aktuell die Befehle /schalter"); + } + if (e.Message.StartsWith("/schalter")) { + this.BotSchalter(e.Message); + } + } + + private void BotSchalter(String message) { + if (message == "/schalter") { + this.user.Send("Was soll ich tun?", new String[] { "/schalter einschalten", "/schalter ausschalten", "/schalter status" }); + } + if(message == "/schalter status") { + String ret = "Der Status des Schalters ist: "; + foreach (Switchbinary item in this.zw.GetCommandClasses()) { + ret += item.Name + ": " + (item.Level ? "An" : "Aus") + ", "; + } + this.user.Send(ret.Substring(0, ret.Length - 2)); + } + if (message == "/schalter einschalten") { + List s = new List(); + foreach (Switchbinary item in this.zw.GetCommandClasses()) { + if (!item.Level) { + s.Add("/schalter einschalten " + item.Name); + } + } + if (s.Count > 0) { + this.user.Send("Was soll ich tun?", s.ToArray()); + } else { + this.user.Send("Keine Geräte ausgeschaltet!"); + } + } else if(message.StartsWith("/schalter einschalten ")) { + String device = message.Substring(22); + foreach (Switchbinary item in this.zw.GetCommandClasses()) { + if(item.Name == device) { + item.Level = true; + this.user.Send("Einschalten von " + item.Name + " " + (item.Level ? "" : "nicht ") + "erfolgreich"); + } + } + } + if (message == "/schalter ausschalten") { + List s = new List(); + foreach (Switchbinary item in this.zw.GetCommandClasses()) { + if (item.Level) { + s.Add("/schalter ausschalten " + item.Name); + } + } + if (s.Count > 0) { + this.user.Send("Was soll ich tun?", s.ToArray()); + } else { + this.user.Send("Keine Geräte eingeschaltet!"); + } + } else if (message.StartsWith("/schalter ausschalten ")) { + String device = message.Substring(22); + foreach (Switchbinary item in this.zw.GetCommandClasses()) { + if (item.Name == device) { + item.Level = false; + this.user.Send("Ausschalten von " + item.Name + " " + (item.Level ? "nicht " : "") + "erfolgreich"); + } + } + } + } + } +} diff --git a/IoT-Bot/IoT-Bot/Condition/Trigger.cs b/IoT-Bot/IoT-Bot/Condition/Trigger.cs new file mode 100644 index 0000000..5e05976 --- /dev/null +++ b/IoT-Bot/IoT-Bot/Condition/Trigger.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BlubbFish.Utils.IoT.Connector; +using BlubbFish.Utils.IoT.Sensor; + +namespace IoTBot.Condition { + class Trigger : ACondition { + public Trigger(String name, Dictionary settings, ASensor sensor, ADataBackend data, AUserBackend user) : base(name, settings, sensor, data, user) { } + + protected override void Data_Update(Object sender, MqttEventArgs e) { + //throw new NotImplementedException(); + } + + protected override void Sensor_Update(Object sender, EventArgs e) { + //throw new NotImplementedException(); + } + + protected override void User_Update(Object sender, UserMessageEventArgs e) { + if (e.Message == this.settings["trigger"]) { + this.Send(); + } + } + } +} diff --git a/IoT-Bot/IoT-Bot/ConditionWorker.cs b/IoT-Bot/IoT-Bot/ConditionWorker.cs index 5e3fb20..554b4dc 100644 --- a/IoT-Bot/IoT-Bot/ConditionWorker.cs +++ b/IoT-Bot/IoT-Bot/ConditionWorker.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using BlubbFish.Utils; using BlubbFish.Utils.IoT.Connector; using BlubbFish.Utils.IoT.Sensor; using IoTBot.Condition; @@ -17,13 +16,16 @@ namespace IoTBot { } public void SetCondition(String name, Dictionary settings) { - Dictionary sensor_settings = new Dictionary(); - foreach (KeyValuePair item in settings) { - if(item.Key.StartsWith("sensor_")) { - sensor_settings.Add(item.Key.Substring(7), item.Value); + ASensor sensor = null; + if (settings.ContainsKey("sensor_type")) { + Dictionary sensor_settings = new Dictionary(); + foreach (KeyValuePair item in settings) { + if (item.Key.StartsWith("sensor_")) { + sensor_settings.Add(item.Key.Substring(7), item.Value); + } } + sensor = ASensor.GetInstance(this.data, sensor_settings, name); } - ASensor sensor = ASensor.GetInstance(this.data, sensor_settings, name); this.conditions.Add(ACondition.GetInstance(name, settings, sensor, this.data, this.user)); } diff --git a/IoT-Bot/IoT-Bot/IoT-Bot.csproj b/IoT-Bot/IoT-Bot/IoT-Bot.csproj index 588acdc..bf1b443 100644 --- a/IoT-Bot/IoT-Bot/IoT-Bot.csproj +++ b/IoT-Bot/IoT-Bot/IoT-Bot.csproj @@ -7,8 +7,8 @@ {89077643-B472-419F-8EAB-56B9E2D13ABC} Exe Properties - MqttToTelegram - MqttToTelegram + IoTBot + IoTBot v4.6.2 512 true @@ -37,6 +37,8 @@ + + @@ -55,6 +57,10 @@ {fac8ce64-bf13-4ece-8097-aeb5dd060098} Utils + + {166258ed-cb3d-43f5-8e8d-3a993b64d022} + Zway + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\Icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/Zway-Bot/Zway-Bot/Resources/Icon.ico b/Zway-Bot/Zway-Bot/Resources/Icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..4d42acd8c043c01889c449794fd405c10547a385 GIT binary patch literal 3446 zcmeHJy^hmB5FXzlt%Z<$C7n|N4}owB9^|N?bVsN>r$}TgXn7k3q`4 z!#6Xr6;23I(cnpDKhMv8GrO{-AZE7*RzLHznA%{4d@hB-!tIR1d)~|?z zf4sz`0`Gv4r7Z;njc7l8jRn#Tl_YpyrAh|r==z0XJ7f1q?Sssi!)^}7Gk{omlQyTd zw2*dyd>7;mjoJO`gs89aPjm!|yuU0Aw@Gm;yaJAdPD%lJrTxMv^c-l**rnY&emOXH zdnf7l*aYccI%2R6LD$fE&cqBl$v>PkV?7l$WTIak zL}&9aQQ)9?d5k;H$A**Gz8z^iP>ePdTZoOLc3w527Ihv=)~wp=*W86%A zF>FXQPCPIagmaS&YWR#DAv+E1`BWiBR-4WaZuZXWX$baP0BX*{*mp95cIt;wk5+<% zDW81oU1`u|ca{!M&2zUJpSF3fk==96hw+qq(P`graC!+-gEzax*MOJ3``A_Aj&0c$ zT;l5}Z}akVSEOR7QWz5*(m=1%kUvfDhLEyUjG2^jmxA2&_>iC-l%EG-5JqTQK^qW5 KdlC5oJ;_gVb~bMS literal 0 HcmV?d00001 diff --git a/Zway-Bot/Zway-Bot/Resources/icon.svg b/Zway-Bot/Zway-Bot/Resources/icon.svg new file mode 100644 index 0000000..d6bba08 --- /dev/null +++ b/Zway-Bot/Zway-Bot/Resources/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Zway-Bot/Zway-Bot/Zway-Bot.csproj b/Zway-Bot/Zway-Bot/Zway-Bot.csproj new file mode 100644 index 0000000..053fc03 --- /dev/null +++ b/Zway-Bot/Zway-Bot/Zway-Bot.csproj @@ -0,0 +1,109 @@ + + + + + Debug + AnyCPU + {AEF8059F-8AEF-45C7-85C4-318C8F797900} + Exe + ZwayBot + Zway-Bot + v4.7.1 + 512 + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + ZwayBot.Program + + + Resources\Icon.ico + + + + ..\packages\LitJson.0.9.0\lib\LitJson.dll + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + {39235fad-ba9d-4b51-82fc-6969967beae9} + ConnectorDataMosquitto + + + {ee6c8f68-ed46-4c1c-abdd-cfcdf75104f2} + ConnectorDataMqtt + + + {b870e4d5-6806-4a0b-b233-8907eedc5afc} + Utils-IoT + + + {fac8ce64-bf13-4ece-8097-aeb5dd060098} + Utils + + + {166258ed-cb3d-43f5-8e8d-3a993b64d022} + Zway + + + + + + + + + + + + PublicResXFileCodeGenerator + Resources.Designer.cs + + + + \ No newline at end of file diff --git a/Zway-Bot/Zway-Bot/bin/Release/ConnectorDataMosquitto.dll b/Zway-Bot/Zway-Bot/bin/Release/ConnectorDataMosquitto.dll new file mode 100644 index 0000000000000000000000000000000000000000..ce671c57d55da3ee40736e9a8069ff4688093e02 GIT binary patch literal 8192 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 literal 0 HcmV?d00001 diff --git a/Zway-Bot/Zway-Bot/bin/Release/LitJson.dll b/Zway-Bot/Zway-Bot/bin/Release/LitJson.dll new file mode 100644 index 0000000000000000000000000000000000000000..f00f11f11441dcc457ea0684ac462e466bf8df54 GIT binary patch literal 54272 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 literal 0 HcmV?d00001 diff --git a/Zway-Bot/Zway-Bot/bin/Release/M2Mqtt.Net.dll b/Zway-Bot/Zway-Bot/bin/Release/M2Mqtt.Net.dll new file mode 100644 index 0000000000000000000000000000000000000000..154580d98531857d97512f52694e035fa5e032a0 GIT binary patch literal 52224 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 literal 0 HcmV?d00001 diff --git a/Zway-Bot/Zway-Bot/bin/Release/Utils.dll b/Zway-Bot/Zway-Bot/bin/Release/Utils.dll new file mode 100644 index 0000000000000000000000000000000000000000..b86be2cfa28d38c7306f309133ed0bd65c45c937 GIT binary patch literal 24576 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 R4bOij%l^MD{|7wqzX17XGlc*E literal 0 HcmV?d00001 diff --git a/Zway-Bot/Zway-Bot/bin/Release/Zway-Bot.exe b/Zway-Bot/Zway-Bot/bin/Release/Zway-Bot.exe new file mode 100644 index 0000000000000000000000000000000000000000..378e85a3419eb9e4acd5eddbb5eb334dbf1b845f GIT binary patch literal 34816 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 LI$w#uzykjpgNBg^ literal 0 HcmV?d00001 diff --git a/Zway-Bot/Zway-Bot/bin/Release/Zway.dll b/Zway-Bot/Zway-Bot/bin/Release/Zway.dll new file mode 100644 index 0000000000000000000000000000000000000000..fc9ccf330af2abbba68e8e2c173e0d4309bdd504 GIT binary patch literal 49664 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 literal 0 HcmV?d00001 diff --git a/Zway-Bot/Zway-Bot/packages.config b/Zway-Bot/Zway-Bot/packages.config new file mode 100644 index 0000000..eb9ba23 --- /dev/null +++ b/Zway-Bot/Zway-Bot/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Zway/Zway.sln b/Zway/Zway.sln new file mode 100644 index 0000000..373e352 --- /dev/null +++ b/Zway/Zway.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.16 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Zway", "Zway\Zway.csproj", "{166258ED-CB3D-43F5-8E8D-3A993B64D022}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {166258ED-CB3D-43F5-8E8D-3A993B64D022}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {166258ED-CB3D-43F5-8E8D-3A993B64D022}.Debug|Any CPU.Build.0 = Debug|Any CPU + {166258ED-CB3D-43F5-8E8D-3A993B64D022}.Release|Any CPU.ActiveCfg = Release|Any CPU + {166258ED-CB3D-43F5-8E8D-3A993B64D022}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2F3A172A-4D52-4191-A84A-675D35B4A292} + EndGlobalSection +EndGlobal diff --git a/Zway/Zway/Devices/CommandClasses/Battery.cs b/Zway/Zway/Devices/CommandClasses/Battery.cs new file mode 100644 index 0000000..c7df38d --- /dev/null +++ b/Zway/Zway/Devices/CommandClasses/Battery.cs @@ -0,0 +1,61 @@ +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 { + /// + /// 128 = Battery + /// + public class Battery : ACommandClass { + + public Double Level { get; private set; } + + public override event UpdatedValue Update; + + public Battery(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + this.InitComplex(json); + } + + internal override void SetUpdate(JsonData json, Match match) { + Boolean success = false; + if (match.Groups[4].Value == ".data") { + if (json.Keys.Contains("last") && json["last"].Keys.Contains("value")) { + this.Level = Double.Parse(json["last"]["value"].ToString()); + success = true; + } + } else if (match.Groups[4].Value == ".data.last") { + if (json.Keys.Contains("value")) { + this.Level = Double.Parse(json["value"].ToString()); + success = true; + } + } else if (match.Groups[4].Value.StartsWith(".data.history.")) { + } else if (match.Groups[4].Value == ".data.lastChange") { + } else { + 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, this)); + } + } + + private void InitComplex(JsonData json) { + if (json.Keys.Contains("data") && json["data"].Keys.Contains("last") && json["data"]["last"].Keys.Contains("value")) { + this.Level = Double.Parse(json["data"]["last"]["value"].ToString()); + } + } + + public override String ToString() { + return "Battery " + this.Name + " [" + this.Id + "]: " + this.Level; + } + + public override Dictionary ToDictionary() { + return new Dictionary { + { "level", this.Level }, + }; + } + } +} diff --git a/Zway/Zway/Devices/CommandClasses/CentralScene.cs b/Zway/Zway/Devices/CommandClasses/CentralScene.cs new file mode 100644 index 0000000..db4764b --- /dev/null +++ b/Zway/Zway/Devices/CommandClasses/CentralScene.cs @@ -0,0 +1,86 @@ +using System; +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 : ACommandClass { + public override event UpdatedValue Update; + + public ReadOnlyDictionary> ValidScenesModes { get; private set; } + public Int32 Scene { get; private set; } + public Int32 Key { get; private set; } + + public Centralscene(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + this.ValidScenesModes = new ReadOnlyDictionary>(new Dictionary>()); + this.InitComplex(json); + } + + internal override void SetUpdate(JsonData json, Match match) { + if (match.Groups[4].Value == ".data.currentScene") { + if (json.Keys.Contains("value")) { + this.Scene = Int32.Parse(json["value"].ToString()); + } + } else if (match.Groups[4].Value == ".data.keyAttribute") { + if (json.Keys.Contains("value") && this.CheckSetUpdateTime(json)) { + this.Key = Int32.Parse(json["value"].ToString()); + this.Update?.Invoke(this, new DeviceUpdateEvent(new Tuple(this.Scene, this.Key), this.LastUpdate, this)); + } + } 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"]; + if(data.Keys.Contains("sceneSupportedKeyAttributesMask")) { + Dictionary> scenes = new Dictionary>(); + foreach (String item in data["sceneSupportedKeyAttributesMask"].Keys) { + if (Int32.TryParse(item, out Int32 mode) && + data["sceneSupportedKeyAttributesMask"][item].Keys.Contains("value") && + data["sceneSupportedKeyAttributesMask"][item]["value"].IsArray) { + JsonData values = data["sceneSupportedKeyAttributesMask"][item]["value"]; + List modes = new List(); + foreach (JsonData value in values) { + modes.Add(Int32.Parse(value.ToString())); + } + scenes.Add(mode, new ReadOnlyCollection(modes)); + } + } + this.ValidScenesModes = new ReadOnlyDictionary>(scenes); + if (data.Keys.Contains("currentScene") && + data["currentScene"].Keys.Contains("value") && + data["currentScene"]["value"] != null) { + this.Scene = Int32.Parse(data["currentScene"]["value"].ToString()); + } + if (data.Keys.Contains("keyAttribute") && + data["keyAttribute"].Keys.Contains("value") && + data["keyAttribute"]["value"] != null) { + this.Key = Int32.Parse(data["keyAttribute"]["value"].ToString()); + } + } + } + } + + public override String ToString() { + return "CentralScene " + this.Name + " [" + this.Id + "]: " + this.Scene+"-"+this.Key; + } + + internal override void Poll() => this.PollNone(); + + public override Dictionary ToDictionary() { + return new Dictionary { + { "scene", this.Scene }, + { "key", this.Key }, + }; + } + } +} diff --git a/Zway/Zway/Devices/CommandClasses/CommandClassSubs/Configurationsub.cs b/Zway/Zway/Devices/CommandClasses/CommandClassSubs/Configurationsub.cs new file mode 100644 index 0000000..fe83f28 --- /dev/null +++ b/Zway/Zway/Devices/CommandClasses/CommandClassSubs/Configurationsub.cs @@ -0,0 +1,69 @@ +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 { + class Configurationsub : ACommandClass { + public override event UpdatedValue Update; + private Int64 _level; + + public Int64 Level { + get { + return this._level; + } + set { + if (this.Size == 1 && Int16.TryParse(value.ToString(), out Int16 value16)) { + this.SetTriple(this.SensorId, value16, 1); + } else if(this.Size == 2 && Int32.TryParse(value.ToString(), out Int32 value32)) { + this.SetTriple(this.SensorId, value32, 2); + } else if(this.Size == 4) { + this.SetTriple(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) { + this.IsSub = true; + 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() => this.PollSub(); + + 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, this)); + } + } + + public override String ToString() { + return "Configuration " + this.Name + " [" + this.Id + "]: " + this.Level; + } + + public override Dictionary ToDictionary() { + return new Dictionary { + { "level", this.Level }, + { "size", this.Size }, + }; + } + } +} \ No newline at end of file diff --git a/Zway/Zway/Devices/CommandClasses/CommandClassSubs/MeterSub.cs b/Zway/Zway/Devices/CommandClasses/CommandClassSubs/MeterSub.cs new file mode 100644 index 0000000..a4aa3c2 --- /dev/null +++ b/Zway/Zway/Devices/CommandClasses/CommandClassSubs/MeterSub.cs @@ -0,0 +1,61 @@ +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 Metersub : ACommandClass { + public override event UpdatedValue Update; + + public String Type { get; private set; } + public Double Level { get; private set; } + public String Scale { get; private set; } + public Metersub(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + this.HasReset = true; + this.IsSub = true; + InitComplex(json); + } + + private void InitComplex(JsonData json) { + if (json.Keys.Contains("sensorTypeString") && + json["sensorTypeString"].Keys.Contains("value") && + json.Keys.Contains("val") && + json["val"].Keys.Contains("value") && + json.Keys.Contains("scaleString") && + json["scaleString"].Keys.Contains("value")) { + this.Type = json["sensorTypeString"]["value"].ToString(); + this.Level = Double.Parse(json["val"]["value"].ToString()); + this.Scale = json["scaleString"]["value"].ToString(); + } + } + + internal override void SetUpdate(JsonData json, Match match) { + if (json.Keys.Contains("val") && json["val"].Keys.Contains("value") && + json.Keys.Contains("sensorTypeString") && json["sensorTypeString"].Keys.Contains("value") && + json.Keys.Contains("scaleString") && json["scaleString"].Keys.Contains("value") && + this.CheckSetUpdateTime(json)) { + this.Level = Double.Parse(json["val"]["value"].ToString()); + this.Type = json["sensorTypeString"]["value"].ToString(); + this.Scale = json["scaleString"]["value"].ToString(); + this.Update?.Invoke(this, new DeviceUpdateEvent(new Tuple(this.Type, this.Scale, this.Level), this.LastUpdate, this)); + } + } + + public override String ToString() { + return "Meter " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.Level + "" + this.Scale; + } + + internal override void Poll() => this.PollNone(); + + public override Dictionary ToDictionary() { + return new Dictionary { + { "level", this.Level }, + { "type", this.Type }, + { "scale", this.Scale }, + }; + } + } +} \ No newline at end of file diff --git a/Zway/Zway/Devices/CommandClasses/CommandClassSubs/SensorMultilevelSub.cs b/Zway/Zway/Devices/CommandClasses/CommandClassSubs/SensorMultilevelSub.cs new file mode 100644 index 0000000..52001d0 --- /dev/null +++ b/Zway/Zway/Devices/CommandClasses/CommandClassSubs/SensorMultilevelSub.cs @@ -0,0 +1,61 @@ +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 Sensormultilevelsub : ACommandClass { + public override event UpdatedValue Update; + + public String Type { get; private set; } + public Double Level { get; private set; } + public String Scale { get; private set; } + + public Sensormultilevelsub(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("sensorTypeString") && + json["sensorTypeString"].Keys.Contains("value") && + json.Keys.Contains("val") && + json["val"].Keys.Contains("value") && + json.Keys.Contains("scaleString") && + json["scaleString"].Keys.Contains("value")) { + this.Type = json["sensorTypeString"]["value"].ToString(); + this.Level = Double.Parse(json["val"]["value"].ToString()); + this.Scale = json["scaleString"]["value"].ToString(); + } + } + + internal override void SetUpdate(JsonData json, Match match) { + if(json.Keys.Contains("val") && json["val"].Keys.Contains("value") && + json.Keys.Contains("sensorTypeString") && json["sensorTypeString"].Keys.Contains("value") && + json.Keys.Contains("scaleString") && json["scaleString"].Keys.Contains("value") && + this.CheckSetUpdateTime(json)) { + this.Level = Double.Parse(json["val"]["value"].ToString()); + this.Type = json["sensorTypeString"]["value"].ToString(); + this.Scale = json["scaleString"]["value"].ToString(); + this.Update?.Invoke(this, new DeviceUpdateEvent(new Tuple(this.Type, this.Scale, this.Level), this.LastUpdate, this)); + } + } + + public override String ToString() { + return "SensorMultilevel " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.Level + "" + this.Scale; + } + + internal override void Poll() => this.PollNone(); + + public override Dictionary ToDictionary() { + return new Dictionary { + { "level", this.Level }, + { "type", this.Type }, + { "scale", this.Scale }, + }; + } + } +} \ No newline at end of file diff --git a/Zway/Zway/Devices/CommandClasses/CommandClassSubs/ThermostatSetPointSub.cs b/Zway/Zway/Devices/CommandClasses/CommandClassSubs/ThermostatSetPointSub.cs new file mode 100644 index 0000000..85ec304 --- /dev/null +++ b/Zway/Zway/Devices/CommandClasses/CommandClassSubs/ThermostatSetPointSub.cs @@ -0,0 +1,94 @@ +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 { + class Thermostatsetpointsub : ACommandClass { + public override event UpdatedValue Update; + + private Double _level; + public Double Level { + get { + return this._level; + } + set { + if (!this.HasMinMax || (this.HasMinMax && value >= this.TempMin && value <= this.TempMax)) { + this.SetTuple(this.SensorId, (Double)Math.Round(value * 2, MidpointRounding.AwayFromZero) / 2); + } + } + } + public String Scale { get; private set; } + public Double TempMax { get; private set; } + public Double TempMin { get; private set; } + public Boolean HasMinMax { get; private set; } + public String Type { get; private set; } + + public Thermostatsetpointsub(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("modeName") && json["modeName"].Keys.Contains("value") && + json.Keys.Contains("val") && json["val"].Keys.Contains("value") && + json.Keys.Contains("deviceScaleString") && json["deviceScaleString"].Keys.Contains("value")) { + this.Type = json["modeName"]["value"].ToString(); + this._level = Double.Parse(json["val"]["value"].ToString()); + this.Scale = json["deviceScaleString"]["value"].ToString(); + } + if (json.Keys.Contains("min") && json["min"].Keys.Contains("value") && + json.Keys.Contains("max") && json["max"].Keys.Contains("value")) { + this.TempMin = Double.Parse(json["min"]["value"].ToString()); + this.TempMax = Double.Parse(json["max"]["value"].ToString()); + this.HasMinMax = true; + } else { + this.HasMinMax = false; + } + } + + internal override void SetUpdate(JsonData json, Match match) { + Boolean ret = false; + if (json.Keys.Contains("val") && json["val"].Keys.Contains("value") && + json.Keys.Contains("deviceScaleString") && json["deviceScaleString"].Keys.Contains("value") && + json.Keys.Contains("modeName") && json["modeName"].Keys.Contains("value")) { + this._level = Double.Parse(json["val"]["value"].ToString()); + this.Scale = json["deviceScaleString"]["value"].ToString(); + this.Type = json["modeName"]["value"].ToString(); + ret = true; + } + if (json.Keys.Contains("min") && json["val"].Keys.Contains("value") && + json.Keys.Contains("max") && json["max"].Keys.Contains("value")) { + this.TempMin = Double.Parse(json["min"]["value"].ToString()); + this.TempMax = Double.Parse(json["max"]["value"].ToString()); + this.HasMinMax = true; + ret = true; + } else { + this.HasMinMax = false; + } + if (ret && this.CheckSetUpdateTime(json)) { + this.Update?.Invoke(this, new DeviceUpdateEvent(new Tuple(this.Type, this.Scale, this.Level, this.TempMin, this.TempMax, this.HasMinMax), this.LastUpdate, this)); + } + } + + public override String ToString() { + return "ThermostatSetPoint " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.Level + "" + this.Scale + " [" + this.TempMin + "," + this.TempMax + "," + this.HasMinMax + "]"; + } + + internal override void Poll() => this.PollSub(); + + public override Dictionary ToDictionary() { + return new Dictionary { + { "level", this.Level }, + { "type", this.Type }, + { "scale", this.Scale }, + { "tempmax", this.TempMax }, + { "tempmin", this.TempMin }, + { "hasminmax", this.HasMinMax }, + }; + } + } +} \ No newline at end of file diff --git a/Zway/Zway/Devices/CommandClasses/Configuration.cs b/Zway/Zway/Devices/CommandClasses/Configuration.cs new file mode 100644 index 0000000..6410555 --- /dev/null +++ b/Zway/Zway/Devices/CommandClasses/Configuration.cs @@ -0,0 +1,62 @@ +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 : ACommandClass { + public override event UpdatedValue Update; + + public Configuration(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); + } + + 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() => this.PollPerSub(); + + public override Dictionary ToDictionary() => this.ToDictionarySub(); + } +} diff --git a/Zway/Zway/Devices/CommandClasses/Indicator.cs b/Zway/Zway/Devices/CommandClasses/Indicator.cs new file mode 100644 index 0000000..9cb15ab --- /dev/null +++ b/Zway/Zway/Devices/CommandClasses/Indicator.cs @@ -0,0 +1,57 @@ +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 Indicator : ACommandClass { + private Boolean _level; + + public override event UpdatedValue Update; + public Boolean Level { + get { + return this._level; + } + set { + this.SetInt(value ? 255 : 0); + } + } + + public Indicator(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("stat") && json["data"]["stat"].Keys.Contains("value")) { + this._level = Int32.Parse(json["data"]["stat"]["value"].ToString()) == 255; + } + } + + internal override void SetUpdate(JsonData json, Match match) { + if(match.Groups[4].Value == ".data.stat") { + if (json.Keys.Contains("value") && this.CheckSetUpdateTime(json)) { + this._level = Int32.Parse(json["value"].ToString()) == 255; + this.Update?.Invoke(this, new DeviceUpdateEvent(this.Level, this.LastUpdate, this)); + } + } else { + Helper.WriteError("Kenne in " + this.Name + " [" + this.Id + "] " + match.Groups[4].Value + " nicht!"); + } + } + + public override String ToString() { + return "Indicator " + this.Name + " [" + this.Id + "]: " + this.Level; + } + + public override Dictionary ToDictionary() { + return new Dictionary { + { "level", this.Level }, + }; + } + } +} diff --git a/Zway/Zway/Devices/CommandClasses/Meter.cs b/Zway/Zway/Devices/CommandClasses/Meter.cs new file mode 100644 index 0000000..9cb8115 --- /dev/null +++ b/Zway/Zway/Devices/CommandClasses/Meter.cs @@ -0,0 +1,61 @@ +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 Meter : ACommandClass { + public override event UpdatedValue Update; + + public Meter(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("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, this.Polling)); + } + } + this.Sub = new ReadOnlyDictionary(subs); + } + } + + internal override void Poll() => this.PollSubGlobal(); + + public override Dictionary ToDictionary() => this.ToDictionarySub(); + } +} diff --git a/Zway/Zway/Devices/CommandClasses/SensorMultilevel.cs b/Zway/Zway/Devices/CommandClasses/SensorMultilevel.cs new file mode 100644 index 0000000..53d974c --- /dev/null +++ b/Zway/Zway/Devices/CommandClasses/SensorMultilevel.cs @@ -0,0 +1,61 @@ +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 { + /// + /// 49 = SensorMultilevel + /// + public class Sensormultilevel : ACommandClass { + public override event UpdatedValue Update; + + public Sensormultilevel(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("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, this.Polling)); + } + } + this.Sub = new ReadOnlyDictionary(subs); + } + } + + internal override void Poll() => this.PollSubGlobal(); + + public override Dictionary ToDictionary() => this.ToDictionarySub(); + } +} diff --git a/Zway/Zway/Devices/CommandClasses/SwitchBinary.cs b/Zway/Zway/Devices/CommandClasses/SwitchBinary.cs new file mode 100644 index 0000000..a2d7dbb --- /dev/null +++ b/Zway/Zway/Devices/CommandClasses/SwitchBinary.cs @@ -0,0 +1,58 @@ +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 { + /// + /// 37 = SwitchBinary + /// + public class Switchbinary : ACommandClass { + private Boolean _level; + + public override event UpdatedValue Update; + + public Boolean Level { + get { + return this._level; + } + set { + this.SetInt(value ? 255 : 0); + } + } + + public Switchbinary(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + this.InitComplex(json); + } + + internal override void SetUpdate(JsonData json, Match match) { + if(match.Groups[4].Value == ".data.level") { + if (json.Keys.Contains("value") && json["value"].IsBoolean && this.CheckSetUpdateTime(json)) { + this._level = (Boolean)json["value"]; + this.Update?.Invoke(this, new DeviceUpdateEvent(this.Level, this.LastUpdate, this)); + } + } else { + Helper.WriteError("Kenne in " + this.Name + " [" + this.Id + "] " + match.Groups[4].Value + " nicht!"); + } + } + + 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.Id + "]: " + this.Level; + } + + public override Dictionary ToDictionary() { + return new Dictionary { + { "level", this.Level } + }; + } + } +} diff --git a/Zway/Zway/Devices/CommandClasses/SwitchMultilevel.cs b/Zway/Zway/Devices/CommandClasses/SwitchMultilevel.cs new file mode 100644 index 0000000..dcb3069 --- /dev/null +++ b/Zway/Zway/Devices/CommandClasses/SwitchMultilevel.cs @@ -0,0 +1,61 @@ +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 { + /// + /// 38 = SwitchMultilevel + /// + public class Switchmultilevel : ACommandClass { + private Int32 _level; + + public override event UpdatedValue Update; + + public Int32 Level { + get { + return this._level; + } + set { + if(value == 0 || (value > 0 && value <= 99) || value == 255) { + this.SetTuple(value, 0); + } + } + } + + public Switchmultilevel(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + this.InitComplex(json); + } + + internal override void SetUpdate(JsonData json, Match match) { + if(match.Groups[4].Value == ".data.level") { + if(json.Keys.Contains("value") && this.CheckSetUpdateTime(json)) { + this._level = Int32.Parse(json["value"].ToString()); + this.Update?.Invoke(this, new DeviceUpdateEvent(this.Level, this.LastUpdate, this)); + } + } else if (match.Groups[4].Value == ".data.prevLevel") { + } else { + Helper.WriteError("Kenne in " + this.Name + " [" + this.Id + "] " + match.Groups[4].Value + " nicht!"); + } + } + + 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.Id + "]: " + this.Level; + } + + public override Dictionary ToDictionary() { + return new Dictionary { + { "level", this.Level } + }; + } + } +} diff --git a/Zway/Zway/Devices/CommandClasses/ThermostatMode.cs b/Zway/Zway/Devices/CommandClasses/ThermostatMode.cs new file mode 100644 index 0000000..09f41ba --- /dev/null +++ b/Zway/Zway/Devices/CommandClasses/ThermostatMode.cs @@ -0,0 +1,80 @@ +using System; +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 : ACommandClass { + private Int32 _level; + + public override event UpdatedValue Update; + + public ReadOnlyDictionary ValidModes { get; private set; } + public Int32 Level { + get { return this._level; } + set { + if (this.ValidModes.ContainsKey(value)) { + this.SetInt(value); + } + } + } + + public Thermostatmode(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + this.ValidModes = new ReadOnlyDictionary(new Dictionary()); + this.InitComplex(json); + } + + internal override void SetUpdate(JsonData json, Match match) { + if(match.Groups[4].Value == ".data.mode") { + if(json.Keys.Contains("value") && this.CheckSetUpdateTime(json)) { + this._level = Int32.Parse(json["value"].ToString()); + this.Update?.Invoke(this, new DeviceUpdateEvent(this.Level, this.LastUpdate, this)); + } + } 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 modes = new Dictionary(); + foreach (String item in data.Keys) { + if (Int32.TryParse(item, out Int32 mode) && + data[item].Keys.Contains("modeName") && + data[item]["modeName"].Keys.Contains("value")) { + modes.Add(mode, data[item]["modeName"]["value"].ToString()); + } + } + this.ValidModes = new ReadOnlyDictionary(modes); + if (data.Keys.Contains("mode") && + data["mode"].Keys.Contains("value")) { + this._level = Int32.Parse(data["mode"]["value"].ToString()); + } + } + } + + public override String ToString() { + return "ThermostatMode " + this.Name + " [" + this.Id + "]: " + this.ValidModes[this.Level]; + } + + public override Dictionary ToDictionary() { + Dictionary modes = new Dictionary(); + foreach (KeyValuePair item in this.ValidModes) { + modes.Add(item.Key.ToString(), item.Value); + } + Dictionary json = new Dictionary { + { "level", this.Level }, + { "modes", modes } + }; + return json; + } + } +} diff --git a/Zway/Zway/Devices/CommandClasses/ThermostatSetPoint.cs b/Zway/Zway/Devices/CommandClasses/ThermostatSetPoint.cs new file mode 100644 index 0000000..eef0824 --- /dev/null +++ b/Zway/Zway/Devices/CommandClasses/ThermostatSetPoint.cs @@ -0,0 +1,61 @@ +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 { + /// + /// 67 = ThermostatSetPoint + /// + public class Thermostatsetpoint : ACommandClass { + public override event UpdatedValue Update; + + public Thermostatsetpoint(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("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, this.Polling)); + } + } + this.Sub = new ReadOnlyDictionary(subs); + } + } + + internal override void Poll() => this.PollPerSub(); + + public override Dictionary ToDictionary() => this.ToDictionarySub(); + } +} diff --git a/Zway/Zway/Devices/CommandClasses/Wakeup.cs b/Zway/Zway/Devices/CommandClasses/Wakeup.cs new file mode 100644 index 0000000..016c740 --- /dev/null +++ b/Zway/Zway/Devices/CommandClasses/Wakeup.cs @@ -0,0 +1,137 @@ +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 { + /// + /// 132 = Wakeup + /// + class Wakeup : ACommandClass { + private Int32 _interval; + private Int32 _againstNode; + + public override event UpdatedValue Update; + public Int32 Interval { + get { + return this._interval; + } + set { + if(value >= this.WakeupMin && value <= this.WakeupMax) { + this.SetTuple(value, this.AgainstNode); + } + } + } + public Int32 AgainstNode { get { + return this._againstNode; + } + set { + this.SetTuple(this.Interval, value); + } + } + public Int32 WakeupMin { get; private set; } + public Int32 WakeupMax { get; private set; } + public Int32 WakeupDefault { get; private set; } + public DateTime LastWakeup { get; private set; } + public DateTime LastSleep { get; private set; } + + public Wakeup(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")) { + JsonData data = json["data"]; + if(data.Keys.Contains("interval") && data["interval"].Keys.Contains("value")) { + this._interval = Int32.Parse(data["interval"]["value"].ToString()); + } + 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.WakeupMin = Int32.Parse(data["min"]["value"].ToString()); + } + if (data.Keys.Contains("max") && data["max"].Keys.Contains("value")) { + this.WakeupMax = Int32.Parse(data["max"]["value"].ToString()); + } + if (data.Keys.Contains("default") && data["default"].Keys.Contains("value")) { + this.WakeupDefault = Int32.Parse(data["default"]["value"].ToString()); + } + if (data.Keys.Contains("lastWakeup") && data["lastWakeup"].Keys.Contains("value")) { + this.LastWakeup = DateTimeOffset.FromUnixTimeSeconds(Int64.Parse(data["lastWakeup"]["value"].ToString())).DateTime.ToLocalTime(); + } + if (data.Keys.Contains("lastSleep") && data["lastSleep"].Keys.Contains("value")) { + this.LastSleep = DateTimeOffset.FromUnixTimeSeconds(Int64.Parse(data["lastSleep"]["value"].ToString())).DateTime.ToLocalTime(); + } + } + } + + internal override void SetUpdate(JsonData json, Match match) { + Boolean success = false; + if (match.Groups[4].Value == ".data.lastWakeup") { + if (json.Keys.Contains("value") && (json["value"].IsInt || json["value"].IsLong)) { + this.LastWakeup = DateTimeOffset.FromUnixTimeSeconds(Int64.Parse(json["value"].ToString())).DateTime.ToLocalTime(); + success = true; + } + } else if (match.Groups[4].Value == ".data.lastSleep") { + if (json.Keys.Contains("value") && (json["value"].IsInt || json["value"].IsLong)) { + this.LastSleep = DateTimeOffset.FromUnixTimeSeconds(Int64.Parse(json["value"].ToString())).DateTime.ToLocalTime(); + success = true; + } + } else if (match.Groups[4].Value == ".data") { + if (json.Keys.Contains("interval") && json["interval"].Keys.Contains("value")) { + this._interval = Int32.Parse(json["interval"]["value"].ToString()); + success = true; + } + if (json.Keys.Contains("nodeId") && json["nodeId"].Keys.Contains("value")) { + this._againstNode = Int32.Parse(json["nodeId"]["value"].ToString()); + success = true; + } + if (json.Keys.Contains("min") && json["min"].Keys.Contains("value")) { + this.WakeupMin = Int32.Parse(json["min"]["value"].ToString()); + success = true; + } + if (json.Keys.Contains("max") && json["max"].Keys.Contains("value")) { + this.WakeupMax = Int32.Parse(json["max"]["value"].ToString()); + success = true; + } + if (json.Keys.Contains("default") && json["default"].Keys.Contains("value")) { + this.WakeupDefault = Int32.Parse(json["default"]["value"].ToString()); + success = true; + } + if (json.Keys.Contains("lastWakeup") && json["lastWakeup"].Keys.Contains("value")) { + this.LastWakeup = DateTimeOffset.FromUnixTimeSeconds(Int64.Parse(json["lastWakeup"]["value"].ToString())).DateTime.ToLocalTime(); + success = true; + } + if (json.Keys.Contains("lastSleep") && json["lastSleep"].Keys.Contains("value")) { + this.LastSleep = DateTimeOffset.FromUnixTimeSeconds(Int64.Parse(json["lastSleep"]["value"].ToString())).DateTime.ToLocalTime(); + success = true; + } + } else { + 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, this)); + } + } + + public override String ToString() { + return "Wakeup " + this.Name + " [" + this.Id + "]: " + this.LastWakeup + "-" + this.LastSleep + " " + this.Interval + " [" + this.WakeupMin + "," + this.WakeupMax + "," + this.WakeupDefault + "," + this.AgainstNode + "]"; + } + + public override Dictionary ToDictionary() { + return new Dictionary { + {"interval", this.Interval }, + {"againstnode", this.AgainstNode }, + { "wakeupmin", this.WakeupMin }, + { "wakeupmax", this.WakeupMax }, + { "wakeupdefault", this.WakeupDefault }, + { "lastwakeup", this.LastWakeup.ToString() }, + { "lastsleep", this.LastSleep.ToString() } + }; + } + } +} diff --git a/Zway/Zway/Devices/Device.cs b/Zway/Zway/Devices/Device.cs new file mode 100644 index 0000000..2a37a08 --- /dev/null +++ b/Zway/Zway/Devices/Device.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Text.RegularExpressions; +using BlubbFish.IoT.Zway.Events; +using BlubbFish.IoT.Zway.lib; +using LitJson; + +namespace BlubbFish.IoT.Zway.Devices { + 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 ReadOnlyDictionary Instances { get; private set; } + public DateTime LastUpdate { get; private set; } + + private Device(JsonData json, Tuple id, HttpConnection http, Boolean polling) { + this.Id = id.Item1; + 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 { + this.Name = "Unknown"; + } + foreach (KeyValuePair item in this.Instances) { + item.Value.Update += this.InstanceUpdate; + } + } + + protected Boolean CheckSetUpdateTime(JsonData json) { + if (json.Keys.Contains("updateTime") && (json["updateTime"].IsInt || json["updateTime"].IsLong)) { + DateTime newdate = DateTimeOffset.FromUnixTimeSeconds(Int64.Parse(json["updateTime"].ToString())).ToLocalTime().DateTime; + if (newdate > this.LastUpdate) { + this.LastUpdate = newdate; + return true; + } else { + return false; + } + } else { + return true; + } + } + + private void InstanceUpdate(Object sender, DeviceUpdateEvent e) { + this.Update?.Invoke(this, e); + } + + 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, Boolean polling) { + if(json.Keys.Contains("instances") && + json["instances"].Count > 0 && + json.Keys.Contains("data") && id.Item1 != 1) { + return new Device(json, id, http, polling); + } + return null; + } + + public override String ToString() { + 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)); + } + } + } + + internal void Poll() { + foreach (KeyValuePair item in this.Instances) { + item.Value.Poll(); + } + } + } +} diff --git a/Zway/Zway/Devices/Instance.cs b/Zway/Zway/Devices/Instance.cs new file mode 100644 index 0000000..b0f1f02 --- /dev/null +++ b/Zway/Zway/Devices/Instance.cs @@ -0,0 +1,78 @@ +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.Interfaces; +using BlubbFish.IoT.Zway.lib; +using LitJson; + +namespace BlubbFish.IoT.Zway.Devices { + public class Instance { + private DateTime nextwakeup; + private Boolean polling; + + public delegate void UpdatedInstance(Object sender, DeviceUpdateEvent e); + public event UpdatedInstance Update; + + public Int32 DeviceId { get; } + public Int32 InstanceId { get; } + public ReadOnlyDictionary CommandClasses { get; private set; } + + 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; + } + this.MakePolltimer(); + } + + private void MakePolltimer() { + if(this.CommandClasses.ContainsKey(ACommandClass.Classes.Wakeup)) { + this.nextwakeup = ((Wakeup)this.CommandClasses[ACommandClass.Classes.Wakeup]).LastWakeup.AddSeconds(((Wakeup)this.CommandClasses[ACommandClass.Classes.Wakeup]).Interval).AddSeconds(-20); + } else { + this.nextwakeup = DateTime.Now.AddSeconds(60); + } + } + + private void ClassUpdate(Object sender, DeviceUpdateEvent e) { + this.Update?.Invoke(this, e); + } + + private void CreateInstances(JsonData json, HttpConnection http) { + Dictionary commands = new Dictionary(); + foreach (String commandid in json.Keys) { + ACommandClass c = ACommandClass.CreateInstance(json[commandid], new Tuple(this.DeviceId, this.InstanceId, (ACommandClass.Classes)Int32.Parse(commandid)), http, this.polling); + if (c != null) { + commands.Add((ACommandClass.Classes)Int32.Parse(commandid), c); + } + } + this.CommandClasses = new ReadOnlyDictionary(commands); + } + + 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, polling); + } + return null; + } + + public override String ToString() { + return "Instance: " + this.DeviceId + "-" + this.InstanceId + " [" + this.CommandClasses.Count + "]"; + } + + internal void Poll() { + if(DateTime.Now > this.nextwakeup) { + this.MakePolltimer(); + foreach (KeyValuePair item in this.CommandClasses) { + item.Value.Poll(); + } + } + } + } +} diff --git a/Zway/Zway/Events/DeviceUpdateEvent.cs b/Zway/Zway/Events/DeviceUpdateEvent.cs new file mode 100644 index 0000000..78c5938 --- /dev/null +++ b/Zway/Zway/Events/DeviceUpdateEvent.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BlubbFish.IoT.Zway.Events { + public class DeviceUpdateEvent : EventArgs { + + public DeviceUpdateEvent() { + } + + public DeviceUpdateEvent(Double value, DateTime time, Object parent) { + this.GetDouble = value; + this.UpdateTime = time; + this.Parent = parent; + } + + public DeviceUpdateEvent(Boolean value, DateTime time, Object parent) { + this.GetBoolean = value; + this.UpdateTime = time; + this.Parent = parent; + } + + public DeviceUpdateEvent(DateTime value, DateTime time, Object parent) { + this.GetDate = value; + this.UpdateTime = time; + this.Parent = parent; + } + + public DeviceUpdateEvent(Tuple value, DateTime time, Object parent) { + this.GetStringStringDoubleTuple = value; + this.UpdateTime = time; + this.Parent = parent; + } + public DeviceUpdateEvent(Tuple value, DateTime time, Object parent) { + this.GetStringStringDoubleDoubleDoubleDoubleBooleanTuple = value; + this.UpdateTime = time; + this.Parent = parent; + } + + public DeviceUpdateEvent(Tuple value, DateTime time, Object parent) { + this.GetIntegerTuple = value; + this.UpdateTime = time; + this.Parent = parent; + } + + public DeviceUpdateEvent(Tuple value, DateTime time, Object parent) { + this.GetLongIntegerTuple = value; + this.UpdateTime = time; + this.Parent = parent; + } + + public Double GetDouble { get; } + public DateTime GetDate { get; } + public Tuple GetStringStringDoubleTuple { get; } + public Tuple GetStringStringDoubleDoubleDoubleDoubleBooleanTuple { get; } + public Tuple GetLongIntegerTuple { get; } + public DateTime UpdateTime { get; } + public Object Parent { get; private set; } + public Boolean GetBoolean { get; } + public Tuple GetIntegerTuple { get; } + } +} \ No newline at end of file diff --git a/Zway/Zway/Exceptions/ZwayExceptions.cs b/Zway/Zway/Exceptions/ZwayExceptions.cs new file mode 100644 index 0000000..9c15199 --- /dev/null +++ b/Zway/Zway/Exceptions/ZwayExceptions.cs @@ -0,0 +1,12 @@ +using System; +using System.Runtime.Serialization; + +namespace BlubbFish.IoT.Zway.Exceptions { + [Serializable] + public class ConnectionException : Exception { + public ConnectionException() { } + public ConnectionException(String message) : base(message) { } + public ConnectionException(String message, Exception innerException) : base(message, innerException) { } + protected ConnectionException(SerializationInfo info, StreamingContext context) : base(info, context) { } + } +} diff --git a/Zway/Zway/Interfaces/ACommandClass.cs b/Zway/Zway/Interfaces/ACommandClass.cs new file mode 100644 index 0000000..05cb788 --- /dev/null +++ b/Zway/Zway/Interfaces/ACommandClass.cs @@ -0,0 +1,233 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Text.RegularExpressions; +using BlubbFish.IoT.Zway.Events; +using BlubbFish.IoT.Zway.lib; +using LitJson; + +namespace BlubbFish.IoT.Zway.Interfaces { + public abstract class ACommandClass { + protected HttpConnection http; + + public delegate void UpdatedValue(Object sender, DeviceUpdateEvent e); + public abstract event UpdatedValue Update; + protected enum IgnoredClasses : Int32 { + Basic = 32, + ControllerReplication = 33, + ApplicationStatus = 34, + SensorBinary = 48, + SwitchColor = 51, + MeterPulse = 53, + MultiChannel = 96, + Alarm = 113, + ManufacturerSpecific = 114, + PowerLevel = 115, + Protection = 117, + NodeNaming = 119, + FirmwareUpdate = 122, + Association = 133, + Version = 134, + MultiChannelAssociation = 142, + MultiCmd = 143 + } + + public enum Classes : Int32 { + SwitchBinary = 37, + SwitchMultilevel = 38, + SensorMultilevel = 49, + Meter = 50, + ThermostatMode = 64, + ThermostatSetPoint = 67, + CentralScene = 91, + Configuration = 112, + Battery = 128, + Wakeup = 132, + Indicator = 135 + } + + public Int32 DeviceId { get; } + public Int32 Instance { get; } + public Classes Commandclass { get; } + public String Id { get; } + public Int32 SensorId { get; } + public DateTime LastUpdate { get; protected set; } + public String Name { get; } + public Boolean Polling { get; set; } + public Boolean PollOnce { get; set; } + public ReadOnlyDictionary Sub { get; protected set; } + public Boolean HasSub { get; protected set; } + public Boolean IsSub { get; protected set; } + public Boolean HasReset { get; protected set; } + + #region Constructor + + protected ACommandClass(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.LastUpdate = DateTime.Now; + this.Polling = polling; + this.HasSub = false; + this.HasReset = false; + this.IsSub = false; + this.Id = this.DeviceId + "-" + this.Instance + "-" + (Int32)this.Commandclass + "-" + this.SensorId; + if (ZwayController.namelist.ContainsKey(this.Id)) { + this.Name = ZwayController.namelist[this.Id]; + } + } + + protected ACommandClass(JsonData json, Tuple id, HttpConnection http, Boolean polling) { + this.DeviceId = id.Item1; + this.Instance = id.Item2; + this.Commandclass = id.Item3; + this.http = http; + this.LastUpdate = DateTime.Now; + this.Polling = polling; + this.HasSub = false; + this.HasReset = false; + this.IsSub = false; + this.Id = this.DeviceId + "-" + this.Instance + "-" + (Int32)this.Commandclass; + if (ZwayController.namelist.ContainsKey(this.Id)) { + this.Name = ZwayController.namelist[this.Id]; + } + } + + internal static ACommandClass CreateInstance(JsonData json, Tuple id, HttpConnection http, Boolean polling) { + if (json.Keys.Contains("name") && + json.Keys.Contains("data") && + json["data"].Keys.Contains("supported") && + json["data"]["supported"].Keys.Contains("value") && + Boolean.Parse(json["data"]["supported"]["value"].ToString()) && + !Enum.IsDefined(typeof(IgnoredClasses), (Int32)id.Item3) && Enum.IsDefined(typeof(Classes), id.Item3)) { + String name = id.Item3.ToString(); + String objectName = "BlubbFish.IoT.Zway.Devices.CommandClasses." + name[0].ToString().ToUpper() + name.Substring(1).ToLower(); + return GetInstanceConcrete(objectName, json, http, id, polling); + } + if (!Enum.IsDefined(typeof(IgnoredClasses), (Int32)id.Item3) && !Enum.IsDefined(typeof(Classes), id.Item3)) { + Helper.WriteError("CommandClass " + id.Item3 + " not exist."); + } + return null; + } + + private static ACommandClass GetInstanceConcrete(String objectName, JsonData json, HttpConnection http, Tuple id, Boolean polling) { + Type t = null; + try { + t = Type.GetType(objectName, true); + } catch (TypeLoadException) { + Console.Error.WriteLine("Konnte Type " + objectName + " nicht laden!"); + return null; + } + return (ACommandClass)t.GetConstructor(new Type[] { typeof(JsonData), typeof(Tuple), typeof(HttpConnection), typeof(Boolean) }).Invoke(new Object[] { json, id, http, polling }); + } + + #endregion + + #region Polling + + internal virtual void Poll() { + if (this.Polling || this.PollOnce) { + this.PollOnce = false; + this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + ((Int32)this.Commandclass).ToString() + "].Get()"); + } + } + + protected void PollNone() { + this.PollOnce = false; + } + + protected void PollSub() { + if (this.Polling || this.PollOnce) { + this.PollOnce = false; + this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + ((Int32)this.Commandclass).ToString() + "].Get(" + this.SensorId + ")"); + } + } + + protected void PollPerSub() { + foreach (KeyValuePair item in this.Sub) { + item.Value.Poll(); + } + } + + protected void PollSubGlobal() { + Boolean poll = false; + foreach (KeyValuePair item in this.Sub) { + if (item.Value.Polling) { + poll = true; + break; + } + } + if (poll) { + this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + ((Int32)this.Commandclass).ToString() + "].Get()"); + } + } + + #endregion + + #region SetValues + + protected void SetInt(Int32 value) { + this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + ((Int32)this.Commandclass).ToString() + "].Set(" + value + ")"); + } + + protected void SetTuple(Double value1, Double value2) { + this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + ((Int32)this.Commandclass).ToString() + "].Set(" + value1 + "," + value2 + ")"); + } + + protected void SetTriple(Double v1, Double v2, Double v3) { + this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + ((Int32)this.Commandclass).ToString() + "].Set(" + v1 + "," + v2 + "," + v3 + ")"); + } + + protected Boolean CheckSetUpdateTime(JsonData json) { + if (json.Keys.Contains("updateTime") && (json["updateTime"].IsInt || json["updateTime"].IsLong)) { + DateTime newdate = DateTimeOffset.FromUnixTimeSeconds(Int64.Parse(json["updateTime"].ToString())).ToLocalTime().DateTime; + if (newdate > this.LastUpdate) { + this.LastUpdate = newdate; + return true; + } else { + return false; + } + } else { + return true; + } + } + + public virtual void Reset() { + if (this.HasReset) { + this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + ((Int32)this.Commandclass).ToString() + "].Reset()"); + } + } + + #endregion + + #region Output + + public String MqttTopic() { + return this.DeviceId + "/" + this.Instance + "/" + ((Int32)this.Commandclass).ToString() + (this.IsSub ? "/" + this.SensorId : ""); + } + + public String ToJson() { + Dictionary json = this.ToDictionary(); + json.Add("date", this.LastUpdate.ToString()); + json.Add("name", this.Name); + json.Add("class", this.Commandclass.ToString()); + return JsonMapper.ToJson(json); + } + + public abstract Dictionary ToDictionary(); + + protected Dictionary ToDictionarySub() { + Dictionary json = new Dictionary(); + foreach (KeyValuePair item in this.Sub) { + json.Add(item.Key.ToString(), item.Value.ToDictionary()); + } + return json; + } + + #endregion + + internal abstract void SetUpdate(JsonData json, Match match); + } +} diff --git a/Zway/Zway/Properties/AssemblyInfo.cs b/Zway/Zway/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a4e2ce0 --- /dev/null +++ b/Zway/Zway/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die einer Assembly zugeordnet sind. +[assembly: AssemblyTitle("Zway")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Zway")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly +// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von +// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("166258ed-cb3d-43f5-8e8d-3a993b64d022")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +// indem Sie "*" wie unten gezeigt eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.3.2.0")] +[assembly: AssemblyFileVersion("1.3.2.0")] diff --git a/Zway/Zway/Zway.csproj b/Zway/Zway/Zway.csproj new file mode 100644 index 0000000..6da4ab8 --- /dev/null +++ b/Zway/Zway/Zway.csproj @@ -0,0 +1,76 @@ + + + + + Debug + AnyCPU + {166258ED-CB3D-43F5-8E8D-3A993B64D022} + Library + Properties + BlubbFish.IoT.Zway + Zway + v4.6.1 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\IoT-Bot\packages\LitJson.0.9.0\lib\LitJson.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Zway/Zway/ZwayController.cs b/Zway/Zway/ZwayController.cs new file mode 100644 index 0000000..00467ce --- /dev/null +++ b/Zway/Zway/ZwayController.cs @@ -0,0 +1,193 @@ +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 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 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, Dictionary names, Boolean enablePoll = true) { + namelist = new ReadOnlyDictionary(names); + this.polling = enablePoll; + this.Connect(settings["server"], settings["user"], settings["pass"]); + } + + private void Connect(String server, String user, String pass) { + this.http = new HttpConnection(server, user, pass); + CultureInfo info = new CultureInfo("de-DE"); + info.NumberFormat.NumberDecimalSeparator = "."; + CultureInfo.DefaultThreadCurrentCulture = info; + CultureInfo.DefaultThreadCurrentUICulture = info; + Thread.CurrentThread.CurrentCulture = info; + Thread.CurrentThread.CurrentUICulture = info; + 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) { + item.Value.Update += this.DeviceUpdate; + } + } + + private void DeviceUpdate(Object sender, DeviceUpdateEvent e) { + this.Update?.Invoke(sender, e); + } + + private void Poll() { + CultureInfo info = new CultureInfo("de-DE"); + info.NumberFormat.NumberDecimalSeparator = "."; + CultureInfo.DefaultThreadCurrentCulture = info; + CultureInfo.DefaultThreadCurrentUICulture = info; + Thread.CurrentThread.CurrentCulture = info; + Thread.CurrentThread.CurrentUICulture = info; + while(true) { + foreach (KeyValuePair item in this.Devices) { + item.Value.Poll(); + } + Thread.Sleep(1000); + } + } + + public ACommandClass GetCommandClass(String id) { + String[] addr = id.Split('-'); + if (addr.Length == 3 || addr.Length == 4) { + return this.GetCommandClass(Int32.Parse(addr[0]), Int32.Parse(addr[1]), (ACommandClass.Classes)Int32.Parse(addr[2]), (addr.Length == 4 ? Int32.Parse(addr[3]) : -1)); + } + return null; + } + + public ACommandClass GetCommandClass(Int32 deviceid, Int32 instanceid, ACommandClass.Classes classid, Int32 subcid = -1) { + if(this.Devices.ContainsKey(deviceid) && this.Devices[deviceid].Instances.ContainsKey(instanceid) && this.Devices[deviceid].Instances[instanceid].CommandClasses.ContainsKey(classid)) { + ACommandClass commandclass = this.Devices[deviceid].Instances[instanceid].CommandClasses[classid]; + if(subcid == -1) { + return commandclass; + } + if (commandclass != null) { + if(commandclass.HasSub) { + if(commandclass.Sub.ContainsKey(subcid)) { + return commandclass.Sub[subcid]; + } + } + } + } + return null; + } + + private void Updater() { + CultureInfo info = new CultureInfo("de-DE"); + info.NumberFormat.NumberDecimalSeparator = "."; + CultureInfo.DefaultThreadCurrentCulture = info; + CultureInfo.DefaultThreadCurrentUICulture = info; + Thread.CurrentThread.CurrentCulture = info; + Thread.CurrentThread.CurrentUICulture = info; + while (true) { + Int64 date = ((DateTimeOffset)DateTime.Now.AddSeconds(-2)).ToUnixTimeSeconds(); + JsonData notifications = this.http.GetJson("ZWave.zway/Data/"+date); + foreach (String item in notifications.Keys) { + Match match = new Regex("^devices\\.([0-9]+)\\.instances\\.([0-9]+)\\.commandClasses\\.([0-9]+)(\\.data\\.([0-9]+)|\\.data\\.[a-z].*|\\.data)$", RegexOptions.IgnoreCase).Match(item); + if(match.Success) { + Int32 deviceid = Int32.Parse(match.Groups[1].Value); + Int32 instanceid = Int32.Parse(match.Groups[2].Value); + ACommandClass.Classes commandid = (ACommandClass.Classes)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); + } + } /*else { + if(item.StartsWith("controller.")) { } + else if(item == "updateTime") { } + else { + match = new Regex("^devices\\.([0-9]+)\\.(data.*)", RegexOptions.IgnoreCase).Match(item); + if(!match.Success) { + + } + } + }*/ + 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); + } + } + } + Thread.Sleep(1500); + } + } + + private void CreateDevices(JsonData json) { + Dictionary devices = new Dictionary(); + foreach (String deviceid in json.Keys) { + 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 Dictionary GetCommandClasses(ACommandClass.Classes classes) { + Dictionary ret = new Dictionary(); + foreach (KeyValuePair device in this.Devices) { + foreach (KeyValuePair instance in device.Value.Instances) { + foreach (KeyValuePair commandclass in instance.Value.CommandClasses) { + if (commandclass.Key == classes) { + ret.Add(commandclass.Value.Id, commandclass.Value); + } + } + } + } + return ret; + } + + #region IDisposable Support + private Boolean disposedValue = false; + + protected virtual void Dispose(Boolean disposing) { + if (!this.disposedValue) { + if (disposing) { + this.updatethread.Abort(); + this.pollthread.Abort(); + } + this.updatethread = null; + this.pollthread = null; + this.Devices = null; + this.disposedValue = true; + } + } + + ~ZwayController() { + Dispose(false); + } + + public void Dispose() { + Dispose(true); + GC.SuppressFinalize(this); + } + #endregion + } +} diff --git a/Zway/Zway/bin/Release/LitJson.dll b/Zway/Zway/bin/Release/LitJson.dll new file mode 100644 index 0000000000000000000000000000000000000000..f00f11f11441dcc457ea0684ac462e466bf8df54 GIT binary patch literal 54272 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 literal 0 HcmV?d00001 diff --git a/Zway/Zway/bin/Release/Zway.dll b/Zway/Zway/bin/Release/Zway.dll new file mode 100644 index 0000000000000000000000000000000000000000..fc9ccf330af2abbba68e8e2c173e0d4309bdd504 GIT binary patch literal 49664 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 literal 0 HcmV?d00001 diff --git a/Zway/Zway/lib/Helper.cs b/Zway/Zway/lib/Helper.cs new file mode 100644 index 0000000..cf6df21 --- /dev/null +++ b/Zway/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/Zway/lib/HttpClient.cs b/Zway/Zway/lib/HttpClient.cs new file mode 100644 index 0000000..72569cc --- /dev/null +++ b/Zway/Zway/lib/HttpClient.cs @@ -0,0 +1,65 @@ +using System; +using System.IO; +using System.Net; +using System.Text; +using LitJson; + +namespace BlubbFish.IoT.Zway.lib { + public class HttpConnection { + private String auth; + private String server; + private Object getLock = new Object(); + + internal HttpConnection(String server, String user, String pass) { + this.auth = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(user + ":" + pass)); + this.server = "http://" + server + ":8083/"; + this.Init(); + } + + private void Init() { + this.GetString("ZAutomation/api/v1/status"); + } + + internal JsonData GetJson(String v) { + String text = this.GetString(v); + if(text == null) { + return new JsonData(); + } + try { + return JsonMapper.ToObject(text); + } catch(Exception) { + return new JsonData(); + } + } + + internal void GetVoid(String v) { + this.GetString(v, false); + } + + private String GetString(String v, Boolean withoutput = true) { + String ret = null; + lock (this.getLock) { + HttpWebRequest request = WebRequest.CreateHttp(this.server + v); + request.Timeout = 5000; + request.Headers.Add(HttpRequestHeader.Authorization, this.auth); + try { + using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { + if (response.StatusCode == HttpStatusCode.Unauthorized) { + Console.Error.WriteLine("Benutzer oder Passwort falsch!"); + throw new Exceptions.ConnectionException("Benutzer oder Passwort falsch!"); + } + if (withoutput) { + StreamReader reader = new StreamReader(response.GetResponseStream()); + ret = reader.ReadToEnd(); + } + } + } catch (Exception e) { + 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; + } + } +} diff --git a/Zway/Zway/packages.config b/Zway/Zway/packages.config new file mode 100644 index 0000000..eb9ba23 --- /dev/null +++ b/Zway/Zway/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file