From f4aa69003822c9ae5505925b14723d95916c1d68 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Sat, 15 Jan 2022 23:18:39 +0100 Subject: [PATCH] [1.6.0] Refactoring is the key --- CHANGELOG.md | 176 ++++++++++++++++ CONTRIBUTING.md | 92 ++++++++ LICENSE | 165 +++++++++++++++ README.md | 50 +++++ Zway/Devices/CommandClasses/Alarm.cs | 77 ++++--- Zway/Devices/CommandClasses/AlarmSensor.cs | 17 +- Zway/Devices/CommandClasses/Battery.cs | 26 +-- Zway/Devices/CommandClasses/CentralScene.cs | 23 +- .../CommandClassSubs/Alarmsensorsub.cs | 21 +- .../CommandClassSubs/Configurationsub.cs | 39 ++-- .../CommandClassSubs/MeterSub.cs | 25 ++- .../SceneControllerConfSub.cs | 27 ++- .../CommandClassSubs/SensorBinarySub.cs | 35 ++-- .../CommandClassSubs/SensorMultilevelSub.cs | 26 ++- .../CommandClassSubs/ThermostatSetPointSub.cs | 44 ++-- Zway/Devices/CommandClasses/Configuration.cs | 17 +- Zway/Devices/CommandClasses/Indicator.cs | 38 ++-- Zway/Devices/CommandClasses/Meter.cs | 17 +- .../CommandClasses/SceneControllerConf.cs | 17 +- Zway/Devices/CommandClasses/SensorBinary.cs | 17 +- .../CommandClasses/SensorMultilevel.cs | 17 +- Zway/Devices/CommandClasses/SwitchBinary.cs | 44 ++-- .../CommandClasses/SwitchMultilevel.cs | 34 ++- Zway/Devices/CommandClasses/ThermostatMode.cs | 19 +- .../CommandClasses/ThermostatSetPoint.cs | 17 +- Zway/Devices/CommandClasses/Wakeup.cs | 63 +++--- Zway/Devices/Device.cs | 45 ++-- Zway/Devices/Instance.cs | 45 ++-- Zway/Events/DeviceUpdateEvent.cs | 4 - Zway/Interfaces/ACommandClass.cs | 102 ++++----- Zway/Zway.csproj | 59 +++--- Zway/ZwayController.cs | 196 +++--------------- Zway/lib/Helper.cs | 15 -- Zway/lib/HttpClient.cs | 88 -------- Zway/lib/Zway/HttpClient.cs | 61 ++++++ Zway/lib/Zway/Zway.cs | 169 +++++++++++++++ Zway/lib/ZwayBoard.cs | 57 +++++ 37 files changed, 1203 insertions(+), 781 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 README.md delete mode 100644 Zway/lib/Helper.cs delete mode 100644 Zway/lib/HttpClient.cs create mode 100644 Zway/lib/Zway/HttpClient.cs create mode 100644 Zway/lib/Zway/Zway.cs create mode 100644 Zway/lib/ZwayBoard.cs diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..90fdabf --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,176 @@ +# Changelog + +## 1.6.0 - 2022-01-15 - Refactoring is the key +### New Features +* Using C# 9 Language features now +* Add Readme, Contribute and Changelog +### Bugfixes +### Changes +* Modify the HttpClient lib, as it now using the Utility one +* Split the ZwayController and move parts to the zway Subclass +* Rewrite the names.ini so that only the commandclass is used for names +* Codingstyle +* Remove Binarys from code +* Move project to netcore +* Remove the HelperClass and use the one from Utils + +## 1.5.1 - 2018-10-29 - Tiny fix for nullpointer exception +### New Features +### Bugfixes +* Avoid nullpointerexception +### Changes + +## 1.5.0 - 2018-09-29 - Throw Exception if 3 times failed to connect to Raspberry server, add 3 new commandlcasses to IgnoredClasses +### New Features +* Add classes to IgnoreClasses +* If a request failed, try again 3 times and then throw the exception to the next level +* Catch all data from the time of the last request and calculate backwards. +### Bugfixes +* Try to fix connectionlost with HttpConnection Class +### Changes +* Codingstyle + +## 1.4.4 - 2018-06-02 - Ignore Inclusioncontroller +### New Features +* Add classes to IgnoreClasses +### Bugfixes +### Changes + +## 1.4.3 - 2018-05-12 - Fixing Issue with Math.Abs(l) +### New Features +* Add classes to IgnoreClasses +### Bugfixes +* Using Math.Abs correctly +### Changes + +## 1.4.2.0 - 2018-05-10 - Some sensors make wrong measurements near 0 not exactly 0, so ABS(value) >= 0.1 is alse false +### New Features +* SensorMultilevelSub now can return Lux in Senml +* Add classes to IgnoreClasses +### Bugfixes +* Fixing Senml topic +* fixing filter so its not exactly needs 0 for temperatur +### Changes + +## 1.4.1.0 - 2018-05-07 - fixing Senml topics and data +### New Features +### Bugfixes +* Fixing Senml topic +### Changes + +## 1.4.0.0 - 2018-05-03 - Create Senml Messages for Linksmart +### New Features +* Add classes to IgnoreClasses +* Add Senml output +### Bugfixes +### Changes +* Refactoring + +## 1.3.6.0 - 2018-01-01 - Better levelcheck and Alarmsensor added +### New Features +* Add CommandClasses AlarmSensor +* Remove classes from IgnoreClasses +* Add a filter if temperature is near zero and drops rapetly to exact 0 +### Bugfixes +### Changes + +## 1.3.5.3 - 2017-12-25 - Change Level to numeric and create State for Bollean values, because telegraf only parse numeric +### New Features +* Boolean levels also returned as Int in Json +### Bugfixes +### Changes + +## 1.3.5.2 - 2017-12-24 - Check to avoid megapeaks in data now also for temperature +### New Features +* Add a filter for temperature also (if > 50 or < -20 its ignored) +### Bugfixes +### Changes + +## 1.3.5.1 - 2017-12-23 - Check to avoid megapeaks in Data +### New Features +* Add a filter for to high values (if W < 3660 its ignored) +### Bugfixes +### Changes + +## 1.3.5.0 - 2017-12-22 - Add Alarm and SceneControllerConf +### New Features +* Add CommandClasses Alarm, SceneControllerConf +* Add classes to IgnoreClasses +### Bugfixes +* Avoid nullpointer Exception +### Changes + +## 1.3.4.1 - 2017-12-21 - SensorBinary and Fixing +### New Features +* Add CommandClasses SensorBinary +### Bugfixes +### Changes +* Json Names are now with a Capital letter + +## 1.3.4.0 - 2017-12-19 - Fixing Json Names +### New Features +### Bugfixes +### Changes +* Json Names are now with a Capital letter + +## 1.3.3.0 - 2017-12-19 - fixing polling once bug +### New Features +### Bugfixes +* Poll Once was not used +### Changes + +## 1.3.2.0 - 2017-12-18 - Forgot some settings, now configuration setting also works again +### New Features +### Bugfixes +* Using Abstract Methods not the Api directly +### Changes +* Using Int -> Double Cast + +## 1.3.1.0 - 2017-12-17 - Tiny fix for mqtt +### New Features +### Bugfixes +* Using Double instead of Single +### Changes + +## 1.3.0.0 - 2017-12-17 - Simpler CommandClass +### New Features +* Using ACommandClass +### Bugfixes +### Changes +* Refactoring CommandClass, Merge CommandClass and CommandClassSub and Put parts to abstract ACommandClass. +* Delete ICommandClass + +# 1.2.0.0 - 2017-12-06 - F4G Faker +### New Features +* When trigger the update event, pass the class itself also +### Bugfixes +### Changes + +# 1.1.2.0 - 2017-12-03 - Tiny Fix +### New Features +### Bugfixes +* Meter Class public, so it cann be accessed +### Changes + +# 1.1.1.0 - 2017-11-25 - Massive improvement +### New Features +* Create Interface CommandClass +* Add CommandClasses Configuration +### Bugfixes +### Changes +* Refactoring the complete code + +# 1.1.0.0 - 2017-11-20 - First working Version +### New Features +* Create structure for returned data from api (Devices/Instances/CommandClasses) +* Create Pollingthreads +* Improve HttpClient +* Add CommandClasses Battery, CentralScene, Meter, SensorMultilevel, ThermostatSetPoint, Indicator, SwitchBinary, SwitchMultilevel, ThermostatMode, Wakeup +### Bugfixes +### Changes + +## 1.0.0.0 - 2017-10-29 - Init +### New Features +* First release +### Bugfixes +### Changes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..20ec6e2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,92 @@ +# Contributing + +When contributing to this repository, please first discuss the change you wish to make via issue, +email, or any other method with the owners of this repository before making a change. + +Please note we have a code of conduct, please follow it in all your interactions with the project. + +## Pull Request Process + +1. Ensure any install or build dependencies are removed before the end of the layer when doing a + build. +2. Update the README.md with details of changes to the interface, this includes new environment + variables, exposed ports, useful file locations and container parameters. +3. Increase the version numbers in any examples files and the README.md to the new version that this + Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). +4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you + do not have permission to do that, you may request the second reviewer to merge it for you. + +## Code of Conduct + +### Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +### Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +### Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +### Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +### Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at git ATTTT blubbfish.net. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +### Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ \ No newline at end of file diff --git a/LICENSE b/LICENSE index e69de29..f0156c5 100644 --- a/LICENSE +++ b/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..aeb0c63 --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +# BlubbFish.IoT.Zway (Zway) + + +Library that connects to a zway controller device and recieves crawls zwave data. This library contains drivers for a Zwave.me installation. This readme is meant for describing the software library. + +This library is running on every hardware that supports dotnet. + + + +## Getting Started + + +The project documentation is available on the [Wiki](https://git.blubbfish.net/vs_projects/Zway/wiki). + +## Usage + +This software can not run itselfs, cause its a library. + +## Development + +* Versioning: Use [SemVer](http://semver.org/) and tag the repository with full version string. E.g. `v1.0.0` + +### Copyright + +This library is under GNU LESSER GENERAL PUBLIC LICENSE Version 3 + +### Prerequisite + +If you want to work with this library, please checkout [zway-project](https://git.blubbfish.net/vs/zway-project) with all submodules, to get all dependencies. + +#### Internal +* BlubbFish.Utils ([Utils](http://git.blubbfish.net/vs_utils/Utils)) +* BlubbFish.Utils.IoT.Interfaces ([Iot-Interfaces](http://git.blubbfish.net/vs_utils/Iot-Interfaces)) + +#### External +* litjson ([Used Fork](https://github.com/blubbfish/litjson), [Original](https://github.com/LitJSON/litjson)) + +### Test + +You need to compile he library and use it with a calling agent. + +### Build + +Build it with Visual Studio. + +## Contributing +Contributions are welcome. + +Please fork, make your changes, and submit a pull request. For major changes, please open an issue first and discuss it with the other authors. + diff --git a/Zway/Devices/CommandClasses/Alarm.cs b/Zway/Devices/CommandClasses/Alarm.cs index 52d1705..3242043 100644 --- a/Zway/Devices/CommandClasses/Alarm.cs +++ b/Zway/Devices/CommandClasses/Alarm.cs @@ -1,15 +1,19 @@ 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 BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses { /// - /// 135 = Indicator + /// 113 = Alarm /// class Alarm : ACommandClass { public override event UpdatedValue Update; @@ -22,52 +26,71 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { /// /// unklar /// - public Int32 AlarmType { get; private set; } + public String AlarmType { get; private set; } #endregion #region Constructor - public Alarm(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { - this.InitComplex(json); - } + public Alarm(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) => this.InitComplex(json); private void InitComplex(JsonData json) { - if (json.Keys.Contains("data") && json["data"].Keys.Contains("V1event")) { - if(json["data"]["V1event"].Keys.Contains("alarmType") && - json["data"]["V1event"]["alarmType"].Keys.Contains("value") && + if(json.ContainsKey("data") && + json["data"].ContainsKey("V1event") && + json["data"].ContainsKey("V1supported") && + json["data"]["V1supported"].ContainsKey("type") && + json["data"]["V1supported"]["type"].ToString() == "bool" && + (Boolean)json["data"]["V1supported"]["value"]) { + if(json["data"]["V1event"].ContainsKey("alarmType") && + json["data"]["V1event"]["alarmType"].ContainsKey("value") && json["data"]["V1event"]["alarmType"]["value"] != null && json["data"]["V1event"]["alarmType"]["value"].IsInt) { - this.AlarmType = Int32.Parse(json["data"]["V1event"]["alarmType"]["value"].ToString()); + this.AlarmType = json["data"]["V1event"]["alarmType"]["value"].ToString(); } - if(json["data"]["V1event"].Keys.Contains("level") && - json["data"]["V1event"]["level"].Keys.Contains("value") && + if(json["data"]["V1event"].ContainsKey("level") && + json["data"]["V1event"]["level"].ContainsKey("value") && json["data"]["V1event"]["level"]["value"] != null && json["data"]["V1event"]["level"]["value"].IsInt) { this.Level = Int32.Parse(json["data"]["V1event"]["level"]["value"].ToString()); } + } else if(json.ContainsKey("data") && json["data"].IsObject && + json["data"].ContainsKey("8") && json["data"]["8"].IsObject) { + if(json["data"]["8"].ContainsKey("typeString") && json["data"]["8"]["typeString"].IsObject && + json["data"]["8"]["typeString"].ContainsKey("value") && json["data"]["8"]["typeString"]["value"] != null && json["data"]["8"]["typeString"]["value"].IsString) { + this.AlarmType = json["data"]["8"]["typeString"]["value"].ToString(); + } + if(json["data"]["8"].ContainsKey("status") && json["data"]["8"]["status"].IsObject && + json["data"]["8"]["status"].ContainsKey("value") && json["data"]["8"]["status"]["value"] != null && json["data"]["8"]["status"]["value"].IsInt) { + this.Level = Int32.Parse(json["data"]["8"]["status"]["value"].ToString()); + } } } #endregion #region ACommandClass - public override String ToString() { - return "Alarm " + this.Name + " [" + this.Id + "]: " + this.AlarmType + " " + this.Level; - } + public override String ToString() => "Alarm " + this.Name + " [" + this.Id + "]: " + this.AlarmType + " " + this.Level; - public override Dictionary ToDictionary() { - return new Dictionary { - { "AlarmType", this.AlarmType }, - { "Level", this.Level }, - }; - } + public override Dictionary ToDictionary() => new Dictionary { + { "AlarmType", this.AlarmType }, + { "Level", this.Level }, + }; internal override void SetUpdate(JsonData json, Match match) { - if (match.Groups[4].Value == ".data.V1event") { - if (json.Keys.Contains("alarmType") && json["alarmType"].Keys.Contains("value") && + if(match.Groups[4].Value == ".data.V1event") { + if(json.Keys.Contains("alarmType") && json["alarmType"].Keys.Contains("value") && json.Keys.Contains("level") && json["level"].Keys.Contains("value") && this.CheckSetUpdateTime(json)) { - this.AlarmType = Int32.Parse(json["alarmType"]["value"].ToString()); + this.AlarmType = json["alarmType"]["value"].ToString(); this.Level = Int32.Parse(json["level"]["value"].ToString()); - this.Update?.Invoke(this, new DeviceUpdateEvent(new Tuple(this.AlarmType, this.Level), this.LastUpdate, this)); + this.Update?.Invoke(this, new DeviceUpdateEvent(new Tuple(this.AlarmType, this.Level), this.LastUpdate, this)); + } + } else if(match.Groups[4].Value == ".data.8") { + if(json.ContainsKey("typeString") && json["typeString"].IsObject && + json["typeString"].ContainsKey("value") && json["typeString"]["value"] != null && json["typeString"]["value"].IsString && + json.ContainsKey("status") && json["status"].IsObject && + json["status"].ContainsKey("value") && json["status"]["value"] != null && json["status"]["value"].IsInt && + this.CheckSetUpdateTime(json)) { + this.AlarmType = json["typeString"]["value"].ToString(); + this.Level = Int32.Parse(json["status"]["value"].ToString()); + this.Update?.Invoke(this, new DeviceUpdateEvent(new Tuple(this.AlarmType, this.Level), this.LastUpdate, this)); } } else { Helper.WriteError("Kenne in " + this.Name + " [" + this.Id + "] " + match.Groups[4].Value + " nicht!"); @@ -78,9 +101,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region ISenml - protected override List ToSenmlList() { - return new List() { }; - } + protected override List ToSenmlList() => new List() { }; #endregion } } diff --git a/Zway/Devices/CommandClasses/AlarmSensor.cs b/Zway/Devices/CommandClasses/AlarmSensor.cs index 64c6032..694f610 100644 --- a/Zway/Devices/CommandClasses/AlarmSensor.cs +++ b/Zway/Devices/CommandClasses/AlarmSensor.cs @@ -2,11 +2,14 @@ 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 BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses { @@ -17,15 +20,15 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { public override event UpdatedValue Update; #region Constructor - public Alarmsensor(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Alarmsensor(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.HasSub = true; - this.InitComplex(json); + this.InitComplex(json, name); foreach (KeyValuePair item in this.Sub) { item.Value.Update += this.DeviceUpdate; } } - private void InitComplex(JsonData json) { + private void InitComplex(JsonData json, (String device, ReadOnlyDictionary descriptions) name) { if (json.Keys.Contains("data")) { JsonData data = json["data"]; Dictionary subs = new Dictionary(); @@ -35,16 +38,14 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { data[item].Keys.Contains("sensorState") && data[item].Keys.Contains("sensorTime") && data[item].Keys.Contains("typeString")) { - subs.Add(subid, new Alarmsensorsub(data[item], new Tuple(this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling)); + subs.Add(subid, new Alarmsensorsub(data[item], (this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling, name)); } } this.Sub = new ReadOnlyDictionary(subs); } } - private void DeviceUpdate(Object sender, DeviceUpdateEvent e) { - this.Update?.Invoke(this, e); - } + private void DeviceUpdate(Object sender, DeviceUpdateEvent e) => this.Update?.Invoke(this, e); #endregion #region ACommandClass diff --git a/Zway/Devices/CommandClasses/Battery.cs b/Zway/Devices/CommandClasses/Battery.cs index 0b7a785..6475f0f 100644 --- a/Zway/Devices/CommandClasses/Battery.cs +++ b/Zway/Devices/CommandClasses/Battery.cs @@ -1,10 +1,14 @@ 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 BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses { @@ -22,9 +26,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region Constructor - public Battery(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { - this.InitComplex(json); - } + public Battery(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) => this.InitComplex(json); private void InitComplex(JsonData json) { if (json.Keys.Contains("data") && json["data"].Keys.Contains("last") && json["data"]["last"].Keys.Contains("value")) { @@ -34,15 +36,11 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region ACommandClass - public override String ToString() { - return "Battery " + this.Name + " [" + this.Id + "]: " + this.Level; - } + public override String ToString() => "Battery " + this.Name + " [" + this.Id + "]: " + this.Level; - public override Dictionary ToDictionary() { - return new Dictionary { - { "Level", this.Level }, - }; - } + public override Dictionary ToDictionary() => new Dictionary { + { "Level", this.Level }, + }; internal override void SetUpdate(JsonData json, Match match) { Boolean success = false; if (match.Groups[4].Value == ".data") { @@ -67,9 +65,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region ISenml - protected override List ToSenmlList() { - return new List() { new SenmlDouble("chargelevel", Senml.Units.Percent, this.Level) }; - } + protected override List ToSenmlList() => new List() { new SenmlDouble("chargelevel", Senml.Units.Percent, this.Level) }; #endregion } diff --git a/Zway/Devices/CommandClasses/CentralScene.cs b/Zway/Devices/CommandClasses/CentralScene.cs index d4a9a96..f6b1b12 100644 --- a/Zway/Devices/CommandClasses/CentralScene.cs +++ b/Zway/Devices/CommandClasses/CentralScene.cs @@ -4,7 +4,8 @@ using System.Collections.ObjectModel; using System.Text.RegularExpressions; using BlubbFish.IoT.Zway.Events; using BlubbFish.IoT.Zway.Interfaces; -using BlubbFish.IoT.Zway.lib; +using BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces.Language; using LitJson; @@ -31,7 +32,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region Constructor - public Centralscene(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Centralscene(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.ValidScenesModes = new ReadOnlyDictionary>(new Dictionary>()); this.InitComplex(json); } @@ -70,16 +71,12 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region ACommandClass - public override String ToString() { - return "CentralScene " + this.Name + " [" + this.Id + "]: " + this.Scene + "-" + this.Key; - } + public override String ToString() => "CentralScene " + this.Name + " [" + this.Id + "]: " + this.Scene + "-" + this.Key; - public override Dictionary ToDictionary() { - return new Dictionary { - { "Scene", this.Scene }, - { "Key", this.Key }, - }; - } + public override Dictionary ToDictionary() => new Dictionary { + { "Scene", this.Scene }, + { "Key", this.Key }, + }; internal override void SetUpdate(JsonData json, Match match) { if (match.Groups[4].Value == ".data.currentScene") { @@ -100,9 +97,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region ISenml - protected override List ToSenmlList() { - return new List() { new SenmlDouble("scene", Senml.Units.CounterValue, this.Scene), new SenmlDouble("key", Senml.Units.CounterValue, this.Key) }; - } + protected override List ToSenmlList() => new List() { new SenmlDouble("scene", Senml.Units.CounterValue, this.Scene), new SenmlDouble("key", Senml.Units.CounterValue, this.Key) }; #endregion } } diff --git a/Zway/Devices/CommandClasses/CommandClassSubs/Alarmsensorsub.cs b/Zway/Devices/CommandClasses/CommandClassSubs/Alarmsensorsub.cs index 5f1fbd8..22fb8b9 100644 --- a/Zway/Devices/CommandClasses/CommandClassSubs/Alarmsensorsub.cs +++ b/Zway/Devices/CommandClasses/CommandClassSubs/Alarmsensorsub.cs @@ -1,10 +1,13 @@ 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 BlubbFish.IoT.Zway.lib.Zway; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { @@ -31,9 +34,9 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region Constructor - public Alarmsensorsub(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Alarmsensorsub(JsonData json, (Int32 device, Int32 instance, Classes commandclass, Int32 sensor) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.IsSub = true; - InitComplex(json); + this.InitComplex(json); } private void InitComplex(JsonData json) { @@ -50,18 +53,14 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region ACommandClass - public override String ToString() { - return "AlarmSensor " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.Source + " " + this.Level + " " + this.Time + " " + this.Type; - } + public override String ToString() => "AlarmSensor " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.Source + " " + this.Level + " " + this.Time + " " + this.Type; - public override Dictionary ToDictionary() { - return new Dictionary { + public override Dictionary ToDictionary() => new Dictionary { { "Source", this.Source }, { "Level", this.Level }, { "Time", this.Time }, { "Type", this.Type } }; - } internal override void SetUpdate(JsonData json, Match match) { if (json.Keys.Contains("srcId") && json["srcId"].Keys.Contains("value") && @@ -81,9 +80,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region ISenml - protected override List ToSenmlList() { - return new List() { }; - } + protected override List ToSenmlList() => new List() { }; #endregion } } \ No newline at end of file diff --git a/Zway/Devices/CommandClasses/CommandClassSubs/Configurationsub.cs b/Zway/Devices/CommandClasses/CommandClassSubs/Configurationsub.cs index 30ab86a..69384dd 100644 --- a/Zway/Devices/CommandClasses/CommandClassSubs/Configurationsub.cs +++ b/Zway/Devices/CommandClasses/CommandClassSubs/Configurationsub.cs @@ -1,10 +1,13 @@ 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 BlubbFish.IoT.Zway.lib.Zway; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { @@ -17,16 +20,14 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { /// Value of the Configuration Item /// public Int64 Level { - get { - return this._level; - } + get => this._level; set { - if (this.Size == 1 && Int16.TryParse(value.ToString(), out Int16 value16)) { - this.SetTriple(this.SensorId, value16, 1); + 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); + this.SetTriple((this.SensorId, value32, 2)); } else if(this.Size == 4) { - this.SetTriple(this.SensorId, value, 4); + this.SetTriple((this.SensorId, value, 4)); } } } @@ -37,9 +38,9 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region Constructor - public Configurationsub(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Configurationsub(JsonData json, (Int32 device, Int32 instance, Classes commandclass, Int32 sensor) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.IsSub = true; - InitComplex(json); + this.InitComplex(json); } private void InitComplex(JsonData json) { @@ -55,16 +56,12 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region ACommandClass - public override String ToString() { - return "Configuration " + this.Name + " [" + this.Id + "]: " + this.Level; - } + public override String ToString() => "Configuration " + this.Name + " [" + this.Id + "]: " + this.Level; - public override Dictionary ToDictionary() { - return new Dictionary { - { "Level", this.Level }, - { "Size", this.Size }, - }; - } + public override Dictionary ToDictionary() => new Dictionary { + { "Level", this.Level }, + { "Size", this.Size }, + }; internal override void SetUpdate(JsonData json, Match match) { if (json.Keys.Contains("val") && json["val"].Keys.Contains("value") && json["val"]["value"] != null && @@ -80,9 +77,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region ISenml - protected override List ToSenmlList() { - return new List() { }; - } + protected override List ToSenmlList() => new List() { }; #endregion } } \ No newline at end of file diff --git a/Zway/Devices/CommandClasses/CommandClassSubs/MeterSub.cs b/Zway/Devices/CommandClasses/CommandClassSubs/MeterSub.cs index e8aebd8..6a58c81 100644 --- a/Zway/Devices/CommandClasses/CommandClassSubs/MeterSub.cs +++ b/Zway/Devices/CommandClasses/CommandClassSubs/MeterSub.cs @@ -1,10 +1,13 @@ 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 BlubbFish.IoT.Zway.lib.Zway; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { @@ -27,10 +30,10 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region Constructor - public Metersub(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Metersub(JsonData json, (Int32 device, Int32 instance, Classes commandclass, Int32 sensor) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.HasReset = true; this.IsSub = true; - InitComplex(json); + this.InitComplex(json); } private void InitComplex(JsonData json) { @@ -48,17 +51,13 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region ACommandClass - public override String ToString() { - return "Meter " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.Level + "" + this.Scale; - } + public override String ToString() => "Meter " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.Level + "" + this.Scale; - public override Dictionary ToDictionary() { - return new Dictionary { - { "Level", this.Level }, - { "Type", this.Type }, - { "Scale", this.Scale }, - }; - } + public override Dictionary ToDictionary() => new Dictionary { + { "Level", this.Level }, + { "Type", this.Type }, + { "Scale", this.Scale }, + }; internal override void SetUpdate(JsonData json, Match match) { if (json.Keys.Contains("val") && json["val"].Keys.Contains("value") && diff --git a/Zway/Devices/CommandClasses/CommandClassSubs/SceneControllerConfSub.cs b/Zway/Devices/CommandClasses/CommandClassSubs/SceneControllerConfSub.cs index 0da79ae..580ac8e 100644 --- a/Zway/Devices/CommandClasses/CommandClassSubs/SceneControllerConfSub.cs +++ b/Zway/Devices/CommandClasses/CommandClassSubs/SceneControllerConfSub.cs @@ -1,10 +1,13 @@ 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 BlubbFish.IoT.Zway.lib.Zway; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { @@ -23,9 +26,9 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region Constructor - public Scenecontrollerconfsub(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Scenecontrollerconfsub(JsonData json, (Int32 device, Int32 instance, Classes commandclass, Int32 sensor) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.IsSub = true; - InitComplex(json); + this.InitComplex(json); } private void InitComplex(JsonData json) { @@ -38,16 +41,12 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region ACommandClass - public override String ToString() { - return "SceneControllerConf " + this.Name + " [" + this.Id + "]: " + this.Scene + " " + this.Duration; - } + public override String ToString() => "SceneControllerConf " + this.Name + " [" + this.Id + "]: " + this.Scene + " " + this.Duration; - public override Dictionary ToDictionary() { - return new Dictionary { - { "Scene", this.Scene }, - { "Duration", this.Duration } - }; - } + public override Dictionary ToDictionary() => new Dictionary { + { "Scene", this.Scene }, + { "Duration", this.Duration } + }; internal override void SetUpdate(JsonData json, Match match) { if (json.Keys.Contains("scene") && json["scene"].Keys.Contains("value") && @@ -63,9 +62,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region ISenml - protected override List ToSenmlList() { - return new List() { }; - } + protected override List ToSenmlList() => new List() { }; #endregion } } \ No newline at end of file diff --git a/Zway/Devices/CommandClasses/CommandClassSubs/SensorBinarySub.cs b/Zway/Devices/CommandClasses/CommandClassSubs/SensorBinarySub.cs index 883212f..0d868ba 100644 --- a/Zway/Devices/CommandClasses/CommandClassSubs/SensorBinarySub.cs +++ b/Zway/Devices/CommandClasses/CommandClassSubs/SensorBinarySub.cs @@ -1,10 +1,13 @@ 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 BlubbFish.IoT.Zway.lib.Zway; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { @@ -23,17 +26,13 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { /// /// /// - public Int32 Level { - get { - return (this.State) ? 1 : 0; - } - } + public Int32 Level => this.State ? 1 : 0; #endregion #region Constructor - public Sensorbinarysub(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Sensorbinarysub(JsonData json, (Int32 device, Int32 instance, Classes commandclass, Int32 sensor) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.IsSub = true; - InitComplex(json); + this.InitComplex(json); } private void InitComplex(JsonData json) { @@ -48,17 +47,13 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region ACommandClass - public override String ToString() { - return "SensorBinary " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.State.ToString(); - } + public override String ToString() => "SensorBinary " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.State.ToString(); - public override Dictionary ToDictionary() { - return new Dictionary { - { "State", this.State }, - { "Type", this.Type }, - { "Level", this.Level } - }; - } + public override Dictionary ToDictionary() => new Dictionary { + { "State", this.State }, + { "Type", this.Type }, + { "Level", this.Level } + }; internal override void SetUpdate(JsonData json, Match match) { if (json.Keys.Contains("level") && json["level"].Keys.Contains("value") && @@ -74,9 +69,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region ISenml - protected override List ToSenmlList() { - return new List() { }; - } + protected override List ToSenmlList() => new List() { }; #endregion } } \ No newline at end of file diff --git a/Zway/Devices/CommandClasses/CommandClassSubs/SensorMultilevelSub.cs b/Zway/Devices/CommandClasses/CommandClassSubs/SensorMultilevelSub.cs index 6fc2667..963e3f3 100644 --- a/Zway/Devices/CommandClasses/CommandClassSubs/SensorMultilevelSub.cs +++ b/Zway/Devices/CommandClasses/CommandClassSubs/SensorMultilevelSub.cs @@ -1,9 +1,11 @@ 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 BlubbFish.IoT.Zway.lib.Zway; using BlubbFish.Utils.IoT.Interfaces.Language; using LitJson; @@ -27,9 +29,9 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region Constructor - public Sensormultilevelsub(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Sensormultilevelsub(JsonData json, (Int32 device, Int32 instance, Classes commandclass, Int32 sensor) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.IsSub = true; - InitComplex(json); + this.InitComplex(json); } private void InitComplex(JsonData json) { @@ -47,25 +49,21 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region ACommandClass - public override String ToString() { - return "SensorMultilevel " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.Level + "" + this.Scale; - } + public override String ToString() => "SensorMultilevel " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.Level + "" + this.Scale; - public override Dictionary ToDictionary() { - return new Dictionary { - { "Level", this.Level }, - { "Type", this.Type }, - { "Scale", this.Scale }, - }; - } + public override Dictionary ToDictionary() => new Dictionary { + { "Level", this.Level }, + { "Type", this.Type }, + { "Scale", this.Scale }, + }; 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")) { String t = json["sensorTypeString"]["value"].ToString(); Double l = Double.Parse(json["val"]["value"].ToString()); - if (t == "Power" && (l > 3660 || l < 0) || + if (t == "Power" && (l > 3680 || l < 0) || t == "Temperature" && (l > 65 || l < -25) || - (t == "Temperature" && this.Level >= 4 && Math.Abs(l) <= 0.1)) { + t == "Temperature" && this.Level >= 4 && Math.Abs(l) <= 0.1) { return; } } diff --git a/Zway/Devices/CommandClasses/CommandClassSubs/ThermostatSetPointSub.cs b/Zway/Devices/CommandClasses/CommandClassSubs/ThermostatSetPointSub.cs index 2aee6bf..3124d15 100644 --- a/Zway/Devices/CommandClasses/CommandClassSubs/ThermostatSetPointSub.cs +++ b/Zway/Devices/CommandClasses/CommandClassSubs/ThermostatSetPointSub.cs @@ -1,9 +1,10 @@ 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 BlubbFish.IoT.Zway.lib.Zway; using BlubbFish.Utils.IoT.Interfaces.Language; using LitJson; @@ -17,12 +18,10 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { /// Target-Temperatur /// public Double Level { - get { - return this._level; - } + get => 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); + if(!this.HasMinMax || this.HasMinMax && value >= this.TempMin && value <= this.TempMax) { + this.SetTuple((this.SensorId, (Double)Math.Round(value * 2, MidpointRounding.AwayFromZero) / 2)); } } } @@ -49,9 +48,9 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region Constructor - public Thermostatsetpointsub(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Thermostatsetpointsub(JsonData json, (Int32 device, Int32 instance, Classes commandclass, Int32 sensor) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.IsSub = true; - InitComplex(json); + this.InitComplex(json); } private void InitComplex(JsonData json) { @@ -74,20 +73,16 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region ACommandClass - public override String ToString() { - return "ThermostatSetPoint " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.Level + "" + this.Scale + " [" + this.TempMin + "," + this.TempMax + "," + this.HasMinMax + "]"; - } + public override String ToString() => "ThermostatSetPoint " + this.Name + " [" + this.Id + "]: " + this.Type + " " + this.Level + "" + this.Scale + " [" + this.TempMin + "," + this.TempMax + "," + this.HasMinMax + "]"; - 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 }, - }; - } + public override Dictionary ToDictionary() => new Dictionary { + { "Level", this.Level }, + { "Type", this.Type }, + { "Scale", this.Scale }, + { "TempMax", this.TempMax }, + { "TempMin", this.TempMin }, + { "HasMinMax", this.HasMinMax }, + }; internal override void SetUpdate(JsonData json, Match match) { Boolean ret = false; @@ -117,12 +112,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses.CommandClassSubs { #endregion #region ISenml - protected override List ToSenmlList() { - if(this.Scale == "°C") { - return new List() { new SenmlDouble("temperatur", Senml.Units.Celsius, this.Level) }; - } - return new List() { }; - } + protected override List ToSenmlList() => this.Scale == "°C" ? new List() { new SenmlDouble("temperatur", Senml.Units.Celsius, this.Level) } : new List() { }; #endregion } } \ No newline at end of file diff --git a/Zway/Devices/CommandClasses/Configuration.cs b/Zway/Devices/CommandClasses/Configuration.cs index eecfb7a..af00493 100644 --- a/Zway/Devices/CommandClasses/Configuration.cs +++ b/Zway/Devices/CommandClasses/Configuration.cs @@ -2,11 +2,14 @@ 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 BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses { @@ -17,15 +20,15 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { public override event UpdatedValue Update; #region Constructor - public Configuration(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Configuration(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.HasSub = true; - this.InitComplex(json); + this.InitComplex(json, name); foreach (KeyValuePair item in this.Sub) { item.Value.Update += this.DeviceUpdate; } } - private void InitComplex(JsonData json) { + private void InitComplex(JsonData json, (String device, ReadOnlyDictionary descriptions) name) { if (json.Keys.Contains("data")) { JsonData data = json["data"]; Dictionary subs = new Dictionary(); @@ -35,16 +38,14 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { 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)); + subs.Add(subid, new Configurationsub(data[item], (this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling, name)); } } this.Sub = new ReadOnlyDictionary(subs); } } - private void DeviceUpdate(Object sender, DeviceUpdateEvent e) { - this.Update?.Invoke(this, e); - } + private void DeviceUpdate(Object sender, DeviceUpdateEvent e) => this.Update?.Invoke(this, e); #endregion #region ACommandClass diff --git a/Zway/Devices/CommandClasses/Indicator.cs b/Zway/Devices/CommandClasses/Indicator.cs index 6261636..b5e2e2d 100644 --- a/Zway/Devices/CommandClasses/Indicator.cs +++ b/Zway/Devices/CommandClasses/Indicator.cs @@ -1,10 +1,14 @@ 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 BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses { @@ -20,30 +24,20 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { /// Status of the Indicator /// public Boolean State { - get { - return this._state; - } - set { - this.SetInt(value ? 255 : 0); - } + get => this._state; + set => this.SetInt(value ? 255 : 0); } /// /// Int-Representation of the Indicator /// public Int32 Level { - get { - return (this.State) ? 1 : 0; - } - set { - this.State = (value == 1); - } + get => this.State ? 1 : 0; + set => this.State = value == 1; } #endregion #region Constructor - public Indicator(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { - this.InitComplex(json); - } + public Indicator(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) => this.InitComplex(json); private void InitComplex(JsonData json) { if (json.Keys.Contains("data") && json["data"].Keys.Contains("stat") && json["data"]["stat"].Keys.Contains("value")) { @@ -53,16 +47,12 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region ACommandClass - public override String ToString() { - return "Indicator " + this.Name + " [" + this.Id + "]: " + this.State; - } + public override String ToString() => "Indicator " + this.Name + " [" + this.Id + "]: " + this.State; - public override Dictionary ToDictionary() { - return new Dictionary { + public override Dictionary ToDictionary() => new Dictionary { { "State", this.State }, { "Level", this.Level } }; - } internal override void SetUpdate(JsonData json, Match match) { if(match.Groups[4].Value == ".data.stat") { @@ -77,9 +67,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region ISenml - protected override List ToSenmlList() { - return new List() { new SenmlBool("status", Senml.Units.CounterValue, this.State) }; - } + protected override List ToSenmlList() => new List() { new SenmlBool("status", Senml.Units.CounterValue, this.State) }; #endregion } diff --git a/Zway/Devices/CommandClasses/Meter.cs b/Zway/Devices/CommandClasses/Meter.cs index d41f060..9b28607 100644 --- a/Zway/Devices/CommandClasses/Meter.cs +++ b/Zway/Devices/CommandClasses/Meter.cs @@ -2,11 +2,14 @@ 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 BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses { @@ -17,15 +20,15 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { public override event UpdatedValue Update; #region Constructor - public Meter(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Meter(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.HasSub = true; - this.InitComplex(json); + this.InitComplex(json, name); foreach (KeyValuePair item in this.Sub) { item.Value.Update += this.DeviceUpdate; } } - private void InitComplex(JsonData json) { + private void InitComplex(JsonData json, (String device, ReadOnlyDictionary descriptions) name) { if (json.Keys.Contains("data")) { JsonData data = json["data"]; Dictionary subs = new Dictionary(); @@ -34,16 +37,14 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { data[item].Keys.Contains("sensorTypeString") && data[item].Keys.Contains("val") && data[item].Keys.Contains("scaleString")) { - subs.Add(subid, new Metersub(data[item], new Tuple(this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling)); + subs.Add(subid, new Metersub(data[item], (this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling, name)); } } this.Sub = new ReadOnlyDictionary(subs); } } - private void DeviceUpdate(Object sender, DeviceUpdateEvent e) { - this.Update?.Invoke(this, e); - } + private void DeviceUpdate(Object sender, DeviceUpdateEvent e) => this.Update?.Invoke(this, e); #endregion #region ACommandClass diff --git a/Zway/Devices/CommandClasses/SceneControllerConf.cs b/Zway/Devices/CommandClasses/SceneControllerConf.cs index a99f7bf..09785aa 100644 --- a/Zway/Devices/CommandClasses/SceneControllerConf.cs +++ b/Zway/Devices/CommandClasses/SceneControllerConf.cs @@ -2,11 +2,14 @@ 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 BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses { @@ -17,15 +20,15 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { public override event UpdatedValue Update; #region Constructor - public Scenecontrollerconf(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Scenecontrollerconf(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.HasSub = true; - this.InitComplex(json); + this.InitComplex(json, name); foreach (KeyValuePair item in this.Sub) { item.Value.Update += this.DeviceUpdate; } } - private void InitComplex(JsonData json) { + private void InitComplex(JsonData json, (String device, ReadOnlyDictionary descriptions) name) { if (json.Keys.Contains("data")) { JsonData data = json["data"]; Dictionary subs = new Dictionary(); @@ -33,16 +36,14 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { if (Int32.TryParse(item, out Int32 subid) && data[item].Keys.Contains("scene") && data[item].Keys.Contains("duration")) { - subs.Add(subid, new Scenecontrollerconfsub(data[item], new Tuple(this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling)); + subs.Add(subid, new Scenecontrollerconfsub(data[item], (this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling, name)); } } this.Sub = new ReadOnlyDictionary(subs); } } - private void DeviceUpdate(Object sender, DeviceUpdateEvent e) { - this.Update?.Invoke(this, e); - } + private void DeviceUpdate(Object sender, DeviceUpdateEvent e) => this.Update?.Invoke(this, e); #endregion #region ACommandClass diff --git a/Zway/Devices/CommandClasses/SensorBinary.cs b/Zway/Devices/CommandClasses/SensorBinary.cs index 5255ae1..1eb06b3 100644 --- a/Zway/Devices/CommandClasses/SensorBinary.cs +++ b/Zway/Devices/CommandClasses/SensorBinary.cs @@ -2,11 +2,14 @@ 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 BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses { @@ -17,15 +20,15 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { public override event UpdatedValue Update; #region Constructor - public Sensorbinary(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Sensorbinary(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.HasSub = true; - this.InitComplex(json); + this.InitComplex(json, name); foreach (KeyValuePair item in this.Sub) { item.Value.Update += this.DeviceUpdate; } } - private void InitComplex(JsonData json) { + private void InitComplex(JsonData json, (String device, ReadOnlyDictionary descriptions) name) { if (json.Keys.Contains("data")) { JsonData data = json["data"]; Dictionary subs = new Dictionary(); @@ -33,16 +36,14 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { if (Int32.TryParse(item, out Int32 subid) && data[item].Keys.Contains("sensorTypeString") && data[item].Keys.Contains("level")) { - subs.Add(subid, new Sensorbinarysub(data[item], new Tuple(this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling)); + subs.Add(subid, new Sensorbinarysub(data[item], (this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling, name)); } } this.Sub = new ReadOnlyDictionary(subs); } } - private void DeviceUpdate(Object sender, DeviceUpdateEvent e) { - this.Update?.Invoke(this, e); - } + private void DeviceUpdate(Object sender, DeviceUpdateEvent e) => this.Update?.Invoke(this, e); #endregion #region ACommandClass diff --git a/Zway/Devices/CommandClasses/SensorMultilevel.cs b/Zway/Devices/CommandClasses/SensorMultilevel.cs index 47a2cdd..1a4f811 100644 --- a/Zway/Devices/CommandClasses/SensorMultilevel.cs +++ b/Zway/Devices/CommandClasses/SensorMultilevel.cs @@ -2,11 +2,14 @@ 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 BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses { @@ -17,15 +20,15 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { public override event UpdatedValue Update; #region Constructor - public Sensormultilevel(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Sensormultilevel(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.HasSub = true; - this.InitComplex(json); + this.InitComplex(json, name); foreach (KeyValuePair item in this.Sub) { item.Value.Update += this.DeviceUpdate; } } - private void InitComplex(JsonData json) { + private void InitComplex(JsonData json, (String device, ReadOnlyDictionary descriptions) name) { if (json.Keys.Contains("data")) { JsonData data = json["data"]; Dictionary subs = new Dictionary(); @@ -34,16 +37,14 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { data[item].Keys.Contains("sensorTypeString") && data[item].Keys.Contains("val") && data[item].Keys.Contains("scaleString")) { - subs.Add(subid, new Sensormultilevelsub(data[item], new Tuple(this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling)); + subs.Add(subid, new Sensormultilevelsub(data[item], (this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling, name)); } } this.Sub = new ReadOnlyDictionary(subs); } } - private void DeviceUpdate(Object sender, DeviceUpdateEvent e) { - this.Update?.Invoke(this, e); - } + private void DeviceUpdate(Object sender, DeviceUpdateEvent e) => this.Update?.Invoke(this, e); #endregion #region ACommandClass diff --git a/Zway/Devices/CommandClasses/SwitchBinary.cs b/Zway/Devices/CommandClasses/SwitchBinary.cs index 5b7d68d..d2a88e0 100644 --- a/Zway/Devices/CommandClasses/SwitchBinary.cs +++ b/Zway/Devices/CommandClasses/SwitchBinary.cs @@ -1,10 +1,14 @@ 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 BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses { @@ -19,31 +23,21 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { /// Int representation of Boolean /// public Int32 Level { - get { - return (this.State) ? 1 : 0; - } - set { - this.State = (value == 1); - } + get => this.State ? 1 : 0; + set => this.State = value == 1; } private Boolean _state; /// /// State if Switch is activated /// public Boolean State { - get { - return this._state; - } - set { - this.SetInt(value ? 255 : 0); - } + get => this._state; + set => this.SetInt(value ? 255 : 0); } #endregion #region Constructor - public Switchbinary(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { - this.InitComplex(json); - } + public Switchbinary(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) => this.InitComplex(json); private void InitComplex(JsonData json) { if (json.Keys.Contains("data") && json["data"].Keys.Contains("level") && json["data"]["level"].Keys.Contains("value") && json["data"]["level"]["value"].IsBoolean) { @@ -53,16 +47,12 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region ACommandClass - public override String ToString() { - return "SwitchBinary " + this.Name + " [" + this.Id + "]: " + this.State; - } + public override String ToString() => "SwitchBinary " + this.Name + " [" + this.Id + "]: " + this.State; - public override Dictionary ToDictionary() { - return new Dictionary { - { "State", this.State }, - { "Level", this.Level } - }; - } + public override Dictionary ToDictionary() => new Dictionary { + { "State", this.State }, + { "Level", this.Level } + }; internal override void SetUpdate(JsonData json, Match match) { if(match.Groups[4].Value == ".data.level") { @@ -77,9 +67,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region ISenml - protected override List ToSenmlList() { - return new List() { new SenmlBool("state", Senml.Units.CounterValue, this.State) }; - } + protected override List ToSenmlList() => new List() { new SenmlBool("state", Senml.Units.CounterValue, this.State) }; #endregion } } diff --git a/Zway/Devices/CommandClasses/SwitchMultilevel.cs b/Zway/Devices/CommandClasses/SwitchMultilevel.cs index 94b8638..e76de17 100644 --- a/Zway/Devices/CommandClasses/SwitchMultilevel.cs +++ b/Zway/Devices/CommandClasses/SwitchMultilevel.cs @@ -1,10 +1,14 @@ 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 BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses { @@ -20,21 +24,17 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { /// Level of thw Switch /// public Int32 Level { - get { - return this._level; - } + get => this._level; set { - if(value == 0 || (value > 0 && value <= 99) || value == 255) { - this.SetTuple(value, 0); + if(value == 0 || value > 0 && value <= 99 || value == 255) { + this.SetTuple((value, 0)); } } } #endregion #region Constructor - public Switchmultilevel(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { - this.InitComplex(json); - } + public Switchmultilevel(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) => this.InitComplex(json); private void InitComplex(JsonData json) { if (json.Keys.Contains("data") && json["data"].Keys.Contains("level") && json["data"]["level"].Keys.Contains("value")) { @@ -44,15 +44,11 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region ACommandClass - public override String ToString() { - return "SwitchMultilevel " + this.Name + " [" + this.Id + "]: " + this.Level; - } + public override String ToString() => "SwitchMultilevel " + this.Name + " [" + this.Id + "]: " + this.Level; - public override Dictionary ToDictionary() { - return new Dictionary { - { "Level", this.Level } - }; - } + public override Dictionary ToDictionary() => new Dictionary { + { "Level", this.Level } + }; internal override void SetUpdate(JsonData json, Match match) { if(match.Groups[4].Value == ".data.level") { @@ -68,9 +64,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region ISenml - protected override List ToSenmlList() { - return new List() { new SenmlDouble("state", Senml.Units.Percent, (Double)this.Level/255) }; - } + protected override List ToSenmlList() => new List() { new SenmlDouble("state", Senml.Units.Percent, (Double)this.Level / 255) }; #endregion } } diff --git a/Zway/Devices/CommandClasses/ThermostatMode.cs b/Zway/Devices/CommandClasses/ThermostatMode.cs index 412923a..41de1c2 100644 --- a/Zway/Devices/CommandClasses/ThermostatMode.cs +++ b/Zway/Devices/CommandClasses/ThermostatMode.cs @@ -2,10 +2,13 @@ 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 BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses { @@ -25,9 +28,9 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { /// Actual mode /// public Int32 Level { - get { return this._level; } + get => this._level; set { - if (this.ValidModes.ContainsKey(value)) { + if(this.ValidModes.ContainsKey(value)) { this.SetInt(value); } } @@ -35,7 +38,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region Constructor - public Thermostatmode(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Thermostatmode(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.ValidModes = new ReadOnlyDictionary(new Dictionary()); this.InitComplex(json); } @@ -61,9 +64,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region ACommandClass - public override String ToString() { - return "ThermostatMode " + this.Name + " [" + this.Id + "]: " + this.ValidModes[this.Level]; - } + public override String ToString() => "ThermostatMode " + this.Name + " [" + this.Id + "]: " + this.ValidModes[this.Level]; public override Dictionary ToDictionary() { Dictionary modes = new Dictionary(); @@ -90,9 +91,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region ISenml - protected override List ToSenmlList() { - return new List() { new SenmlDouble("mode", Senml.Units.CounterValue, this.Level) }; - } + protected override List ToSenmlList() => new List() { new SenmlDouble("mode", Senml.Units.CounterValue, this.Level) }; #endregion } } diff --git a/Zway/Devices/CommandClasses/ThermostatSetPoint.cs b/Zway/Devices/CommandClasses/ThermostatSetPoint.cs index 9cc92ca..866b3f8 100644 --- a/Zway/Devices/CommandClasses/ThermostatSetPoint.cs +++ b/Zway/Devices/CommandClasses/ThermostatSetPoint.cs @@ -2,11 +2,14 @@ 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 BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Devices.CommandClasses { @@ -17,15 +20,15 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { public override event UpdatedValue Update; #region Constructor - public Thermostatsetpoint(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { + public Thermostatsetpoint(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) { this.HasSub = true; - this.InitComplex(json); + this.InitComplex(json, name); foreach (KeyValuePair item in this.Sub) { item.Value.Update += this.DeviceUpdate; } } - private void InitComplex(JsonData json) { + private void InitComplex(JsonData json, (String device, ReadOnlyDictionary descriptions) name) { if (json.Keys.Contains("data")) { JsonData data = json["data"]; Dictionary subs = new Dictionary(); @@ -34,16 +37,14 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { data[item].Keys.Contains("modeName") && data[item].Keys.Contains("val") && data[item].Keys.Contains("deviceScaleString")) { - subs.Add(subid, new Thermostatsetpointsub(data[item], new Tuple(this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling)); + subs.Add(subid, new Thermostatsetpointsub(data[item], (this.DeviceId, this.Instance, this.Commandclass, subid), this.http, this.Polling, name)); } } this.Sub = new ReadOnlyDictionary(subs); } } - private void DeviceUpdate(Object sender, DeviceUpdateEvent e) { - this.Update?.Invoke(this, e); - } + private void DeviceUpdate(Object sender, DeviceUpdateEvent e) => this.Update?.Invoke(this, e); #endregion #region ACommandClass diff --git a/Zway/Devices/CommandClasses/Wakeup.cs b/Zway/Devices/CommandClasses/Wakeup.cs index 747cff2..7e8c2b7 100644 --- a/Zway/Devices/CommandClasses/Wakeup.cs +++ b/Zway/Devices/CommandClasses/Wakeup.cs @@ -1,9 +1,11 @@ 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 BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces.Language; using LitJson; @@ -17,38 +19,31 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #region Properties private Int32 _interval; public Int32 Interval { - get { - return this._interval; - } + get => this._interval; set { if(value >= this.WakeupMin && value <= this.WakeupMax) { - this.SetTuple(value, this.AgainstNode); + this.SetTuple((value, this.AgainstNode)); } } } private Int32 _againstNode; - public Int32 AgainstNode { get { - return this._againstNode; - } - set { - this.SetTuple(this.Interval, value); - } + public Int32 AgainstNode { + get => this._againstNode; + set => this.SetTuple((this.Interval, value)); } public Int32 WakeupMin { get; private set; } public Int32 WakeupMax { get; private set; } public Boolean HasMinMaxState { get; private set; } - public Int32 HasMinMaxLevel { get { return (this.HasMinMaxState) ? 1 : 0; } } + public Int32 HasMinMaxLevel => this.HasMinMaxState ? 1 : 0; public Int32 WakeupDefault { get; private set; } public Boolean HasDefaultState { get; private set; } - public Int32 HasDefaultLevel { get { return (this.HasDefaultState) ? 1 : 0; } } + public Int32 HasDefaultLevel => this.HasDefaultState ? 1 : 0; public DateTime LastWakeup { get; private set; } public DateTime LastSleep { get; private set; } #endregion #region Constructor - public Wakeup(JsonData json, Tuple id, HttpConnection http, Boolean polling) : base(json, id, http, polling) { - this.InitComplex(json); - } + public Wakeup(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) : base(id, http, polling, name) => this.InitComplex(json); private void InitComplex(JsonData json) { if (json.Keys.Contains("data")) { @@ -84,25 +79,21 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region ACommandClass - 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 String ToString() => "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 }, - { "HasMinMaxState", this.HasMinMaxState }, - { "HasMinMaxLevel", this.HasMinMaxLevel }, - { "WakeupDefault", this.WakeupDefault }, - { "HasDefaultState", this.HasDefaultState }, - { "HasDefaultLevel", this.HasDefaultLevel }, - { "LastWakeup", this.LastWakeup.ToString() }, - { "LastSleep", this.LastSleep.ToString() } - }; - } + public override Dictionary ToDictionary() => new Dictionary { + { "Interval", this.Interval }, + { "AgainstNode", this.AgainstNode }, + { "WakeupMin", this.WakeupMin }, + { "WakeupMax", this.WakeupMax }, + { "HasMinMaxState", this.HasMinMaxState }, + { "HasMinMaxLevel", this.HasMinMaxLevel }, + { "WakeupDefault", this.WakeupDefault }, + { "HasDefaultState", this.HasDefaultState }, + { "HasDefaultLevel", this.HasDefaultLevel }, + { "LastWakeup", this.LastWakeup.ToString() }, + { "LastSleep", this.LastSleep.ToString() } + }; internal override void SetUpdate(JsonData json, Match match) { Boolean success = false; @@ -160,9 +151,7 @@ namespace BlubbFish.IoT.Zway.Devices.CommandClasses { #endregion #region ISenml - protected override List ToSenmlList() { - return new List() { }; - } + protected override List ToSenmlList() => new List() { }; #endregion } } diff --git a/Zway/Devices/Device.cs b/Zway/Devices/Device.cs index b4a57da..f8f8a94 100644 --- a/Zway/Devices/Device.cs +++ b/Zway/Devices/Device.cs @@ -2,8 +2,10 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Text.RegularExpressions; + using BlubbFish.IoT.Zway.Events; -using BlubbFish.IoT.Zway.lib; +using BlubbFish.IoT.Zway.lib.Zway; + using LitJson; namespace BlubbFish.IoT.Zway.Devices { @@ -18,15 +20,21 @@ namespace BlubbFish.IoT.Zway.Devices { 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; + private Device(JsonData json, Int32 id, HttpConnection http, Boolean polling, ReadOnlyDictionary> names) { + this.Id = id; 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"; + + Int32 ManufacturerId = json["data"].ContainsKey("manufacturerId") && json["data"]["manufacturerId"].IsObject && json["data"]["manufacturerId"].ContainsKey("value") && json["data"]["manufacturerId"]["value"] != null && json["data"]["manufacturerId"]["value"].IsInt ? (Int32)json["data"]["manufacturerId"]["value"] : 0; + Int32 ProductType = json["data"].ContainsKey("manufacturerProductType") && json["data"]["manufacturerProductType"].IsObject && json["data"]["manufacturerProductType"].ContainsKey("value") && json["data"]["manufacturerProductType"]["value"] != null && json["data"]["manufacturerProductType"]["value"].IsInt ? (Int32)json["data"]["manufacturerProductType"]["value"] : 0; + Int32 ProductId = json["data"].ContainsKey("manufacturerProductId") && json["data"]["manufacturerProductId"].IsObject && json["data"]["manufacturerProductId"].ContainsKey("value") && json["data"]["manufacturerProductId"]["value"] != null && json["data"]["manufacturerProductId"]["value"].IsInt ? (Int32)json["data"]["manufacturerProductId"]["value"] : 0; + ReadOnlyDictionary descriptions = new ReadOnlyDictionary(new Dictionary()); + if(names.ContainsKey(ManufacturerId + "-" + ProductType + "-" + ProductId)) { + descriptions = names[ManufacturerId + "-" + ProductType + "-" + ProductId]; } + this.Name = json["data"].Keys.Contains("givenName") && json["data"]["givenName"].Keys.Contains("value") ? json["data"]["givenName"]["value"].ToString() : "Unknown"; + + this.CreateInstances(json["instances"], http, descriptions); + foreach (KeyValuePair item in this.Instances) { item.Value.Update += this.InstanceUpdate; } @@ -46,14 +54,12 @@ namespace BlubbFish.IoT.Zway.Devices { } } - private void InstanceUpdate(Object sender, DeviceUpdateEvent e) { - this.Update?.Invoke(this, e); - } + private void InstanceUpdate(Object sender, DeviceUpdateEvent e) => this.Update?.Invoke(this, e); - private void CreateInstances(JsonData json, HttpConnection http) { + private void CreateInstances(JsonData json, HttpConnection http, ReadOnlyDictionary names) { 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); + Instance i = Instance.CreateInstance(json[instanceid], (this.Id, Int32.Parse(instanceid)), http, this.polling, (this.Name, names)); if (i != null) { instances.Add(Int32.Parse(instanceid), i); } @@ -61,18 +67,9 @@ namespace BlubbFish.IoT.Zway.Devices { 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; - } + internal static Device CreateDevice(JsonData json, Int32 id, HttpConnection http, Boolean polling, ReadOnlyDictionary> names) => json.Keys.Contains("instances") && json["instances"].Count > 0 && json.Keys.Contains("data") && id != 1 ? new Device(json, id, http, polling, names) : null; - public override String ToString() { - return this.Name+"_"+this.Id+" ["+this.Instances.Count+"]"; - } + public override String ToString() => this.Name + "_" + this.Id + " [" + this.Instances.Count + "]"; internal void SetUpdate(JsonData json, Match match) { if (match.Groups[2].Value == "data.lastReceived") { diff --git a/Zway/Devices/Instance.cs b/Zway/Devices/Instance.cs index f267740..ec975e8 100644 --- a/Zway/Devices/Instance.cs +++ b/Zway/Devices/Instance.cs @@ -1,16 +1,20 @@ 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 BlubbFish.IoT.Zway.lib.Zway; + using LitJson; namespace BlubbFish.IoT.Zway.Devices { public class Instance { private DateTime nextwakeup; private readonly Boolean polling; + private readonly String instanceName; + private readonly String deviceName; public delegate void UpdatedInstance(Object sender, DeviceUpdateEvent e); public event UpdatedInstance Update; @@ -19,33 +23,27 @@ namespace BlubbFish.IoT.Zway.Devices { 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; + private Instance(JsonData json, (Int32 device, Int32 instance) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) { + this.DeviceId = id.device; + this.InstanceId = id.instance; this.polling = polling; - this.CreateInstances(json["commandClasses"], http); + this.instanceName = name.descriptions.ContainsKey(this.InstanceId.ToString()) ? name.descriptions[this.InstanceId.ToString()] : ""; + this.deviceName = name.device; + this.CreateClasses(json["commandClasses"], http, name); 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 MakePolltimer() => this.nextwakeup = this.CommandClasses.ContainsKey(ACommandClass.Classes.Wakeup) ? ((Wakeup)this.CommandClasses[ACommandClass.Classes.Wakeup]).LastWakeup.AddSeconds(((Wakeup)this.CommandClasses[ACommandClass.Classes.Wakeup]).Interval).AddSeconds(-20) : DateTime.Now.AddSeconds(60); - private void ClassUpdate(Object sender, DeviceUpdateEvent e) { - this.Update?.Invoke(this, e); - } + private void ClassUpdate(Object sender, DeviceUpdateEvent e) => this.Update?.Invoke(this, e); - private void CreateInstances(JsonData json, HttpConnection http) { + private void CreateClasses(JsonData json, HttpConnection http, (String device, ReadOnlyDictionary descriptions) name) { 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); + ACommandClass c = ACommandClass.CreateClass(json[commandid], (this.DeviceId, this.InstanceId, (ACommandClass.Classes)Int32.Parse(commandid)), http, this.polling, name); if (c != null) { commands.Add((ACommandClass.Classes)Int32.Parse(commandid), c); } @@ -53,18 +51,9 @@ namespace BlubbFish.IoT.Zway.Devices { 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; - } + internal static Instance CreateInstance(JsonData json, (Int32 device, Int32 instance) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) => json.Keys.Contains("commandClasses") && json["commandClasses"].Count > 0 && json.Keys.Contains("data") ? new Instance(json, id, http, polling, name) : null; - public override String ToString() { - return "Instance: " + this.DeviceId + "-" + this.InstanceId + " [" + this.CommandClasses.Count + "]"; - } + public override String ToString() => "Instance "+this.deviceName+""+(this.instanceName != ""?" ["+ this.instanceName +"]":"") +": " + this.DeviceId + "-" + this.InstanceId + " [" + this.CommandClasses.Count + "]"; internal void Poll() { if(DateTime.Now > this.nextwakeup) { diff --git a/Zway/Events/DeviceUpdateEvent.cs b/Zway/Events/DeviceUpdateEvent.cs index 0ad9158..284b99d 100644 --- a/Zway/Events/DeviceUpdateEvent.cs +++ b/Zway/Events/DeviceUpdateEvent.cs @@ -1,8 +1,4 @@ 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 { diff --git a/Zway/Interfaces/ACommandClass.cs b/Zway/Interfaces/ACommandClass.cs index 3ed8ea5..7daca8e 100644 --- a/Zway/Interfaces/ACommandClass.cs +++ b/Zway/Interfaces/ACommandClass.cs @@ -2,10 +2,14 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Text.RegularExpressions; + using BlubbFish.IoT.Zway.Events; using BlubbFish.IoT.Zway.lib; +using BlubbFish.IoT.Zway.lib.Zway; +using BlubbFish.Utils; using BlubbFish.Utils.IoT.Interfaces; using BlubbFish.Utils.IoT.Interfaces.Language; + using LitJson; namespace BlubbFish.IoT.Zway.Interfaces { @@ -84,11 +88,11 @@ namespace BlubbFish.IoT.Zway.Interfaces { #endregion #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; + protected ACommandClass((Int32 device, Int32 instance, Classes commandclass, Int32 sensor) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) { + this.DeviceId = id.device; + this.Instance = id.instance; + this.Commandclass = id.commandclass; + this.SensorId = id.sensor; this.http = http; this.LastUpdate = DateTime.Now; this.Polling = polling; @@ -96,15 +100,12 @@ namespace BlubbFish.IoT.Zway.Interfaces { 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]; - } + this.Name = name.descriptions.ContainsKey(this.Instance + "-" + (Int32)this.Commandclass + "-" + this.SensorId) ? name.device + " " + name.descriptions[this.Instance + "-" + (Int32)this.Commandclass + "-" + this.SensorId] : name.device + " " + this.Instance + "-" + this.Commandclass; } - - protected ACommandClass(JsonData json, Tuple id, HttpConnection http, Boolean polling) { - this.DeviceId = id.Item1; - this.Instance = id.Item2; - this.Commandclass = id.Item3; + protected ACommandClass((Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) { + this.DeviceId = id.device; + this.Instance = id.instance; + this.Commandclass = id.commandclass; this.http = http; this.LastUpdate = DateTime.Now; this.Polling = polling; @@ -112,67 +113,53 @@ namespace BlubbFish.IoT.Zway.Interfaces { 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]; - } + this.Name = name.descriptions.ContainsKey(this.Instance + "-" + (Int32)this.Commandclass) ? name.device + " " + name.descriptions[this.Instance + "-" + (Int32)this.Commandclass] : name.device + " " + this.Instance + "-" + this.Commandclass; } - - internal static ACommandClass CreateInstance(JsonData json, Tuple id, HttpConnection http, Boolean polling) { - if (json.Keys.Contains("name") && + internal static ACommandClass CreateClass(JsonData json, (Int32 device, Int32 instance, Classes commandclass) id, HttpConnection http, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) { + 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); + !Enum.IsDefined(typeof(IgnoredClasses), (Int32)id.commandclass) && Enum.IsDefined(typeof(Classes), id.commandclass)) { + String objectName = "BlubbFish.IoT.Zway.Devices.CommandClasses." + id.commandclass.ToString().ToUpperLower(); + return GetInstanceConcrete(objectName, json, http, id, polling, name); } - if (!Enum.IsDefined(typeof(IgnoredClasses), (Int32)id.Item3) && !Enum.IsDefined(typeof(Classes), id.Item3)) { - Helper.WriteError("CommandClass " + id.Item3 + " not exist. (" + id.Item1 + ", " + id.Item2 + ")"); + if (!Enum.IsDefined(typeof(IgnoredClasses), (Int32)id.commandclass) && !Enum.IsDefined(typeof(Classes), id.commandclass)) { + Helper.WriteError("CommandClass " + id.commandclass + " not exist. (" + id.device + ", " + id.instance + ")"); } return null; } - - private static ACommandClass GetInstanceConcrete(String objectName, JsonData json, HttpConnection http, Tuple id, Boolean polling) { - Type t = null; + private static ACommandClass GetInstanceConcrete(String objectName, JsonData json, HttpConnection http, (Int32 device, Int32 instance, Classes commandclass) id, Boolean polling, (String device, ReadOnlyDictionary descriptions) name) { try { - t = Type.GetType(objectName, true); + Type t = Type.GetType(objectName, true); + return (ACommandClass)t.GetConstructor(new Type[] { typeof(JsonData), typeof((Int32 device, Int32 instance, Classes commandclass)), typeof(HttpConnection), typeof(Boolean), typeof((String device, ReadOnlyDictionary descriptions)) }).Invoke(new Object[] { json, id, http, polling, name }); } 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()"); + 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 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 + ")"); + 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; Boolean pollonce = false; @@ -185,25 +172,15 @@ namespace BlubbFish.IoT.Zway.Interfaces { } } if (poll || pollonce) { - this.http.GetVoid("ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + ((Int32)this.Commandclass).ToString() + "].Get()"); + 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 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, Double) value) => this.http.GetVoid("/ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + ((Int32)this.Commandclass).ToString() + "].Set(" + value.Item1 + "," + value.Item2 + ")"); + protected void SetTriple((Double, Double, Double) value) => this.http.GetVoid("/ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + ((Int32)this.Commandclass).ToString() + "].Set(" + value.Item1 + "," + value.Item2 + "," + value.Item3 + ")"); 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; @@ -217,13 +194,11 @@ namespace BlubbFish.IoT.Zway.Interfaces { 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()"); + this.http.GetVoid("/ZWave.zway/Run/devices[" + this.DeviceId + "].instances[" + this.Instance + "].commandClasses[" + ((Int32)this.Commandclass).ToString() + "].Reset()"); } } - #endregion #region InternalHelper @@ -234,7 +209,6 @@ namespace BlubbFish.IoT.Zway.Interfaces { } return json; } - protected List ToSenmlListSub() { List list = new List(); foreach (KeyValuePair item in this.Sub) { @@ -245,10 +219,7 @@ namespace BlubbFish.IoT.Zway.Interfaces { #endregion #region IMqtt - public String MqttTopic() { - return this.DeviceId + "/" + this.Instance + "/" + ((Int32)this.Commandclass).ToString() + (this.IsSub ? "/" + this.SensorId : ""); - } - + public String MqttTopic() => this.DeviceId + "/" + this.Instance + "/" + ((Int32)this.Commandclass).ToString() + (this.IsSub ? "/" + this.SensorId : ""); public String ToJson() { Dictionary json = this.ToDictionary(); json.Add("LastUpdate", this.LastUpdate.ToString()); @@ -259,6 +230,7 @@ namespace BlubbFish.IoT.Zway.Interfaces { #endregion #region ISenml + public String SenmlTopic() => "LS/v2/ZGW/"; public String ToSenml() { List l = this.ToSenmlList(); if(l.Count == 0) { @@ -271,10 +243,6 @@ namespace BlubbFish.IoT.Zway.Interfaces { }; return JsonMapper.ToJson(json); } - - public String SenmlTopic() { - return "LS/v2/ZGW/"; - } #endregion #region Abstract diff --git a/Zway/Zway.csproj b/Zway/Zway.csproj index 9cdafd3..e9f493c 100644 --- a/Zway/Zway.csproj +++ b/Zway/Zway.csproj @@ -5,50 +5,57 @@ BlubbFish.IoT.Zway Zway Zway.IoT.BlubbFish - 1.5.1 - 1.5.1.0 - 1.5.1.0 + 1.6.0 de-DE Library that speaks with zwave module/server BlubbFish BlubbFish - Copyright © 2017 - 09.01.2021 + Copyright © 2017 - 15.01.2022 LICENCE https://git.blubbfish.net/vs_projects/Zway https://git.blubbfish.net/vs_projects/Zway.git git - 1.5.1 Tiny fix for nullpointer exception -1.5.0 Throw Exception if 3 times failed to connect to Raspberry server, add 3 new commandlcasses to IgnoredClasses -1.4.4 Add Inclusioncontroller -1.4.3 Fixing Issue with Math.Abs(l) -1.4.2.0 Some sensors make wrong measurements near 0 not exactly 0, so ABS(value) >= 0.1 is alse false -1.4.1.0 fixing Senml topics and data -1.4.0.0 Create Senml Messages for Linksmart -1.3.6.0 Better levelcheck and Alarmsensor added -1.3.5.3 Change Level to numeric and create State for Bollean values, because telegraf only parse numeric -1.3.5.2 Check to avoid megapeaks in data now also for temperature -1.3.5.1 Check to avoid megapeaks in Data -1.3.5.0 Add Sensorbinary, Alarm and SceneControllerConf and changed DeviceUpdateEvent so its not as complicate as before. Also fixing the gernal Json Names to the right values -1.3.4.1 Fixing some Json Topics -1.3.4.0 Fixing Json Names -1.3.3.0 fixing polling once bug -1.3.2.0 Forgot some settings, now configuration setting also works again -1.3.1.0 Tiny fix for mqtt -1.3.0.0 Remove Interface ICommandClass.cs and dublicated classes CommandClass.cs and CommandClassSub.cs, put them into the abstracted class ACommandClass.cs -1.0.0.0 Telegram Condition + + 1.6.0 - 2022-01-15 - Refactoring is the key + 1.5.1 - 2018-10-29 - Tiny fix for nullpointer exception + 1.5.0 - 2018-09-29 - Throw Exception if 3 times failed to connect to Raspberry server, add 3 new commandlcasses to IgnoredClasses + 1.4.4 - 2018-06-02 - Ignore Inclusioncontroller + 1.4.3 - 2018-05-12 - Fixing Issue with Math.Abs(l) + 1.4.2.0 - 2018-05-10 - Some sensors make wrong measurements near 0 not exactly 0, so ABS(value) >= 0.1 is alse false + 1.4.1.0 - 2018-05-07 - fixing Senml topics and data + 1.4.0.0 - 2018-05-03 - Create Senml Messages for Linksmart + 1.3.6.0 - 2018-01-01 - Better levelcheck and Alarmsensor added + 1.3.5.3 - 2017-12-25 - Change Level to numeric and create State for Bollean values, because telegraf only parse numeric + 1.3.5.2 - 2017-12-24 - Check to avoid megapeaks in data now also for temperature + 1.3.5.1 - 2017-12-23 - Check to avoid megapeaks in Data + 1.3.5.0 - 2017-12-22 - Add Alarm and SceneControllerConf + 1.3.4.1 - 2017-12-21 - SensorBinary and Fixing + 1.3.4.0 - 2017-12-19 - Fixing Json Names + 1.3.3.0 - 2017-12-19 - fixing polling once bug + 1.3.2.0 - 2017-12-18 - Forgot some settings, now configuration setting also works again + 1.3.1.0 - 2017-12-17 - Tiny fix for mqtt + 1.3.0.0 - 2017-12-17 - Simpler CommandClass + 1.2.0.0 - 2017-12-06 - F4G Faker + 1.1.2.0 - 2017-12-03 - Tiny Fix + 1.1.1.0 - 2017-11-25 - Massive improvement + 1.1.0.0 - 2017-11-20 - First working Version + 1.0.0.0 - 2017-10-29 - Init + + - - - + + + + True diff --git a/Zway/ZwayController.cs b/Zway/ZwayController.cs index 2bf26f9..a94121a 100644 --- a/Zway/ZwayController.cs +++ b/Zway/ZwayController.cs @@ -1,194 +1,46 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Globalization; -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; +using BlubbFish.Utils; namespace BlubbFish.IoT.Zway { public class ZwayController : IDisposable { - private HttpConnection http; - private Thread updatethread; - private Thread pollthread; - public static ReadOnlyDictionary namelist; - private readonly Boolean polling; + private ZwayBoard zwayboard; + private Boolean _IsInit = false; public delegate void DataUpdate(Object sender, DeviceUpdateEvent e); - public event DataUpdate Update; + public event DataUpdate Recieved; - 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; + public ZwayController(Dictionary settings, Dictionary> names, Boolean enablePoll = true) { + try { + Console.WriteLine("BlubbFish.IoT.Zway.ZwayController.Construct()"); + this.zwayboard = ZwayBoard.GetInstance(settings, new ReadOnlyDictionary>(names), enablePoll); + this.zwayboard.Connect(); + this.zwayboard.Update += this.DeviceUpdate; + this._IsInit = true; + } catch(Exception e) { + Helper.WriteError("Error while Loading BlubbFish.IoT.Zway.ZwayController.ZwayController: " + e.Message + "\n\n" + e.StackTrace); + throw; } } - private void DeviceUpdate(Object sender, DeviceUpdateEvent e) { - this.Update?.Invoke(sender, e); - } + public ACommandClass GetCommandClass(String id) => this.zwayboard.GetCommandClass(id); + public ReadOnlyDictionary Devices => this.zwayboard.Devices; - 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; - DateTime lastRequest = DateTime.Now.AddSeconds(-2); - while (true) { - Int64 date = ((DateTimeOffset)lastRequest).ToUnixTimeSeconds(); - lastRequest = DateTime.Now; - 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); - } + private void DeviceUpdate(Object sender, DeviceUpdateEvent e) => this.Recieved?.Invoke(sender, e); public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); + if(this._IsInit) { + Console.WriteLine("BlubbFish.IoT.Zway.ZwayController.Dispose()"); + this._IsInit = false; + this.zwayboard.Dispose(); + this.zwayboard = null; + } } - #endregion } } diff --git a/Zway/lib/Helper.cs b/Zway/lib/Helper.cs deleted file mode 100644 index 1477cf0..0000000 --- a/Zway/lib/Helper.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace BlubbFish.IoT.Zway.lib { - class Helper { - internal static void WriteError(String text) { - Console.ForegroundColor = ConsoleColor.Red; - Console.Error.WriteLine("ERROR: "+text); - Console.ResetColor(); - } - } -} diff --git a/Zway/lib/HttpClient.cs b/Zway/lib/HttpClient.cs deleted file mode 100644 index 18e041a..0000000 --- a/Zway/lib/HttpClient.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.IO; -using System.Net; -using System.Text; -using LitJson; - -namespace BlubbFish.IoT.Zway.lib { - public class HttpConnection { - private readonly String auth; - private readonly String server; - private static readonly 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.GetVoid("ZAutomation/api/v1/status"); - } - - internal JsonData GetJson(String v) { - String text = null; - for (Int32 i = 0; i < 3; i++) { - try { - text = this.GetString(v); - break; - } catch (Exception e) { - Helper.WriteError(e.Message); - if(i==2) { - throw; - } - System.Threading.Thread.Sleep(30000); - } - } - if(text == null) { - return new JsonData(); - } - try { - return JsonMapper.ToObject(text); - } catch(Exception) { - return new JsonData(); - } - } - - internal void GetVoid(String v) { - for (Int32 i = 0; i < 3; i++) { - try { - this.GetString(v, false); - break; - } catch (Exception e) { - Helper.WriteError(e.Message); - if (i == 2) { - throw; - } - System.Threading.Thread.Sleep(30000); - } - } - } - - private String GetString(String v, Boolean withoutput = true) { - String ret = null; - lock (getLock) { - HttpWebRequest request = WebRequest.CreateHttp(this.server + v); - request.Timeout = 10000; - 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/lib/Zway/HttpClient.cs b/Zway/lib/Zway/HttpClient.cs new file mode 100644 index 0000000..696eb4d --- /dev/null +++ b/Zway/lib/Zway/HttpClient.cs @@ -0,0 +1,61 @@ +using System; +using System.IO; +using System.Net; +using System.Text; +using System.Threading.Tasks; + +using BlubbFish.Utils; + +using LitJson; + +namespace BlubbFish.IoT.Zway.lib.Zway { + public class HttpConnection { + private readonly HttpEndpoint http; + + internal HttpConnection(String server, String user, String pass) { + this.http = new HttpEndpoint("http://" + server, ("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(user + ":" + pass)))); + this.Init(); + } + + private void Init() => this.http.RequestString("/ZAutomation/api/v1/status", "", false).Wait(); + + internal async Task GetJson(String v) { + String text = null; + for (Int32 i = 0; i < 3; i++) { + try { + text = await this.http.RequestString(v); + break; + } catch (Exception e) { + Helper.WriteError(e.Message); + if(i==2) { + throw; + } + System.Threading.Thread.Sleep(30000); + } + } + if(text == null) { + return new JsonData(); + } + try { + return JsonMapper.ToObject(text); + } catch(Exception) { + return new JsonData(); + } + } + + internal async void GetVoid(String address) { + for (Int32 i = 0; i < 3; i++) { + try { + _ = await this.http.RequestString(address, "", false); + break; + } catch (Exception e) { + Helper.WriteError(e.Message); + if (i == 2) { + throw; + } + System.Threading.Thread.Sleep(30000); + } + } + } + } +} diff --git a/Zway/lib/Zway/Zway.cs b/Zway/lib/Zway/Zway.cs new file mode 100644 index 0000000..5bcd59a --- /dev/null +++ b/Zway/lib/Zway/Zway.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Text.RegularExpressions; +using System.Threading; + +using BlubbFish.IoT.Zway.Devices; +using BlubbFish.IoT.Zway.Interfaces; + +using LitJson; + +namespace BlubbFish.IoT.Zway.lib.Zway { + class Zway : ZwayBoard { + private HttpConnection http; + private Thread updatethread; + private Boolean updatethreadRunning = false; + private Thread pollthread; + private Boolean pollthreadRunning = false; + + #region abstract functions + public Zway(Dictionary settings, ReadOnlyDictionary> names, Boolean enablePoll) : base(settings, names, enablePoll) { + } + public override void Connect() { + this.http = new HttpConnection(this.config["server"], this.config["user"], this.config["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").Result); + this.updatethread = new Thread(this.Updater); + this.updatethreadRunning = true; + this.updatethread.Start(); + this.pollthread = new Thread(this.Poll); + this.pollthreadRunning = true; + this.pollthread.Start(); + foreach(KeyValuePair item in this.Devices) { + item.Value.Update += this.DeviceUpdate; + } + } + public override void Dispose() { + this.updatethreadRunning = false; + while(this.updatethread != null && this.updatethread.IsAlive) { + Thread.Sleep(10); + } + this.updatethread = null; + + this.pollthreadRunning = false; + while(this.pollthread != null && this.pollthread.IsAlive) { + Thread.Sleep(10); + } + this.pollthread = null; + + this.pollthread.Abort(); + this.Devices = null; + } + #endregion + + #region Threaded runners + 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; + DateTime lastRequest = DateTime.Now.AddSeconds(-2); + while(this.updatethreadRunning) { + Int64 date = ((DateTimeOffset)lastRequest).ToUnixTimeSeconds(); + lastRequest = DateTime.Now; + JsonData notifications = this.http.GetJson("/ZWave.zway/Data/" + date).Result; + 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 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(this.pollthreadRunning) { + foreach(KeyValuePair item in this.Devices) { + item.Value.Poll(); + } + Thread.Sleep(1000); + } + } + #endregion + + #region External functions + public override ACommandClass GetCommandClass(String id) { + String[] addr = id.Split('-'); + return addr.Length == 3 || addr.Length == 4 ? this.GetCommandClass(Int32.Parse(addr[0]), Int32.Parse(addr[1]), (ACommandClass.Classes)Int32.Parse(addr[2]), addr.Length == 4 ? Int32.Parse(addr[3]) : -1) : null; + } + 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; + } + #endregion + + #region Internal functions + private void CreateDevices(JsonData json) { + Dictionary devices = new Dictionary(); + foreach(String deviceid in json.Keys) { + Device d = Device.CreateDevice(json[deviceid], Int32.Parse(deviceid), this.http, this.polling, this.names); + if(d != null) { + devices.Add(Int32.Parse(deviceid), d); + } + } + this.Devices = new ReadOnlyDictionary(devices); + } + private 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; + } + #endregion + } +} diff --git a/Zway/lib/ZwayBoard.cs b/Zway/lib/ZwayBoard.cs new file mode 100644 index 0000000..c44f245 --- /dev/null +++ b/Zway/lib/ZwayBoard.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; + +using BlubbFish.IoT.Zway.Devices; +using BlubbFish.IoT.Zway.Events; +using BlubbFish.IoT.Zway.Interfaces; +using BlubbFish.Utils; + +namespace BlubbFish.IoT.Zway.lib { + public abstract class ZwayBoard : IDisposable { + protected Dictionary config; + protected Boolean polling; + protected ReadOnlyDictionary> names; + + public delegate void DataUpdate(Object sender, DeviceUpdateEvent e); + public event DataUpdate Update; + + public ReadOnlyDictionary Devices { + get; protected set; + } + + #region Constructor and deconstructor + protected ZwayBoard(Dictionary settings, ReadOnlyDictionary> names, Boolean enablePoll) { + this.config = settings; + this.names = names; + this.polling = enablePoll; + } + public static ZwayBoard GetInstance(Dictionary settings, ReadOnlyDictionary> names, Boolean enablePoll) { + if(settings.Count == 0) { + throw new ArgumentException("Missing block [zway] in settingsfile"); + } else if(!settings.ContainsKey("type")) { + throw new ArgumentException("Missing type for [zway] in settingsfile"); + } + String object_sensor = "BlubbFish.IoT.Zway.lib." + settings["type"].ToUpperLower() + "." + settings["type"].ToUpperLower(); + try { + Type t = Type.GetType(object_sensor, true); + return (ZwayBoard)t.GetConstructor(new Type[] { typeof(Dictionary), typeof(ReadOnlyDictionary>), typeof(Boolean) }).Invoke(new Object[] { settings, names, enablePoll }); + } catch(TypeLoadException) { + throw new ArgumentException("Configuration: " + settings["type"] + " is not a ZwayBoard"); + } catch(FileNotFoundException) { + throw new Exception("Driver " + object_sensor + " could not load!"); + } + + } + public abstract void Dispose(); + #endregion + + #region External + public abstract void Connect(); + public abstract ACommandClass GetCommandClass(String id); + #endregion + + protected void DeviceUpdate(Object sender, DeviceUpdateEvent e) => this.Update?.Invoke(sender, e); + } +}