mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[souliss] Souliss Binding initial contribution (#11083)
* Initial Contribution Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> Co-Authored-By: Tonino Fazio <fazioa@gmail.com> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update pom.xml spotless-apply Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> Co-Authored-By: Tonino Fazio <fazioa@gmail.com> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Renamed healty in healthy (simple word error) Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update thing-types.xml onOff to CamelCase Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * camelCase fixed on some types Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update bundles/org.openhab.binding.souliss/README.md Co-authored-by: Matthew Skinner <matt@pcmus.com> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update bundles/org.openhab.binding.souliss/README.md Co-authored-by: Matthew Skinner <matt@pcmus.com> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update README.md Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update README.md Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update README.md Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update README.md Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * fixed camelCase on thhings parameters Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update thing-types.xml fixed label cases Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update thing-types.xml Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Revert "Update thing-types.xml" This reverts commit 5c19fbc69dee53f41d56a847bc82660192e0158c. Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Initial Contribution Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> Co-Authored-By: Tonino Fazio <fazioa@gmail.com> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Fix some errors (Nullable issues) and pom.xml format Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update pom.xml spotless-apply Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> Co-Authored-By: Tonino Fazio <fazioa@gmail.com> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissT11Handler.java Default case on switch (handlecommand ) Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * added secoresend to t31 skeleton and variable smessage fix declaration Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Initial Contribution Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> Co-Authored-By: Tonino Fazio <fazioa@gmail.com> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update pom.xml spotless-apply Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> Co-Authored-By: Tonino Fazio <fazioa@gmail.com> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissGatewayHandler.java Cutted comments and uneccessary log on gw status Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Renamed healty in healthy (simple word error) Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * fixed camelCase on thhings parameters Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update thing-types.xml Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * cleanup and quality code fixes Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissBindingUDPDecoder.java fixed some npe Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * npe check fix Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissCommonCommands.java Remove comments unused code Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissCommonCommands.java commented out code unused Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissCommonCommands.java remove unused code commented out Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissBindingUDPServerJob.java remove unused code comments Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissBindingSendDispatcherJob.java fixed logger trace and remove unused code comments Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update bundles/org.openhab.binding.souliss/README.md Co-authored-by: Matthew Skinner <matt@pcmus.com> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * removed completely unnecessary comments Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * fixed some thing types cases Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissGatewayHandler.java removed unnecessary log line Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissGatewayHandler.java removed unnecessary comment Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * loggers as final ! Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissGatewayJobHealthy.java removed unnecessary logs Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissGatewayJobPing.java removed unnecessary logs Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * fixed redundancy on types checks Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update README.md fixed examples parms Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissGatewayHandler.java changed parm var name bridge Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update bundles/org.openhab.binding.souliss/src/main/java/org/openhab/binding/souliss/handler/SoulissT11Handler.java remove comments Co-authored-by: Matthew Skinner <matt@pcmus.com> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update bundles/org.openhab.binding.souliss/src/main/java/org/openhab/binding/souliss/handler/SoulissT12Handler.java comments removed Co-authored-by: Matthew Skinner <matt@pcmus.com> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update bundles/org.openhab.binding.souliss/src/main/java/org/openhab/binding/souliss/handler/SoulissT13Handler.java comments removed Co-authored-by: Matthew Skinner <matt@pcmus.com> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * fixed thing type on README and some case on xml thing types Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update README.md cutted part about manually thing config specs on README . Who use oh already knows it . Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Code cleanup and optimizations based on @Skinah tips Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * fixes from @Skinah suggestions Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> Fixed typeid's on costants files Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * various optimizations follow @Skinah tips (thanks!) Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * spotless:apply fix Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * fixes constants and channel id types of t31 Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Fix various NPE warnings Fixes many ... Some added suppresswarnings. Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissGenericActionMessage.java Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Refactor handlers into souliss.internal.handler Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * spoless:apply fix Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * spotless:apply Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * fix t19 (securesend parm ,labels and setvalue) Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update thing-types.xml spotless:apply fix Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update bundles/org.openhab.binding.souliss/README.md Co-authored-by: Fabian Wolter <github@fabian-wolter.de> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update bundles/org.openhab.binding.souliss/README.md Co-authored-by: Fabian Wolter <github@fabian-wolter.de> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update bundles/org.openhab.binding.souliss/README.md Co-authored-by: Fabian Wolter <github@fabian-wolter.de> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update bundles/org.openhab.binding.souliss/README.md Co-authored-by: Fabian Wolter <github@fabian-wolter.de> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update bundles/org.openhab.binding.souliss/README.md Co-authored-by: Fabian Wolter <github@fabian-wolter.de> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * spotless:apply fix Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Null checks Warnings removed (mitigated with local copy of field) - removed comments Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * syntax sugar fixed of consts and section removed from README Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * moved files to internal package Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissHandlerFactory.java check types on object and not on strings Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * various fixes based on @fwolter Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Gateway ip address regex on config param Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * changed description of gateway ip on param Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * formatted tables in README.md Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * removed comments Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * wip for npe checks - breaking functionality :-( Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * spotless fix Author: Luca Calcaterra <calcaterra.luca@gmail.com> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * fix contrib header in some files Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * reworked udp - only one bridge allowed and UDP listen only to bridge port 230 ...passing datagramsocket with soulissnetworkparameter class Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * quite ok. Where to close socket in case of thread interruption ? Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * wip Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * wip2 Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * wip3 udp receive but not on vpn Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Classes names Refactor Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * wip Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * wip Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * replaced datagramsocket with nio socket- seems to be ok Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update UDPListenDiscoverRunnable.java Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Fixed some null checks removed securesend option (only t11 end similar) Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * dummy initial value of raw values - removed thread on decoder line Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * fix t19 ex catch and broadcast function Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Reworked Config of Gateway as Class (todo check nulls...) Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Added representation property on gw - some cleanups Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissGatewayHandler.java cleanup unused vars Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * refactor methods of gw parameters Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * WIP to remove NetworkParameter class Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * wip refactor DiscoverResult Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * wip remove networkparameters Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * WIP remove NetworkParameter Class. Things online only on a health message Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * WIP Fix Topics Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * WIP2 Fix topics Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update pom.xml upgrade binding version to 3.2 snapshot Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * topics bound to bridge - seems to be ok. Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * remove NetworkParameters class - topics ok but need parse rework Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * code cleanup and bugs check fix Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Add node and slot to property - other fixes Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * change default interval subscription -cleanup constants Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * WIP WAN Address gw Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * WAN option external network. Fixed Putin on commands - to test well Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * cleanup - safesend check WIP Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * fixed secursend for t11-18 Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * WIP Fix null checks Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissGenericHandler.java fixed wrong assignment of prop Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * null checks fixes for code quality Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * fixed listen port according to gw parm (default 23000) Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * nuances Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update thing-types.xml changed default values Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * CommonCommands to static - other fixes . seems quite ok, remain T31 to fix (securesend) Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update UDPListenDiscoverRunnable.java Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissGatewayHandler.java changed executor imp for udp Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * restored commoncommands non static Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SendDispatcherRunnable.java safesendcheck fix (not really) Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * various nuances (sonarlint) Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update README.md Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update bundles/org.openhab.binding.souliss/README.md Co-authored-by: Fabian Wolter <github@fabian-wolter.de> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update bundles/org.openhab.binding.souliss/README.md Co-authored-by: Fabian Wolter <github@fabian-wolter.de> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update README.md removed explain how oh works on example Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update bundles/org.openhab.binding.souliss/README.md Co-authored-by: Fabian Wolter <github@fabian-wolter.de> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update bundles/org.openhab.binding.souliss/src/main/feature/feature.xml Co-authored-by: Fabian Wolter <github@fabian-wolter.de> Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * @fwolter various fixes Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissT11Handler.java wrong header Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissT11Handler.java Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * fix headers descriptions before authors on all classes Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * all var on begin of classes and @nullable sugar syntax Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * removed @nullable on local vars Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * wip comments translations and cleanup Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * cleanup comments and translated them (if italian occourred) Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * @fwolter suggestions for approval...various fixes Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * various fixes based on @fwolter suggestions. Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * various fixes based on @fwolter suggestions. Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissGatewayHandler.java Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update thing-types.xml Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update UDPListenDiscoverRunnable.java hexutils usage Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissT22Handler.java removed unused method Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissT22Handler.java fix previous commit Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissT11Handler.java @Nullable on configuration Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * method to put bridge offline (network exception on listener) Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update thing-types.xml changed some channels to trigger type Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * WIP broken Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update thing-types.xml spotless:apply Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * various changes call super on initialize() of all handlers. Changed to QuantityType where appliable Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissGatewayDiscovery.java added uniqueId (ip of gateway+node+slot) as representationProperty Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * wip for load discovery component Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * big fixes and code quality improvments Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * fixes Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update SoulissGenericHandler.java Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> * Update README.md wrong format .. Signed-off-by: Luca Calcaterra <calcaterra.luca@gmail.com> Co-authored-by: Tonino Fazio <fazioa@gmail.com> Co-authored-by: Matthew Skinner <matt@pcmus.com> Co-authored-by: Fabian Wolter <github@fabian-wolter.de>
This commit is contained in:
parent
31668b3891
commit
649c865c16
@ -283,6 +283,7 @@
|
|||||||
/bundles/org.openhab.binding.sonos/ @kgoderis @lolodomo
|
/bundles/org.openhab.binding.sonos/ @kgoderis @lolodomo
|
||||||
/bundles/org.openhab.binding.sonyaudio/ @freke
|
/bundles/org.openhab.binding.sonyaudio/ @freke
|
||||||
/bundles/org.openhab.binding.sonyprojector/ @lolodomo
|
/bundles/org.openhab.binding.sonyprojector/ @lolodomo
|
||||||
|
/bundles/org.openhab.binding.souliss/ @lucacalcaterra @fazioa
|
||||||
/bundles/org.openhab.binding.spotify/ @Hilbrand
|
/bundles/org.openhab.binding.spotify/ @Hilbrand
|
||||||
/bundles/org.openhab.binding.squeezebox/ @digitaldan @mhilbush
|
/bundles/org.openhab.binding.squeezebox/ @digitaldan @mhilbush
|
||||||
/bundles/org.openhab.binding.surepetcare/ @renescherer @HerzScheisse
|
/bundles/org.openhab.binding.surepetcare/ @renescherer @HerzScheisse
|
||||||
|
@ -1393,6 +1393,11 @@
|
|||||||
<artifactId>org.openhab.binding.sonyprojector</artifactId>
|
<artifactId>org.openhab.binding.sonyprojector</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.binding.souliss</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openhab.addons.bundles</groupId>
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
<artifactId>org.openhab.binding.spotify</artifactId>
|
<artifactId>org.openhab.binding.spotify</artifactId>
|
||||||
|
13
bundles/org.openhab.binding.souliss/NOTICE
Normal file
13
bundles/org.openhab.binding.souliss/NOTICE
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
This content is produced and maintained by the openHAB project.
|
||||||
|
|
||||||
|
* Project home: https://www.openhab.org
|
||||||
|
|
||||||
|
== Declared Project Licenses
|
||||||
|
|
||||||
|
This program and the accompanying materials are made available under the terms
|
||||||
|
of the Eclipse Public License 2.0 which is available at
|
||||||
|
https://www.eclipse.org/legal/epl-2.0/.
|
||||||
|
|
||||||
|
== Source Code
|
||||||
|
|
||||||
|
https://github.com/openhab/openhab-addons
|
321
bundles/org.openhab.binding.souliss/README.md
Normal file
321
bundles/org.openhab.binding.souliss/README.md
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
# Souliss Binding
|
||||||
|
|
||||||
|
[Souliss](http://www.souliss.net/) is a networking framework for Arduino and compatibles boards, and is designed to let you easily build a smart home that is distributed over multiple boards via Ethernet, WiFi, wireless point-to-point and RS485 bus.
|
||||||
|
|
||||||
|
Souliss is an open-source and community driven project, you can use the [wiki](https://github.com/souliss/souliss/wiki) and [Community](https://github.com/souliss/souliss/wiki/Community) to get help and share your results.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
The binding requires a deployed network.
|
||||||
|
As a minimum, you need one Souliss node with Ethernet or WiFi access configured as a [Gateway](https://github.com/souliss/souliss/wiki/Gateway).
|
||||||
|
A Gateway is a special node that is able to communicate with the user interfaces.
|
||||||
|
The binding interacts as a user interface for Souliss.
|
||||||
|
|
||||||
|
A starting point is the [Souliss wiki](https://github.com/souliss/souliss/wiki).
|
||||||
|
The best is to start with a single node and connect with SoulissApp.
|
||||||
|
The code for networking activities of this binding is based on [SoulissApp](https://github.com/souliss/souliss/wiki/SoulissApp) code, so once connected with SoulissApp, you can move to openHAB directly.
|
||||||
|
|
||||||
|
You can use SoulissApp and the Souliss binding at the same time, and generally up to five (by default, but can be increased) user interfaces simultaneously.
|
||||||
|
|
||||||
|
### Sketches
|
||||||
|
|
||||||
|
The easiest way is start with a simple example to control an ON/OFF light (though a relay).
|
||||||
|
You can go to project [Souliss](https://github.com/souliss/souliss), see a lot of examples sketches: [Souliss examples](https://github.com/souliss/souliss/tree/friariello/examples)
|
||||||
|
|
||||||
|
|
||||||
|
## Discovery
|
||||||
|
|
||||||
|
First add a gateway (one only is permitted on LAN at this moment), then discovery can find other things (Souliss Typicals)
|
||||||
|
|
||||||
|
## Supported Things
|
||||||
|
|
||||||
|
In Souliss Framework a Typical is one of predefined logic dedicated to smart home devices like lights, heating or antitheft.
|
||||||
|
|
||||||
|
Typical can be one of T11, T12, T13, T14, etc...
|
||||||
|
|
||||||
|
They are defined [here](https://github.com/souliss/souliss/wiki/Typicals).
|
||||||
|
|
||||||
|
Typicals match directly with openHAB Thing type.
|
||||||
|
|
||||||
|
| Device type | Typical Code | Thing type |
|
||||||
|
|-----------------------------------------------------------|----------------|------------|
|
||||||
|
| ON/OFF Digital Output with Timer Option | T11 | t11 |
|
||||||
|
| ON/OFF Digital Output with AUTO mode | T12 | t12 |
|
||||||
|
| Digital Input Value | T13 | t13 |
|
||||||
|
| Pulse Digital Output | T14 | t14 |
|
||||||
|
| RGB LED Strip | T16 | t16 |
|
||||||
|
| ON/OFF Digital Output | T18 | t18 |
|
||||||
|
| Single Color LED Strip | T19 | t19 |
|
||||||
|
| Digital Input Pass Through | T1A | t1A |
|
||||||
|
| Motorized devices with limit switches | T21 | t21 |
|
||||||
|
| Motorized devices with limit switches and middle position | T22 | t22 |
|
||||||
|
| Temperature control | T31 | t31 |
|
||||||
|
| Anti-theft integration (Main) | T41 | t41 |
|
||||||
|
| Anti-theft integration (Peer) | T42 | t42 |
|
||||||
|
| Analog input, half-precision floating point | T51 | t51 |
|
||||||
|
| Temperature measure (-20, +50) °C | T52 | t52 |
|
||||||
|
| Humidity measure (0, 100) % | T53 | t53 |
|
||||||
|
| Light Sensor (0, 40) kLux | T54 | t54 |
|
||||||
|
| Voltage (0, 400) V | T55 | t55 |
|
||||||
|
| Current (0, 25) A | T56 | t56 |
|
||||||
|
| Power (0, 6500) W | T57 | t57 |
|
||||||
|
| Pressure measure (0, 1500) hPa | T58 | t58 |
|
||||||
|
| Analog Setpoint | T61 | t61 |
|
||||||
|
| Analog Setpoint-Temperature measure (-20, +50) °C | T62 | t62 |
|
||||||
|
| Analog Setpoint-Humidity measure (0, 100) % | T63 | t63 |
|
||||||
|
| Analog Setpoint-Light Sensor (0, 40) kLux | T64 | t64 |
|
||||||
|
| Analog Setpoint-Voltage (0, 400) V | T65 | t65 |
|
||||||
|
| Analog Setpoint-Current (0, 25) A | T66 | t66 |
|
||||||
|
| Analog Setpoint-Power (0, 6500) W | T67 | t67 |
|
||||||
|
| Analog Setpoint-Pressure measure (0, 1500) hPa | T68 | t68 |
|
||||||
|
| Broadcast messages | Action Message | topic |
|
||||||
|
|
||||||
|
### Channels
|
||||||
|
|
||||||
|
The following matrix lists the capabilities (channels) for each type:
|
||||||
|
|
||||||
|
| Thing type / Channel | Switch / onOff | Switch / sleep | DateTime / lastStatusStored | Number / healthy | Switch / autoMode | Contact / stateOnOff | Contact / stateOpenClose | Switch / pulse | Switch / whiteMode | Rollershutter / rollerBrightness | Dimmer / dimmerBrightness | Color / ledColor | Switch / one | Switch / two | Switch / three | Switch / four | Switch / five | Switch / six | Switch / seven | Switch / eight |
|
||||||
|
|----------------------|----------------|----------------|-----------------------------|------------------|-------------------|----------------------|--------------------------|----------------|--------------------|----------------------------------|---------------------------|------------------|--------------|--------------|----------------|---------------|---------------|--------------|----------------|----------------|
|
||||||
|
| t11 | x | x | x | x | | | | | | | | | | | | | | | | |
|
||||||
|
| t12 | x | | x | x | x | | | | | | | | | | | | | | | |
|
||||||
|
| t13 | | | x | x | | x | x | | | | | | | | | | | | | |
|
||||||
|
| t14 | | | x | x | | | | x | | | | | | | | | | | | |
|
||||||
|
| t16 | x | x | x | x | | | | | x | x | x | x | | | | | | | | |
|
||||||
|
| t18 | x | | x | x | | | | | | | | | | | | | | | | |
|
||||||
|
| t19 | x | x | x | x | | | | | | x | x | | | | | | | | | |
|
||||||
|
| t1A | | | x | x | | | | | | | | | x | x | x | x | x | x | x | x |
|
||||||
|
|
||||||
|
| Thing type / Channel | DateTime / lastStatusStored | Number / healthy | Rollershutter / rollerShutter | (see below) / rollerShutterState | (see down) / mode | (see down) / fan | Switch / status | Number / setPoint | Switch / setAsMeasured | Switch / measured | Switch / statusAlarm | Switch / onOffAlarm | Switch / rearmAlarm |
|
||||||
|
|----------------------|-----------------------------|------------------|-------------------------------|----------------------------------|-------------------|------------------|-----------------|-------------------|------------------------|-------------------|----------------------|---------------------|---------------------|
|
||||||
|
| t21 | x | x | | x | | | | | | | | | |
|
||||||
|
| t22 | x | x | x | x | | | | | | | | | |
|
||||||
|
| t31 | x | x | | | x | x | x | x | x | x | | | |
|
||||||
|
| t41 | x | x | | | | | | | | | x | x | x |
|
||||||
|
| t42 | x | x | | | | | | | | | x | | x |
|
||||||
|
|
||||||
|
rollershutterstate = opening, closing, limSwitchOpen , limSwitchClose, stateOpen, stateClose, noLimSwitch
|
||||||
|
|
||||||
|
mode = COOLING_MODE, HEATING_MODE, POWEREDOFF_MODE
|
||||||
|
|
||||||
|
fan = AUTO, HIGH, MEDIUM, LOW, FANOFF
|
||||||
|
|
||||||
|
|
||||||
|
| Thing type / Channel | DateTime / lastStatusStored | Number / healthy | Number / value |
|
||||||
|
|----------------------|-----------------------------|------------------|----------------|
|
||||||
|
| t51 | x | x | x |
|
||||||
|
| t52 | x | x | x |
|
||||||
|
| t53 | x | x | x |
|
||||||
|
| t54 | x | x | x |
|
||||||
|
| t55 | x | x | x |
|
||||||
|
| t56 | x | x | x |
|
||||||
|
| t57 | x | x | x |
|
||||||
|
| t58 | x | x | x |
|
||||||
|
|
||||||
|
| Thing type / Channel | DateTime / lastStatusStored | Number / healthy | Number / value |
|
||||||
|
|----------------------|-----------------------------|------------------|----------------|
|
||||||
|
| t61 | x | x | x |
|
||||||
|
| t62 | x | x | x |
|
||||||
|
| t63 | x | x | x |
|
||||||
|
| t64 | x | x | x |
|
||||||
|
| t65 | x | x | x |
|
||||||
|
| t66 | x | x | x |
|
||||||
|
| t67 | x | x | x |
|
||||||
|
| t68 | x | x | x |
|
||||||
|
| topic | x | | x |
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
| Thing type | Parameters Name and Default Value | Description |
|
||||||
|
|------------|-----------------------------------|-------------------------------------------------------------------------------------------------------|
|
||||||
|
| Gateway | gatewayLanAddress="" | Mandatory - lan address of Gateway |
|
||||||
|
| " | gatewayWanAddress="" | (advanced) When gateway is outside local network can insert domain/ip in this field |
|
||||||
|
| " | gatewayPortNumber=230 | (advanced) Gateway UDP Port |
|
||||||
|
| " | preferredLocalPortNumber=23000 | (advanced) Local UDP Port |
|
||||||
|
| " | pingInterval=30 | (advanced) Interval in seconds to check for device presence |
|
||||||
|
| " | subscriptionInterval=2 | (advanced) Interval in minutes to subscribe Souliss Gateway |
|
||||||
|
| " | healthyInterval=35 | (advanced) Interval in seconds to send nodes healthy |
|
||||||
|
| " | userIndex=70 | (advanced) Generally the default is good. It must be different from other ui (ex: SoulissApp) |
|
||||||
|
| " | nodeIndex=120 | (advanced) Generally the default value work good. It must is different from other ui (ex: SoulissApp) |
|
||||||
|
| Txx (all) | Node | Node of typical |
|
||||||
|
| Txx (all) | Slot | Slot of typical |
|
||||||
|
| T11 | sleep=5 | Set sleep timer in cycles |
|
||||||
|
| T11 | secureSend=true | Ensure command is correctly executed |
|
||||||
|
| T12 | | |
|
||||||
|
| T13 | | |
|
||||||
|
| T14 | | |
|
||||||
|
| T16 | sleep=5 | Set sleep timer in cycles |
|
||||||
|
| T19 | sleep=5 | Set sleep timer in cycles |
|
||||||
|
| T1A | | |
|
||||||
|
| T21 | | |
|
||||||
|
| T22 | | |
|
||||||
|
| T31 | | |
|
||||||
|
| T4x | | |
|
||||||
|
| T5x | | |
|
||||||
|
| T6x | | |
|
||||||
|
|
||||||
|
|
||||||
|
## Full Example
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
souliss.things:
|
||||||
|
|
||||||
|
```
|
||||||
|
Bridge souliss:gateway:105 "Souliss Gateway - 105" [gatewayLanAddress="192.168.1.105", gatewayPortNumber=230, preferredLocalPortNumber=0, pingInterval=30, subscriptionInterval=2, healthyInterval=38, userIndex=72, nodeIndex=38, timeoutToRequeue=5000, timeoutToRemovePacket=20000]
|
||||||
|
{
|
||||||
|
Thing t14 1-6 "Portoncino"@"Rientro" [node=1,slot=6] //thing UID is named as node-slot only as mnemonic convention, but you are free to assign other values
|
||||||
|
Thing t14 1-7 "Cancello"@"Rientro" [node=1,slot=7]
|
||||||
|
Thing t57 1-4 "Consumo"@"Soggiorno" [node=1,slot=4]
|
||||||
|
Thing t57 4-0 "Fotovoltaico"@"Soggiorno" [node=4,slot=0]
|
||||||
|
Thing t57 4-6 "Pannelli Gruppo 1"@"Soggiorno" [node=4,slot=6]
|
||||||
|
Thing t57 4-8 "Pannelli Gruppo 2"@"Soggiorno" [node=4,slot=8]
|
||||||
|
Thing t52 4-10 "Temp.Pannelli Gruppo 1"@"Soggiorno" [node=4,slot=10]
|
||||||
|
Thing t52 4-12 "Temp.Pannelli Gruppo 2"@"Soggiorno" [node=4,slot=12]
|
||||||
|
|
||||||
|
Thing t52 3-0 "Temperatura Boiler Solare Termico" [node=3,slot=0]
|
||||||
|
Thing t52 3-2 "Temperatura Termocamino" [node=3,slot=2]
|
||||||
|
Thing t11 3-4 "Acqua Termocamino" [node=3,slot=4]
|
||||||
|
Thing t11 3-6 "Auto: Boiler / Termocamino" [node=3,slot=6]
|
||||||
|
Thing t31 3-7 "Acqua Auto: Boiler / Termocamino" [node=3,slot=7]
|
||||||
|
|
||||||
|
Thing t31 6-0 "Termostato Soggiorno"@"Soggiorno" [node=6,slot=0]
|
||||||
|
Thing t53 6-7 "Umidità"@"Soggiorno" [node=6,slot=7]
|
||||||
|
Thing t19 6-9 "Termostato Soggiorno - Luminosità"@"Soggiorno" [node=6,slot=9]
|
||||||
|
|
||||||
|
Thing t11 5-0 "Tettoia"@"Giardino" [node=5,slot=0]
|
||||||
|
|
||||||
|
Thing t11 12-0 "Divano"@"Soggiorno" [node=12,slot=0,sleep=10, secureSend=false]
|
||||||
|
|
||||||
|
Thing t16 8-0 "LYT1" [node=8,slot=0]
|
||||||
|
|
||||||
|
Thing t11 10-0 "Albero di Natale" [node=10,slot=0]
|
||||||
|
Thing t11 11-0 "Birra"@"Soppalco" [node=11,slot=0]
|
||||||
|
Thing t52 11-1 "Birra - Temp 1"@"Soppalco" [node=11,slot=1]
|
||||||
|
Thing t52 11-3 "Birra - Temp 2"@"Soppalco" [node=11,slot=3]
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
You have to write your Gateway IP Number and leave all other to default values
|
||||||
|
|
||||||
|
|
||||||
|
default.items:
|
||||||
|
|
||||||
|
```
|
||||||
|
Group Home "Tonino" <house>
|
||||||
|
|
||||||
|
Group FamilyRoom "Soggiorno" <parents_2_4> (Home)
|
||||||
|
Group Divano "Divano" (Home)
|
||||||
|
Group Outside "Esterno" <garden> (Home)
|
||||||
|
Group TV "TV" <television> (Home)
|
||||||
|
Group Elettricita
|
||||||
|
Group Diagnostic
|
||||||
|
Group TermostatoSoggiorno
|
||||||
|
|
||||||
|
Switch tettoia "Tettoia" <light> (Outside) ["Lighting"] {autoupdate="false", channel="souliss:t11:105:5-0:onoff"}
|
||||||
|
String tettoia_aggiornamento "Agg [%1$td.%1$tm.%1$tY %1$tk:%1$tM:%1$tS]" <keyring> (Outside, Diagnostic) {channel="souliss:t31:105:5-0:lastStatusStored"}
|
||||||
|
|
||||||
|
Switch portoncino "Portoncino" <light> (FamilyRoom) ["Lighting"] {autoupdate="false",channel="souliss:t14:105:1-6:pulse"}
|
||||||
|
Switch cancello "Cancello" <light> (FamilyRoom) ["Lighting"] {autoupdate="false",channel="souliss:t14:105:1-7:pulse"}
|
||||||
|
|
||||||
|
Number FamilyRoom_Temperature "Temperatura [%.1f °C]" <temperature> (FamilyRoom) {channel="souliss:t31:105:6-0:measured"}
|
||||||
|
Number FamilyRoom_Humidity "Umidità [%.1f %%]" <humidity> (FamilyRoom) {channel="souliss:t53:105:6-7:value"}
|
||||||
|
String AggiornamentoNodo6 "Agg [%1$td.%1$tm.%1$tY %1$tk:%1$tM:%1$tS]" <keyring> (FamilyRoom, Diagnostic) {channel="souliss:t31:105:6-0:lastStatusStored"}
|
||||||
|
|
||||||
|
Number Consumo "Consumo [%.1f W]" <energy> (FamilyRoom, Elettricita) {channel="souliss:t57:105:1-4:value"}
|
||||||
|
Number Fotovoltaico "Fotovoltaico [%.1f W]" <energy> (FamilyRoom, Elettricita) {channel="souliss:t57:105:4-0:value"}
|
||||||
|
String AggiornamentoNodo1 "Agg.Consumi [%1$td.%1$tm.%1$tY %1$tk:%1$tM:%1$tS]" <keyring> (FamilyRoom, Elettricita, Diagnostic) {channel="souliss:t57:105:1-4:lastStatusStored"}
|
||||||
|
String AggiornamentoNodo4 "Agg.Fotovoltaico [%1$td.%1$tm.%1$tY %1$tk:%1$tM:%1$tS]" <keyring> (FamilyRoom, Elettricita, Diagnostic) {channel="souliss:t57:105:4-0:lastStatusStored"}
|
||||||
|
|
||||||
|
Switch divano "Divano" <light> (FamilyRoom, Divano ) ["Switchable"] {autoupdate="false", channel="souliss:t11:105:12-0:onOff"}
|
||||||
|
String divano_aggiornamento "Agg. [%1$td.%1$tm.%1$tY %1$tk:%1$tM:%1$tS]" <keyring> (FamilyRoom, Divano, Diagnostic) {channel="souliss:t57:105:12-0:lastStatusStored"}
|
||||||
|
String divano_healthy "Salute" <keyring> (FamilyRoom, Divano, Diagnostic) {channel="souliss:t57:105:12-0:healthy"}
|
||||||
|
|
||||||
|
Number termostatosoggiorno_temperatura "Temperatura [%.1f °C]" <temperature> (TermostatoSoggiorno) {channel="souliss:t31:105:6-0:measured"}
|
||||||
|
Number termostatosoggiorno_umidita "Umidità [%.1f %%]" <temperature> (TermostatoSoggiorno) {channel="souliss:t53:105:6-7:value" }
|
||||||
|
|
||||||
|
Number termostatosoggiorno_umidita "Umidità" <humidity> (TermostatoSoggiorno) {channel="souliss:t53:105:6-7:value" }
|
||||||
|
|
||||||
|
Number termostatosoggiorno_temperatura "Temperatura" <temperature> (TermostatoSoggiorno) {channel="souliss:t31:105:6-0:measured"}
|
||||||
|
Number termostatosoggiorno_setpoint "Regola Set Point [%.1f °c]" <heating> (TermostatoSoggiorno) {autoupdate="false", channel="souliss:t31:105:6-0:sePpoint"}
|
||||||
|
Switch termostatosoggiorno_setasmeasured "Set temp. attuale" <heating> (TermostatoSoggiorno) {channel="souliss:t31:105:6-0:setAsMeasured"}
|
||||||
|
String termostatosoggiorno_modo "Modo" (TermostatoSoggiorno) {autoupdate="false", channel="souliss:t31:105:6-0:mode"}
|
||||||
|
Switch termostatosoggiorno_power "Termostato" <powerIcon> (TermostatoSoggiorno) {channel="souliss:t31:105:6-0:system"}
|
||||||
|
Switch termostatosoggiorno_fire "Fire" <fire> (TermostatoSoggiorno) {channel="souliss:t31:105:6-0:fire"}
|
||||||
|
|
||||||
|
Dimmer TermostatoSoggiorno_displayBright "Lumin.min. display" (TermostatoSoggiorno) {channel="souliss:t19:105:6-9" }
|
||||||
|
String TermostatoSoggiorno_aggiornamento "Agg.[%1$td.%1$tm.%1$tY %1$tk:%1$tM:%1$tS]" <keyring> (TermostatoSoggiorno, Diagnostic) {channel="souliss:t31:105:6-0:lastStatusStored"}
|
||||||
|
Number TermostatoSoggiorno_healthy "Salute" <keyring> (TermostatoSoggiorno, Diagnostic ) {channel="souliss:t31:105:6-0:healthy"}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
default.sitemaps:
|
||||||
|
|
||||||
|
```
|
||||||
|
sitemap default label="Tonino" {
|
||||||
|
Frame {
|
||||||
|
Text label="Rientro casa" icon="light" {
|
||||||
|
Switch item=portoncino mappings=[ON="Apri"]
|
||||||
|
Switch item=cancello mappings=[ON="Apri"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Frame {
|
||||||
|
Group item=Outside
|
||||||
|
}
|
||||||
|
|
||||||
|
Text item=Consumo label="Consumo [%.1f W]"
|
||||||
|
Text item=Fotovoltaico label="Fotovoltaico [%.1f W]"
|
||||||
|
|
||||||
|
Frame {
|
||||||
|
|
||||||
|
Group item=Elettricita label="Elettricità" icon="energy"
|
||||||
|
}
|
||||||
|
|
||||||
|
Frame {
|
||||||
|
Group item=Divano icon="light"
|
||||||
|
}
|
||||||
|
|
||||||
|
Frame label="Temperature"{
|
||||||
|
|
||||||
|
Text label="Temperatura e umidità" icon="temperature" {
|
||||||
|
Default item=FamilyRoom_Temperature label="Temperatura"
|
||||||
|
Default item=FamilyRoom_Humidity label="Umidità"
|
||||||
|
Default item=AggiornamentoNodo6 icon="icon16x16"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Text label="Termostato soggiorno" icon="temperature" {
|
||||||
|
Setpoint item=termostatosoggiorno_setpoint step=0.5 minValue=10 maxValue=30
|
||||||
|
Default item=termostatosoggiorno_temperatura
|
||||||
|
Default item=termostatosoggiorno_umidita
|
||||||
|
Switch item=termostatosoggiorno_setasmeasured mappings=[ON="Set"]
|
||||||
|
Switch item=termostatosoggiorno_modo label="Heating Mode" mappings=[HEATING_MODE="Set"]
|
||||||
|
Switch item=termostatosoggiorno_power label="Power On/Off"
|
||||||
|
Default item=termostatosoggiorno_fire label="Fire"
|
||||||
|
Text item=termostatoSoggiorno_aggiornamento label="Aggiornato: [%1$td.%1$tm.%1$tY %1$tk:%1$tM:%1$tS]" icon="icon16x16"
|
||||||
|
Default item=termostatoSoggiorno_healthy
|
||||||
|
Slider item=termostatoSoggiorno_displayBright
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
## Community
|
||||||
|
|
||||||
|
Souliss is a small community and doesn't have sufficient human resources to be more active on openHAB official community.
|
||||||
|
|
||||||
|
These are some very popular forum:
|
||||||
|
|
||||||
|
English Group, [here](https://groups.google.com/forum/#!forum/souliss)
|
||||||
|
|
||||||
|
Italian Group, [here](https://groups.google.com/forum/#!forum/souliss-it)
|
||||||
|
|
||||||
|
Spanish Group, [here] (https://groups.google.com/forum/#!forum/souliss-es)
|
||||||
|
|
||||||
|
## Contribution
|
||||||
|
|
||||||
|
Official repository for contributing to the Souliss project, GitHub page: [here](https://github.com/souliss)
|
||||||
|
|
||||||
|
## Known issues
|
||||||
|
|
||||||
|
Securesend is, at moment, enabled and tested only for t11...
|
17
bundles/org.openhab.binding.souliss/pom.xml
Normal file
17
bundles/org.openhab.binding.souliss/pom.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||||
|
<version>3.2.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>org.openhab.binding.souliss</artifactId>
|
||||||
|
|
||||||
|
<name>openHAB Add-ons :: Bundles :: Souliss Binding</name>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<features name="org.openhab.binding.souliss-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||||
|
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||||
|
|
||||||
|
<feature name="openhab-binding-souliss" description="Souliss Binding" version="${project.version}">
|
||||||
|
<feature>openhab-runtime-base</feature>
|
||||||
|
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.souliss/${project.version}</bundle>
|
||||||
|
</feature>
|
||||||
|
</features>
|
@ -0,0 +1,210 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissBinding} class defines common constants, which are
|
||||||
|
* used across the whole binding.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public final class SoulissBindingConstants {
|
||||||
|
|
||||||
|
public static final String BINDING_ID = "souliss";
|
||||||
|
|
||||||
|
public static final long DISCOVERY_RESEND_TIMEOUT_IN_SECONDS = 45;
|
||||||
|
public static final int DISCOVERY_TIMEOUT_IN_SECONDS = 120;
|
||||||
|
public static final long SEND_DISPATCHER_MIN_DELAY_CYCLE_IN_MILLIS = 500;
|
||||||
|
|
||||||
|
// List of all Thing Type UIDs
|
||||||
|
public static final ThingTypeUID GATEWAY_THING_TYPE = new ThingTypeUID(BINDING_ID, "gateway");
|
||||||
|
|
||||||
|
public static final String T11 = "t11";
|
||||||
|
public static final String T12 = "t12";
|
||||||
|
public static final String T13 = "t13";
|
||||||
|
public static final String T14 = "t14";
|
||||||
|
public static final String T16 = "t16";
|
||||||
|
public static final String T18 = "t18";
|
||||||
|
public static final String T19 = "t19";
|
||||||
|
public static final String T1A = "t1a";
|
||||||
|
public static final String T21 = "t21";
|
||||||
|
public static final String T22 = "t22";
|
||||||
|
public static final String T31 = "t31";
|
||||||
|
public static final String T41 = "t41";
|
||||||
|
public static final String T42 = "t42";
|
||||||
|
public static final String T51 = "t51";
|
||||||
|
public static final String T52 = "t52";
|
||||||
|
public static final String T53 = "t53";
|
||||||
|
public static final String T54 = "t54";
|
||||||
|
public static final String T55 = "t55";
|
||||||
|
public static final String T56 = "t56";
|
||||||
|
public static final String T57 = "t57";
|
||||||
|
public static final String T58 = "t58";
|
||||||
|
public static final String T61 = "t61";
|
||||||
|
public static final String T62 = "t62";
|
||||||
|
public static final String T63 = "t63";
|
||||||
|
public static final String T64 = "t64";
|
||||||
|
public static final String T65 = "t65";
|
||||||
|
public static final String T66 = "t66";
|
||||||
|
public static final String T67 = "t67";
|
||||||
|
public static final String T68 = "t68";
|
||||||
|
public static final String TOPICS = "topic";
|
||||||
|
|
||||||
|
public static final ThingTypeUID T11_THING_TYPE = new ThingTypeUID(BINDING_ID, T11);
|
||||||
|
public static final ThingTypeUID T12_THING_TYPE = new ThingTypeUID(BINDING_ID, T12);
|
||||||
|
public static final ThingTypeUID T13_THING_TYPE = new ThingTypeUID(BINDING_ID, T13);
|
||||||
|
public static final ThingTypeUID T14_THING_TYPE = new ThingTypeUID(BINDING_ID, T14);
|
||||||
|
public static final ThingTypeUID T16_THING_TYPE = new ThingTypeUID(BINDING_ID, T16);
|
||||||
|
public static final ThingTypeUID T18_THING_TYPE = new ThingTypeUID(BINDING_ID, T18);
|
||||||
|
public static final ThingTypeUID T19_THING_TYPE = new ThingTypeUID(BINDING_ID, T19);
|
||||||
|
public static final ThingTypeUID T1A_THING_TYPE = new ThingTypeUID(BINDING_ID, T1A);
|
||||||
|
public static final ThingTypeUID T21_THING_TYPE = new ThingTypeUID(BINDING_ID, T21);
|
||||||
|
public static final ThingTypeUID T22_THING_TYPE = new ThingTypeUID(BINDING_ID, T22);
|
||||||
|
public static final ThingTypeUID T31_THING_TYPE = new ThingTypeUID(BINDING_ID, T31);
|
||||||
|
public static final ThingTypeUID T41_THING_TYPE = new ThingTypeUID(BINDING_ID, T41);
|
||||||
|
public static final ThingTypeUID T42_THING_TYPE = new ThingTypeUID(BINDING_ID, T42);
|
||||||
|
public static final ThingTypeUID T51_THING_TYPE = new ThingTypeUID(BINDING_ID, T51);
|
||||||
|
public static final ThingTypeUID T52_THING_TYPE = new ThingTypeUID(BINDING_ID, T52);
|
||||||
|
public static final ThingTypeUID T53_THING_TYPE = new ThingTypeUID(BINDING_ID, T53);
|
||||||
|
public static final ThingTypeUID T54_THING_TYPE = new ThingTypeUID(BINDING_ID, T54);
|
||||||
|
public static final ThingTypeUID T55_THING_TYPE = new ThingTypeUID(BINDING_ID, T55);
|
||||||
|
public static final ThingTypeUID T56_THING_TYPE = new ThingTypeUID(BINDING_ID, T56);
|
||||||
|
public static final ThingTypeUID T57_THING_TYPE = new ThingTypeUID(BINDING_ID, T57);
|
||||||
|
public static final ThingTypeUID T58_THING_TYPE = new ThingTypeUID(BINDING_ID, T58);
|
||||||
|
public static final ThingTypeUID T61_THING_TYPE = new ThingTypeUID(BINDING_ID, T61);
|
||||||
|
public static final ThingTypeUID T62_THING_TYPE = new ThingTypeUID(BINDING_ID, T62);
|
||||||
|
public static final ThingTypeUID T63_THING_TYPE = new ThingTypeUID(BINDING_ID, T63);
|
||||||
|
public static final ThingTypeUID T64_THING_TYPE = new ThingTypeUID(BINDING_ID, T64);
|
||||||
|
public static final ThingTypeUID T65_THING_TYPE = new ThingTypeUID(BINDING_ID, T65);
|
||||||
|
public static final ThingTypeUID T66_THING_TYPE = new ThingTypeUID(BINDING_ID, T66);
|
||||||
|
public static final ThingTypeUID T67_THING_TYPE = new ThingTypeUID(BINDING_ID, T67);
|
||||||
|
public static final ThingTypeUID T68_THING_TYPE = new ThingTypeUID(BINDING_ID, T68);
|
||||||
|
public static final ThingTypeUID TOPICS_THING_TYPE = new ThingTypeUID(BINDING_ID, TOPICS);
|
||||||
|
|
||||||
|
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(GATEWAY_THING_TYPE, T11_THING_TYPE,
|
||||||
|
T12_THING_TYPE, T13_THING_TYPE, T14_THING_TYPE, T16_THING_TYPE, T18_THING_TYPE, T19_THING_TYPE,
|
||||||
|
T1A_THING_TYPE, T21_THING_TYPE, T22_THING_TYPE, T31_THING_TYPE, T41_THING_TYPE, T42_THING_TYPE,
|
||||||
|
T51_THING_TYPE, T52_THING_TYPE, T53_THING_TYPE, T54_THING_TYPE, T55_THING_TYPE, T56_THING_TYPE,
|
||||||
|
T57_THING_TYPE, T58_THING_TYPE, T61_THING_TYPE, T62_THING_TYPE, T63_THING_TYPE, T64_THING_TYPE,
|
||||||
|
T65_THING_TYPE, T66_THING_TYPE, T67_THING_TYPE, T68_THING_TYPE, TOPICS_THING_TYPE);
|
||||||
|
|
||||||
|
// List of all Channel ids
|
||||||
|
public static final String ONOFF_CHANNEL = "onOff";
|
||||||
|
|
||||||
|
public static final String PULSE_CHANNEL = "pulse";
|
||||||
|
public static final String SLEEP_CHANNEL = "sleep";
|
||||||
|
public static final String AUTOMODE_CHANNEL = "autoMode";
|
||||||
|
public static final String STATEONOFF_CHANNEL = "stateOnOff";
|
||||||
|
public static final String STATEOPENCLOSE_CHANNEL = "stateOpenClose";
|
||||||
|
public static final String ROLLERSHUTTER_CHANNEL = "rollerShutter";
|
||||||
|
public static final String ROLLERSHUTTER_STATE_CHANNEL_CHANNEL = "rollerShutterState";
|
||||||
|
|
||||||
|
public static final String ROLLERSHUTTER_MESSAGE_OPENING_CHANNEL = "opening";
|
||||||
|
public static final String ROLLERSHUTTER_MESSAGE_CLOSING_CHANNEL = "closing";
|
||||||
|
public static final String ROLLERSHUTTER_MESSAGE_LIMITSWITCH_OPEN_CHANNEL = "limSwitchOpen";
|
||||||
|
public static final String ROLLERSHUTTER_MESSAGE_LIMITSWITCH_CLOSE_CHANNEL = "limSwitchClose";
|
||||||
|
public static final String ROLLERSHUTTER_MESSAGE_STATE_OPEN_CHANNEL = "stateOpen";
|
||||||
|
public static final String ROLLERSHUTTER_MESSAGE_STATE_CLOSE_CHANNEL = "stateClose";
|
||||||
|
public static final String ROLLERSHUTTER_MESSAGE_NO_LIMITSWITCH_CHANNEL = "NoLimSwitch";
|
||||||
|
public static final String ROLLERSHUTTER_MESSAGE_STOP_CHANNEL = "stop";
|
||||||
|
public static final String ROLLERSHUTTER_MESSAGE_TIMER_OFF = "timer off";
|
||||||
|
|
||||||
|
public static final String T1A_1_CHANNEL = "one";
|
||||||
|
public static final String T1A_2_CHANNEL = "two";
|
||||||
|
public static final String T1A_3_CHANNEL = "three";
|
||||||
|
public static final String T1A_4_CHANNEL = "four";
|
||||||
|
public static final String T1A_5_CHANNEL = "five";
|
||||||
|
public static final String T1A_6_CHANNEL = "six";
|
||||||
|
public static final String T1A_7_CHANNEL = "seven";
|
||||||
|
public static final String T1A_8_CHANNEL = "eight";
|
||||||
|
|
||||||
|
public static final String T31_MODE_CHANNEL = "mode";
|
||||||
|
public static final String T31_SYSTEM_CHANNEL = "system";
|
||||||
|
public static final String T31_FIRE_CHANNEL = "fire";
|
||||||
|
public static final String T31_FAN_CHANNEL = "fan";
|
||||||
|
public static final String T31_BUTTON_CHANNEL = "setAsMeasured";
|
||||||
|
public static final String T31_VALUE_CHANNEL = "measured";
|
||||||
|
public static final String T31_SETPOINT_CHANNEL = "setPoint";
|
||||||
|
|
||||||
|
public static final String T31_COOLINGMODE_MESSAGE_MODE_CHANNEL = "COOLING_MODE";
|
||||||
|
public static final String T31_HEATINGMODE_MESSAGE_MODE_CHANNEL = "HEATING_MODE";
|
||||||
|
public static final String T31_OFF_MESSAGE_SYSTEM_CHANNEL = "SYSTEM_OFF";
|
||||||
|
public static final String T31_ON_MESSAGE_SYSTEM_CHANNEL = "SYSTEM_ON";
|
||||||
|
public static final String T31_ON_MESSAGE_FIRE_CHANNEL = "FIRE_ON";
|
||||||
|
public static final String T31_OFF_MESSAGE_FIRE_CHANNEL = "FIRE_OFF";
|
||||||
|
|
||||||
|
public static final String T31_FANAUTO_MESSAGE_FAN_CHANNEL = "AUTO";
|
||||||
|
public static final String T31_FANOFF_MESSAGE_FAN_CHANNEL = "FANOFF";
|
||||||
|
public static final String T31_FANLOW_MESSAGE_FAN_CHANNEL = "LOW";
|
||||||
|
public static final String T31_FANMEDIUM_MESSAGE_FAN_CHANNEL = "MEDIUM";
|
||||||
|
public static final String T31_FANHIGH_MESSAGE_FAN_CHANNEL = "HIGH";
|
||||||
|
|
||||||
|
public static final String T4N_ONOFFALARM_CHANNEL = "onOffAlarm";
|
||||||
|
public static final String T4N_STATUSALARM_CHANNEL = "statusAlarm";
|
||||||
|
public static final String T4N_REARMALARM_CHANNEL = "rearmAlarm";
|
||||||
|
public static final String T41_RESETALARM_CHANNEL = "resetAlarm";
|
||||||
|
|
||||||
|
public static final String T4N_ALARMON_MESSAGE_CHANNEL = "ALARMON";
|
||||||
|
public static final String T4N_ALARMOFF_MESSAGE_CHANNEL = "ALARMOFF";
|
||||||
|
public static final String T4N_REARMOFF_MESSAGE_CHANNEL = "REARMOFF";
|
||||||
|
public static final String T4N_ARMED_MESSAGE_CHANNEL = "ARMED";
|
||||||
|
|
||||||
|
public static final String WHITE_MODE_CHANNEL = "whitemode";
|
||||||
|
public static final String ROLLER_BRIGHTNESS_CHANNEL = "rollerBrightness";
|
||||||
|
public static final String DIMMER_BRIGHTNESS_CHANNEL = "dimmerBrightness";
|
||||||
|
public static final String LED_COLOR_CHANNEL = "ledcolor";
|
||||||
|
|
||||||
|
public static final String LASTMESSAGE_CHANNEL = "lastMessage";
|
||||||
|
public static final String LASTSTATUSSTORED_CHANNEL = "lastStatusStored";
|
||||||
|
public static final String HEALTHY_CHANNEL = "healthy";
|
||||||
|
|
||||||
|
public static final String T5N_VALUE_CHANNEL = "value";
|
||||||
|
public static final String T6N_VALUE_CHANNEL = "value";
|
||||||
|
public static final String FLOATING_POINT_CHANNEL = "float";
|
||||||
|
public static final String HUMIDITY_CHANNEL = "humidity";
|
||||||
|
public static final String TEMPERATURE_CHANNEL = "temperature";
|
||||||
|
public static final String AMPERE_CHANNEL = "ampere";
|
||||||
|
public static final String VOLTAGE_CHANNEL = "voltage";
|
||||||
|
public static final String POWER_CHANNEL = "power";
|
||||||
|
|
||||||
|
public static final String CONFIG_ID = "ID";
|
||||||
|
public static final String CONFIG_IP_ADDRESS = "gatewayLanAddress";
|
||||||
|
|
||||||
|
public static final String UUID_NODE_SLOT_SEPARATOR = "-";
|
||||||
|
|
||||||
|
public static final String UUID_ELEMENTS_SEPARATOR = ":";
|
||||||
|
|
||||||
|
public static final String CONFIG_SLEEP = "sleep";
|
||||||
|
|
||||||
|
public static final String CONFIG_SECURE_SEND = "secureSend";
|
||||||
|
|
||||||
|
public static final String CONFIG_TIMEOUT_TO_REQUEUE = "timeoutToRequeue";
|
||||||
|
|
||||||
|
public static final String CONFIG_TIMEOUT_TO_REMOVE_PACKET = "timeoutToRemovePacket";
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
public static final String PROPERTY_NODE = "node";
|
||||||
|
public static final String PROPERTY_SLOT = "slot";
|
||||||
|
public static final String PROPERTY_UNIQUEID = "uniqueId";
|
||||||
|
|
||||||
|
// private constructor
|
||||||
|
private SoulissBindingConstants() {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal;
|
||||||
|
|
||||||
|
import java.net.DatagramSocket;
|
||||||
|
import java.net.SocketException;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissDatagramSocketFactory} is responsible for creating datagramSocket object for trasmission e
|
||||||
|
* receiving.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissDatagramSocketFactory {
|
||||||
|
|
||||||
|
public static @Nullable DatagramSocket getSocketDatagram(Logger logger) {
|
||||||
|
return getSocketDatagram(0, logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @Nullable DatagramSocket getSocketDatagram(int socketPortNumber, Logger logger) {
|
||||||
|
// return DatagramSocket for packet trasmission
|
||||||
|
DatagramSocket soulissDatagramSocket = null;
|
||||||
|
logger.debug("Setup socket");
|
||||||
|
try {
|
||||||
|
if (socketPortNumber != 0) {
|
||||||
|
soulissDatagramSocket = new DatagramSocket(socketPortNumber);
|
||||||
|
} else {
|
||||||
|
soulissDatagramSocket = new DatagramSocket();
|
||||||
|
}
|
||||||
|
logger.debug("Datagram Socket Created on port {}", soulissDatagramSocket.getLocalPort());
|
||||||
|
} catch (SocketException e) {
|
||||||
|
logger.warn("Error on creation of Socket: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return soulissDatagramSocket;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,138 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal;
|
||||||
|
|
||||||
|
import static org.openhab.binding.souliss.internal.SoulissBindingConstants.*;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissGatewayHandler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT11Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT12Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT13Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT14Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT16Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT18Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT19Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT1AHandler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT22Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT31Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT41Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT42Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT51Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT52Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT53Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT54Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT55Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT56Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT57Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT61Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT62Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT63Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT64Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT65Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT66Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT67Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT68Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissTopicsHandler;
|
||||||
|
import org.openhab.core.thing.Bridge;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
|
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandler;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissHandlerFactory} is responsible for creating things and thingGeneric
|
||||||
|
* handlers. It fire when a new thingGeneric is added.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
@Component(configurationPid = "binding.souliss", service = ThingHandlerFactory.class)
|
||||||
|
public class SoulissHandlerFactory extends BaseThingHandlerFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||||
|
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||||
|
var thingTypeUID = thing.getThingTypeUID();
|
||||||
|
|
||||||
|
if (thingTypeUID.equals(GATEWAY_THING_TYPE)) {
|
||||||
|
return new SoulissGatewayHandler((Bridge) thing);
|
||||||
|
} else if (thingTypeUID.equals(T11_THING_TYPE)) {
|
||||||
|
return new SoulissT11Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T12_THING_TYPE)) {
|
||||||
|
return new SoulissT12Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T13_THING_TYPE)) {
|
||||||
|
return new SoulissT13Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T14_THING_TYPE)) {
|
||||||
|
return new SoulissT14Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T16_THING_TYPE)) {
|
||||||
|
return new SoulissT16Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T18_THING_TYPE)) {
|
||||||
|
return new SoulissT18Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T19_THING_TYPE)) {
|
||||||
|
return new SoulissT19Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T1A_THING_TYPE)) {
|
||||||
|
return new SoulissT1AHandler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T21_THING_TYPE) || (thingTypeUID.equals(T22_THING_TYPE))) {
|
||||||
|
return new SoulissT22Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T31_THING_TYPE)) {
|
||||||
|
return new SoulissT31Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T41_THING_TYPE)) {
|
||||||
|
return new SoulissT41Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T42_THING_TYPE)) {
|
||||||
|
return new SoulissT42Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T51_THING_TYPE)) {
|
||||||
|
return new SoulissT51Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T52_THING_TYPE)) {
|
||||||
|
return new SoulissT52Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T53_THING_TYPE)) {
|
||||||
|
return new SoulissT53Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T54_THING_TYPE)) {
|
||||||
|
return new SoulissT54Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T55_THING_TYPE)) {
|
||||||
|
return new SoulissT55Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T56_THING_TYPE)) {
|
||||||
|
return new SoulissT56Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T57_THING_TYPE)) {
|
||||||
|
return new SoulissT57Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T61_THING_TYPE)) {
|
||||||
|
return new SoulissT61Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T62_THING_TYPE)) {
|
||||||
|
return new SoulissT62Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T63_THING_TYPE)) {
|
||||||
|
return new SoulissT63Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T64_THING_TYPE)) {
|
||||||
|
return new SoulissT64Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T65_THING_TYPE)) {
|
||||||
|
return new SoulissT65Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T66_THING_TYPE)) {
|
||||||
|
return new SoulissT66Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T67_THING_TYPE)) {
|
||||||
|
return new SoulissT67Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(T68_THING_TYPE)) {
|
||||||
|
return new SoulissT68Handler(thing);
|
||||||
|
} else if (thingTypeUID.equals(TOPICS_THING_TYPE)) {
|
||||||
|
return new SoulissTopicsHandler(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,309 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the class {@link SoulissProtocolConstants} class contains Souliss constants. Original version is taken from
|
||||||
|
* SoulissApp. For scope of this binding not all constants are used.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
* @author Alessandro Del Pex - soulissapp
|
||||||
|
* @author Tonino Fazio - @since 1.7.0
|
||||||
|
* @author Luca Remigio - @since 2.0.0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public final class SoulissProtocolConstants {
|
||||||
|
|
||||||
|
public static final String TAG = "SoulissApp:Typicals";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /** // Defines for Typicals C LIBRARY
|
||||||
|
*
|
||||||
|
* #define SOULISS_T31 31 // Temperature control #define Souliss_T41 41 //
|
||||||
|
* Anti-theft integration (Main) #define Souliss_T42 42 // Anti-theft
|
||||||
|
* integration (Peer)
|
||||||
|
*/
|
||||||
|
public static final byte SOULISS_T_EMPTY = 0;
|
||||||
|
public static final byte SOULISS_T_RELATED = (byte) 0xFF;
|
||||||
|
|
||||||
|
public static final byte SOULISS_TSERVICE_NODE_HEALTHY = (byte) 0x98;
|
||||||
|
public static final byte SOULISS_TSERVICE_NODE_TIMESTAMP = (byte) 0x99;
|
||||||
|
|
||||||
|
public static final int SOULISS_TSERVICE_NODE_HEALTHY_VIRTUAL_SLOT = 998;
|
||||||
|
public static final int SOULISS_TSERVICE_NODE_TIMESTAMP_VIRTUAL_SLOT = 999;
|
||||||
|
|
||||||
|
// Defines for Typicals
|
||||||
|
public static final byte SOULISS_T11 = 0x11;
|
||||||
|
public static final byte SOULISS_T12 = 0x12;
|
||||||
|
public static final byte SOULISS_T13 = 0x13;
|
||||||
|
public static final byte SOULISS_T14 = 0x14;
|
||||||
|
// RGB Light
|
||||||
|
public static final byte SOULISS_T1N_RGB = 0x15;
|
||||||
|
public static final byte SOULISS_T16 = 0x16;
|
||||||
|
public static final byte SOULISS_T18 = 0x18;
|
||||||
|
public static final byte SOULISS_T19 = 0x19;
|
||||||
|
public static final byte SOULISS_T1A = 0x1A;
|
||||||
|
|
||||||
|
// Motorized devices with limit switches
|
||||||
|
public static final byte SOULISS_T21 = 0x21;
|
||||||
|
// Motorized devices with limit switches and middle position
|
||||||
|
public static final byte SOULISS_T22 = 0x22;
|
||||||
|
public static final byte SOULISS_T31 = 0x31;
|
||||||
|
public static final byte SOULISS_T32_IRCOM_AIRCON = 0x32;
|
||||||
|
|
||||||
|
// Anti-theft group (used with massive commands)
|
||||||
|
public static final byte SOULISS_T42_ANTITHEFT_GROUP = 0x40;
|
||||||
|
// Anti-theft integration (Main)
|
||||||
|
public static final byte SOULISS_T41_ANTITHEFT_MAIN = 0x41;
|
||||||
|
// Anti-theft integration (Peer)
|
||||||
|
public static final byte SOULISS_T42_ANTITHEFT_PEER = 0x42;
|
||||||
|
|
||||||
|
public static final byte SOULISS_T51 = 0x51;
|
||||||
|
public static final byte SOULISS_T52_TEMPERATURE_SENSOR = 0x52;
|
||||||
|
public static final byte SOULISS_T53_HUMIDITY_SENSOR = 0x53;
|
||||||
|
public static final byte SOULISS_T54_LUX_SENSOR = 0x54;
|
||||||
|
public static final byte SOULISS_T55_VOLTAGE_SENSOR = 0x55;
|
||||||
|
public static final byte SOULISS_T56_CURRENT_SENSOR = 0x56;
|
||||||
|
public static final byte SOULISS_T57_POWER_SENSOR = 0x57;
|
||||||
|
public static final byte SOULISS_T58_PRESSURE_SENSOR = 0x58;
|
||||||
|
|
||||||
|
public static final byte SOULISS_T61 = 0x61;
|
||||||
|
public static final byte SOULISS_T62_TEMPERATURE_SENSOR = 0x62;
|
||||||
|
public static final byte SOULISS_T63_HUMIDITY_SENSOR = 0x63;
|
||||||
|
public static final byte SOULISS_T64_LUX_SENSOR = 0x64;
|
||||||
|
public static final byte SOULISS_T65_VOLTAGE_SENSOR = 0x65;
|
||||||
|
public static final byte SOULISS_T66_CURRENT_SENSOR = 0x66;
|
||||||
|
public static final byte SOULISS_T67_POWER_SENSOR = 0x67;
|
||||||
|
public static final byte SOULISS_T68_PRESSURE_SENSOR = 0x68;
|
||||||
|
|
||||||
|
public static final byte SOULISS_TOPICS = 0x72;
|
||||||
|
|
||||||
|
// customized (remote) AirCon commands
|
||||||
|
public static final int SOULISS_T_IRCOM_AIRCON_POW_ON = 0x8FFE;
|
||||||
|
public static final int SOULISS_T_IRCOM_AIRCON_POW_AUTO_20 = 0x8FFD;
|
||||||
|
public static final int SOULISS_T_IRCOM_AIRCON_POW_AUTO_24 = 0x8FFE;
|
||||||
|
public static final int SOULISS_T_IRCOM_AIRCON_POW_COOL_18 = 0x807B;
|
||||||
|
public static final int SOULISS_T_IRCOM_AIRCON_POW_COOL_22 = 0x8079;
|
||||||
|
public static final int SOULISS_T_IRCOM_AIRCON_POW_COOL_26 = 0x807A;
|
||||||
|
public static final int SOULISS_T_IRCOM_AIRCON_POW_FAN = 0x8733;
|
||||||
|
public static final int SOULISS_T_IRCOM_AIRCON_POW_DRY = 0x87BE;
|
||||||
|
public static final int SOULISS_T_IRCOM_AIRCON_POW_OFF = 0x70FE;
|
||||||
|
|
||||||
|
// Souliss Aircon Temperature
|
||||||
|
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_16C = 0xF;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_17C = 0x7;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_18C = 0xB;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_19C = 0x3;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_20C = 0xD;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_21C = 0x5;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_22C = 0x9;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_23C = 0x1;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_24C = 0xE;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_25C = 0x6;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_26C = 0xA;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_27C = 0x2;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_28C = 0xC;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_29C = 0x4;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_30C = 0x8;
|
||||||
|
|
||||||
|
// Souliss conditioner Function
|
||||||
|
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_FUN_AAUTO = 0xF;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_FUN_DRY = 0xB;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_FUN_FAN = 0x3;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_FUN_HEAT = 0xD;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_FUN_COOL = 0x7;
|
||||||
|
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_FAN_AUTO = 0x7;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_FAN_HIGH = 0x2;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_FAN_MEDIUM = 0x6;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_TEMP_FAN_LOW = 0x5;
|
||||||
|
|
||||||
|
// optional switches. May be used to toggle
|
||||||
|
// custom aircon functions as air deflector, ionizer, turbomode, etc.
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_OPT1 = 0x2D;
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_OPT2 = 0x77;
|
||||||
|
|
||||||
|
public static final byte SOULISS_T_IRCOM_AIRCON_RESET = 0x00;
|
||||||
|
|
||||||
|
// General defines for T1n
|
||||||
|
public static final byte SOULISS_T1N_TOGGLE_CMD = 0x01;
|
||||||
|
public static final byte SOULISS_T1N_ON_CMD = 0x02;
|
||||||
|
public static final byte SOULISS_T1N_OFF_CMD = 0x04;
|
||||||
|
public static final byte SOULISS_T1N_AUTO_CMD = 0x08;
|
||||||
|
public static final byte SOULISS_T1N_TIMED = 0x30;
|
||||||
|
public static final byte SOULISS_T1N_RST_CMD = 0x00;
|
||||||
|
public static final byte SOULISS_T1N_ON_COIL = 0x01;
|
||||||
|
public static final byte SOULISS_T1N_OFF_COIL = 0x00;
|
||||||
|
public static final byte SOULISS_T1N_ON_COIL_AUTO = (byte) 0xF1;
|
||||||
|
public static final byte SOULISS_T1N_OFF_COIL_AUTO = (byte) 0xF0;
|
||||||
|
// Set a state
|
||||||
|
public static final byte SOULISS_T1N_SET = 0x22;
|
||||||
|
|
||||||
|
// Increase Light
|
||||||
|
public static final byte SOULISS_T1N_BRIGHT_UP = 0x10;
|
||||||
|
// Decrease Light
|
||||||
|
public static final byte SOULISS_T1N_BRIGHT_DOWN = 0x20;
|
||||||
|
// Flash Light
|
||||||
|
public static final byte SOULISS_T1N_FLASH = 0x21;
|
||||||
|
|
||||||
|
public static final byte SOULISS_T1N_ON_FEEDBACK = 0x23;
|
||||||
|
public static final byte SOULISS_T1N_OFF_FEEDBACK = 0x24;
|
||||||
|
public static final String SOULISS_T12_USE_OF_SLOT_AUTO_MODE = "autoMode";
|
||||||
|
public static final String SOULISS_T12_USE_OF_SLOT_SWITCH = "switch";
|
||||||
|
|
||||||
|
// Set a state
|
||||||
|
public static final long SOULISS_T16_RED = 0x22FF0000;
|
||||||
|
public static final long SOULISS_T16_GREEN = 0x2200FF00;
|
||||||
|
public static final long SOULISS_T16_BLUE = 0x220000FF;
|
||||||
|
public static final long SOULISS_T18_PULSE = 0xA1;
|
||||||
|
/*
|
||||||
|
* IR RGB Typical
|
||||||
|
*/
|
||||||
|
public static final byte SOULISS_T1N_RGB_ON_CMD = 0x1;
|
||||||
|
public static final byte SOULISS_T1N_RGB_OFF_CMD = 0x9;
|
||||||
|
|
||||||
|
// Souliss RGB main colours
|
||||||
|
public static final byte SOULISS_T1N_RGB_R = 0x2;
|
||||||
|
public static final byte SOULISS_T1N_RGB_G = 0x3;
|
||||||
|
public static final byte SOULISS_T1N_RGB_B = 0x4;
|
||||||
|
public static final byte SOULISS_T1N_RGB_W = 0x5;
|
||||||
|
// Souliss RGB Controls
|
||||||
|
public static final byte SOULISS_T_IRCOM_RGB_BRIGHT_UP = 0x6;
|
||||||
|
public static final byte SOULISS_T_IRCOM_RGB_BRIGHT_DOWN = 0x7;
|
||||||
|
// MODES
|
||||||
|
public static final byte SOULISS_T_IRCOM_RGB_MODE_FLASH = (byte) 0xA1;
|
||||||
|
public static final byte SOULISS_T_IRCOM_RGB_MODE_STROBE = (byte) 0xA2;
|
||||||
|
public static final byte SOULISS_T_IRCOM_RGB_MODE_FADE = (byte) 0xA3;
|
||||||
|
public static final byte SOULISS_T_IRCOM_RGB_MODE_SMOOTH = (byte) 0xA4;
|
||||||
|
|
||||||
|
public static final byte SOULISS_T1N_RGB_R2 = (byte) 0xB1;
|
||||||
|
public static final byte SOULISS_T1N_RGB_R3 = (byte) 0xB2;
|
||||||
|
public static final byte SOULISS_T1N_RGB_R4 = (byte) 0xB3;
|
||||||
|
public static final byte SOULISS_T1N_RGB_R5 = (byte) 0xB4;
|
||||||
|
public static final byte SOULISS_T1N_RGB_G2 = (byte) 0xC1;
|
||||||
|
public static final byte SOULISS_T1N_RGB_G3 = (byte) 0xC2;
|
||||||
|
public static final byte SOULISS_T1N_RGB_G4 = (byte) 0xC3;
|
||||||
|
public static final byte SOULISS_T1N_RGB_G5 = (byte) 0xC4;
|
||||||
|
public static final byte SOULISS_T1N_RGB_B2 = (byte) 0xD1;
|
||||||
|
public static final byte SOULISS_T1N_RGB_B3 = (byte) 0xD2;
|
||||||
|
public static final byte SOULISS_T1N_RGB_B4 = (byte) 0xD3;
|
||||||
|
public static final byte SOULISS_T1N_RGB_B5 = (byte) 0xD4;
|
||||||
|
|
||||||
|
public static final byte SOULISS_T1N_RGB_RST_CMD = 0x00;
|
||||||
|
|
||||||
|
// Defines for Typical 2n
|
||||||
|
public static final byte SOULISS_T2N_CLOSE_CMD = 0x01;
|
||||||
|
public static final byte SOULISS_T2N_OPEN_CMD = 0x02;
|
||||||
|
public static final byte SOULISS_T2N_STOP_CMD = 0x04;
|
||||||
|
// Close Command (only from local pushbutton)
|
||||||
|
public static final byte SOULISS_T2N_CLOSE_CMD_LOCAL = 0x08;
|
||||||
|
// Open Command (only from local pushbutton)
|
||||||
|
public static final byte SOULISS_T2N_OPEN_CMD_LOCAL = 0x10;
|
||||||
|
public static final byte SOULISS_T2N_TOGGLE_CMD = 0x08;
|
||||||
|
public static final byte SOULISS_T2N_RST_CMD = 0x00;
|
||||||
|
// Timer set value
|
||||||
|
public static final byte SOULISS_T2N_TIMER_VAL = (byte) 0xC0;
|
||||||
|
// Timer expired value
|
||||||
|
public static final byte SOULISS_T2N_TIMER_OFF = (byte) 0xA0;
|
||||||
|
// Timed stop value
|
||||||
|
public static final byte SOULISS_T2N_TIMEDSTOP_VAL = (byte) 0xC2;
|
||||||
|
// Timed stop exipred value
|
||||||
|
public static final byte SOULISS_T2N_TIMEDSTOP_OFF = (byte) 0xC0;
|
||||||
|
public static final byte SOULISS_T2N_LIMSWITCH_CLOSE = 0x14;
|
||||||
|
public static final byte SOULISS_T2N_LIMSWITCH_OPEN = 0x16;
|
||||||
|
// Close Feedback from Limit Switch
|
||||||
|
public static final byte SOULISS_T2N_STATE_CLOSE = 0x08;
|
||||||
|
// Open Feedback from Limit Switch
|
||||||
|
public static final byte SOULISS_T2N_STATE_OPEN = 0x10;
|
||||||
|
|
||||||
|
public static final byte SOULISS_T2N_NOLIMSWITCH = 0x20;
|
||||||
|
public static final byte SOULISS_T2N_COIL_CLOSE = 0x01;
|
||||||
|
public static final byte SOULISS_T2N_COIL_OPEN = 0x02;
|
||||||
|
public static final byte SOULISS_T2N_COIL_STOP = 0x03;
|
||||||
|
public static final byte SOULISS_T2N_COIL_OFF = 0x00;
|
||||||
|
|
||||||
|
// General defines for T3n
|
||||||
|
public static final String SOULISS_T31_USE_OF_SLOT_SETPOINT = "setPoint";
|
||||||
|
public static final String SOULISS_T31_USE_OF_SLOT_MEASURED = "measured";
|
||||||
|
public static final String SOULISS_T31_USE_OF_SLOT_SETASMEASURED = "setAsMeasured";
|
||||||
|
|
||||||
|
public static final byte SOULISS_T31_USE_OF_SLOT_SETPOINT_COMMAND = 0x0C;
|
||||||
|
public static final byte SOULISS_T31_USE_OF_SLOT_HEATING = 0x05;
|
||||||
|
public static final byte SOULISS_T31_USE_OF_SLOT_COOLING = 0x04;
|
||||||
|
public static final String SOULISS_T31_USE_OF_SLOT_HEATING_COOLING = "heatingCooling";
|
||||||
|
public static final byte SOULISS_T31_USE_OF_SLOT_FAN_OFF = 0x06;
|
||||||
|
public static final byte SOULISS_T31_USE_OF_SLOT_FAN_LOW = 0x07;
|
||||||
|
public static final byte SOULISS_T31_USE_OF_SLOT_FAN_MED = 0x08;
|
||||||
|
public static final byte SOULISS_T31_USE_OF_SLOT_FAN_HIGH = 0x09;
|
||||||
|
public static final byte SOULISS_T31_USE_OF_SLOT_FAN_AUTOMODE = 0x0A;
|
||||||
|
public static final String SOULISS_T31_USE_OF_SLOT_POWER = "power";
|
||||||
|
|
||||||
|
public static final byte SOULISS_T3N_IN_SETPOINT = 0x01;
|
||||||
|
public static final byte SOULISS_T3N_OUT_SETPOINT = 0x02;
|
||||||
|
public static final byte SOULISS_T3N_AS_MEASURED = 0x03;
|
||||||
|
public static final byte SOULISS_T3N_COOLING = 0x04;
|
||||||
|
public static final byte SOULISS_T3N_HEATING = 0x05;
|
||||||
|
public static final byte SOULISS_T3N_FAN_OFF = 0x06;
|
||||||
|
public static final byte SOULISS_T3N_FAN_LOW = 0x07;
|
||||||
|
public static final byte SOULISS_T3N_FAN_MED = 0x08;
|
||||||
|
public static final byte SOULISS_T3N_FAN_HIGH = 0x09;
|
||||||
|
public static final byte SOULISS_T3N_FAN_AUTO = 0x0A;
|
||||||
|
public static final byte SOULISS_T3N_FAN_MANUAL = 0x0B;
|
||||||
|
public static final byte SOULISS_T3N_SET_TEMP = 0x0C;
|
||||||
|
public static final byte SOULISS_T3N_SHUTDOWN = 0x0D;
|
||||||
|
|
||||||
|
public static final String SOULISS_T3N_HEATING_ON = "0x02";
|
||||||
|
public static final String SOULISS_T3N_COOLING_ON = "0x03";
|
||||||
|
public static final String SOULISS_T3N_FAN_ON_1 = "0x08";
|
||||||
|
public static final String SOULISS_T3N_FAN_ON_2 = "0x10";
|
||||||
|
public static final String SOULISS_T3N_FAN_ON_3 = "0x20";
|
||||||
|
|
||||||
|
// General defines for T4n
|
||||||
|
|
||||||
|
// Alarm Condition Detected (Input)
|
||||||
|
public static final byte SOULISS_T4N_ALARM = 0x01;
|
||||||
|
public static final byte SOULISS_T4N_RST_CMD = 0x00;
|
||||||
|
// Silence and Arm Command
|
||||||
|
public static final byte SOULISS_T4N_REARM = 0x03;
|
||||||
|
// Anti-theft not Armed Command
|
||||||
|
public static final byte SOULISS_T4N_NOT_ARMED = 0x04;
|
||||||
|
// Anti-theft Armed Command
|
||||||
|
public static final byte SOULISS_T4N_ARMED = 0x05;
|
||||||
|
// Anti-theft Armed Feedback
|
||||||
|
public static final byte SOULISS_T4N_ANTITHEFT = 0x01;
|
||||||
|
// Anti-theft not Armed Feedback
|
||||||
|
public static final byte SOULISS_T4N_NO_ANTITHEFT = 0x00;
|
||||||
|
// Anti-theft in Alarm
|
||||||
|
public static final byte SOULISS_T4N_IN_ALARM = 0x03;
|
||||||
|
|
||||||
|
public static final byte SOULISS_RST_CMD = 0x00;
|
||||||
|
public static final byte SOULISS_NOT_TRIGGED = 0x00;
|
||||||
|
public static final byte SOULISS_TRIGGED = 0x01;
|
||||||
|
|
||||||
|
// Defines for current sensor
|
||||||
|
public static final byte SOULISS_T_CURRENT_SENSOR = 0x65;
|
||||||
|
|
||||||
|
// REMOVE THESE
|
||||||
|
public static final byte SOULISS_T_TEMPERATURE_SENSOR = 0x67;
|
||||||
|
public static final byte SOULISS_T_TEMPERATURE_SENSOR_REFRESH = 0x02;
|
||||||
|
|
||||||
|
public static final byte SOULISS_T_HUMIDITY_SENSOR = 0x69;
|
||||||
|
public static final byte SOULISS_T_HUMIDITY_SENSOR_REFRESH = 0x03;
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Network constants. The class {@link SoulissUDPConstants} contains Souliss constants. Original version is
|
||||||
|
* taken from SoulissApp. For scope of this binding not all constants are used.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
* @author Alessandro Del Pex - @since 1.7.0
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissUDPConstants {
|
||||||
|
|
||||||
|
public static final String TAG = "SoulissApp";
|
||||||
|
|
||||||
|
public static final int SOULISS_BINDING_LOCAL_PORT = 0;
|
||||||
|
public static final int SOULISS_GATEWAY_DEFAULT_PORT = 230;
|
||||||
|
|
||||||
|
public static final Integer SOULISS_DEFAULT_NODE_INDEX = 70;
|
||||||
|
public static final Integer SOULISS_DEFAULT_USER_INDEX = 120;
|
||||||
|
|
||||||
|
public static final String BROADCASTADDR = "255.255.255.255";
|
||||||
|
|
||||||
|
public static final byte SOULISS_UDP_FUNCTION_FORCE = 0x33;
|
||||||
|
public static final byte SOULISS_UDP_FUNCTION_FORCE_MASSIVE = 0x34;
|
||||||
|
|
||||||
|
public static final byte SOULISS_UDP_FUNCTION_SUBSCRIBE_REQ = 0x21;
|
||||||
|
public static final byte SOULISS_UDP_FUNCTION_SUBSCRIBE_RESP = 0x31;
|
||||||
|
public static final byte SOULISS_UDP_FUNCTION_POLL_REQ = 0x27;
|
||||||
|
public static final byte SOULISS_UDP_FUNCTION_POLL_RESP = 0x37;
|
||||||
|
public static final byte SOULISS_UDP_FUNCTION_TYP_REQ = 0x22;
|
||||||
|
public static final byte SOULISS_UDP_FUNCTION_TYP_RESP = 0x32;
|
||||||
|
public static final byte SOULISS_UDP_FUNCTION_HEALTHY_REQ = 0x25;
|
||||||
|
public static final byte SOULISS_UDP_FUNCTION_HEALTHY_RESP = 0x35;
|
||||||
|
|
||||||
|
public static final byte SOULISS_UDP_FUNCTION_PING_REQ = 0x8;
|
||||||
|
public static final byte SOULISS_UDP_FUNCTION_PING_RESP = 0x18;
|
||||||
|
|
||||||
|
public static final byte SOULISS_UDP_FUNCTION_DISCOVER_GW_NODE_BCAST_REQ = 0x28;
|
||||||
|
public static final byte SOULISS_UDP_FUNCTION_DISCOVER_GW_NODE_BCAST_RESP = 0x38;
|
||||||
|
|
||||||
|
public static final int SOULISS_UDP_FUNCTION_DBSTRUCT_REQ = 0x26;
|
||||||
|
public static final int SOULISS_UDP_FUNCTION_DBSTRUCT_RESP = 0x36;
|
||||||
|
|
||||||
|
public static final int SOULISS_UDP_FUNCTION_ACTION_MESSAGE = 0x72;
|
||||||
|
|
||||||
|
protected static final Byte[] PING_PAYLOAD = { SOULISS_UDP_FUNCTION_PING_REQ, 0, 0, 0, 0 };
|
||||||
|
protected static final Byte[] PING_DISCOVER_BCAST_PAYLOAD = { SOULISS_UDP_FUNCTION_DISCOVER_GW_NODE_BCAST_REQ, 0, 0,
|
||||||
|
0, 0 };
|
||||||
|
protected static final Byte[] DBSTRUCT_PAYLOAD = { SOULISS_UDP_FUNCTION_DBSTRUCT_REQ, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
// private constructor
|
||||||
|
private SoulissUDPConstants() {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.config;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link GatewayConfig} is responsible for holding souliss gateway config
|
||||||
|
*
|
||||||
|
* @author Luca Calcaterra - Initial Contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public final class GatewayConfig {
|
||||||
|
public int pingInterval;
|
||||||
|
public int subscriptionInterval;
|
||||||
|
public int healthyInterval;
|
||||||
|
public int sendInterval;
|
||||||
|
public int timeoutToRequeue;
|
||||||
|
public int timeoutToRemovePacket;
|
||||||
|
public int preferredLocalPortNumber;
|
||||||
|
public int gatewayPortNumber;
|
||||||
|
public int userIndex;
|
||||||
|
public int nodeIndex;
|
||||||
|
public String gatewayLanAddress = "";
|
||||||
|
public String gatewayWanAddress = "";
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.discovery;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result callback interface.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public interface DiscoverResult {
|
||||||
|
static boolean IS_GATEWAY_DETECTED = false;
|
||||||
|
|
||||||
|
void gatewayDetected(InetAddress addr, String id);
|
||||||
|
|
||||||
|
void thingDetectedTypicals(byte lastByteGatewayIP, byte typical, byte node, byte slot);
|
||||||
|
|
||||||
|
void thingDetectedActionMessages(String sTopicNumber, String sTopicVariant);
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.discovery;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissGatewayHandler;
|
||||||
|
import org.openhab.binding.souliss.internal.protocol.CommonCommands;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissDiscoverJob implements Runnable {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(SoulissDiscoverJob.class);
|
||||||
|
|
||||||
|
private final CommonCommands commonCommands = new CommonCommands();
|
||||||
|
|
||||||
|
private int resendCounter = 0;
|
||||||
|
|
||||||
|
private @Nullable SoulissGatewayHandler gwHandler;
|
||||||
|
|
||||||
|
public SoulissDiscoverJob(@Nullable SoulissGatewayHandler soulissGwHandler) {
|
||||||
|
this.gwHandler = soulissGwHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
var localGwHandler = this.gwHandler;
|
||||||
|
if (localGwHandler != null) {
|
||||||
|
commonCommands.sendDBStructFrame(localGwHandler.getGwConfig());
|
||||||
|
logger.debug("Sending request to gateway for souliss network - Counter={}", resendCounter);
|
||||||
|
} else {
|
||||||
|
logger.debug("Gateway null - Skipped");
|
||||||
|
}
|
||||||
|
resendCounter++;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,277 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.discovery;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissProtocolConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissGatewayHandler;
|
||||||
|
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||||
|
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||||
|
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||||
|
import org.openhab.core.config.discovery.DiscoveryService;
|
||||||
|
import org.openhab.core.thing.ThingUID;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandler;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link soulissHandlerFactory} is responsible for creating things and thingGeneric
|
||||||
|
* handlers.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissGatewayDiscovery extends AbstractDiscoveryService
|
||||||
|
implements DiscoverResult, DiscoveryService, ThingHandlerService {
|
||||||
|
private @Nullable ScheduledFuture<?> discoveryJob = null;
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(SoulissGatewayDiscovery.class);
|
||||||
|
|
||||||
|
private @Nullable SoulissDiscoverJob soulissDiscoverRunnableClass = null;
|
||||||
|
|
||||||
|
private @Nullable SoulissGatewayHandler soulissGwHandler;
|
||||||
|
|
||||||
|
public SoulissGatewayDiscovery() {
|
||||||
|
super(SoulissBindingConstants.SUPPORTED_THING_TYPES_UIDS, SoulissBindingConstants.DISCOVERY_TIMEOUT_IN_SECONDS,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deactivate() {
|
||||||
|
super.deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link gatewayDetected} callback used to create the Gateway
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void gatewayDetected(InetAddress addr, String id) {
|
||||||
|
logger.debug("Souliss gateway found: {} ", addr.getHostName());
|
||||||
|
|
||||||
|
String label = "Souliss Gateway " + (Byte.parseByte(id) & 0xFF);
|
||||||
|
Map<String, Object> properties = new TreeMap<>();
|
||||||
|
properties.put(SoulissBindingConstants.CONFIG_IP_ADDRESS, addr.getHostAddress());
|
||||||
|
var gatewayUID = new ThingUID(SoulissBindingConstants.GATEWAY_THING_TYPE,
|
||||||
|
Integer.toString((Byte.parseByte(id) & 0xFF)));
|
||||||
|
var discoveryResult = DiscoveryResultBuilder.create(gatewayUID).withLabel(label)
|
||||||
|
.withRepresentationProperty(SoulissBindingConstants.CONFIG_IP_ADDRESS).withProperties(properties)
|
||||||
|
.build();
|
||||||
|
thingDiscovered(discoveryResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void startScan() {
|
||||||
|
logger.debug("Starting Scan Service");
|
||||||
|
|
||||||
|
// create discovery class
|
||||||
|
if (soulissDiscoverRunnableClass == null) {
|
||||||
|
soulissDiscoverRunnableClass = new SoulissDiscoverJob(this.soulissGwHandler);
|
||||||
|
|
||||||
|
// send command for gw struct (typicals).. must be not soo much quick..
|
||||||
|
discoveryJob = scheduler.scheduleWithFixedDelay(soulissDiscoverRunnableClass, 2,
|
||||||
|
SoulissBindingConstants.DISCOVERY_RESEND_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
|
||||||
|
logger.debug("Start Discovery Job");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected synchronized void stopScan() {
|
||||||
|
ScheduledFuture<?> localDiscoveryJob = this.discoveryJob;
|
||||||
|
if (localDiscoveryJob != null) {
|
||||||
|
localDiscoveryJob.cancel(false);
|
||||||
|
soulissDiscoverRunnableClass = null;
|
||||||
|
logger.debug("Discovery Job Stopped");
|
||||||
|
}
|
||||||
|
super.stopScan();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void thingDetectedActionMessages(String topicNumber, String sTopicVariant) {
|
||||||
|
ThingUID thingUID = null;
|
||||||
|
var label = "";
|
||||||
|
DiscoveryResult discoveryResult;
|
||||||
|
String sNodeID = topicNumber + SoulissBindingConstants.UUID_NODE_SLOT_SEPARATOR + sTopicVariant;
|
||||||
|
|
||||||
|
var localGwHandler = this.soulissGwHandler;
|
||||||
|
if (localGwHandler != null) {
|
||||||
|
var gatewayUID = localGwHandler.getThing().getUID();
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.TOPICS_THING_TYPE, gatewayUID, sNodeID);
|
||||||
|
label = "Topic. Number: " + topicNumber + ", Variant: " + sTopicVariant;
|
||||||
|
|
||||||
|
discoveryResult = DiscoveryResultBuilder.create(thingUID).withLabel(label)
|
||||||
|
.withProperty("number", topicNumber).withProperty("variant", sTopicVariant)
|
||||||
|
.withRepresentationProperty("number").withBridge(gatewayUID).build();
|
||||||
|
thingDiscovered(discoveryResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void thingDetectedTypicals(byte lastByteGatewayIP, byte typical, byte node, byte slot) {
|
||||||
|
ThingUID thingUID = null;
|
||||||
|
var label = "";
|
||||||
|
DiscoveryResult discoveryResult;
|
||||||
|
var gwHandler = this.soulissGwHandler;
|
||||||
|
if ((gwHandler != null) && (lastByteGatewayIP == (byte) Integer
|
||||||
|
.parseInt(gwHandler.getGwConfig().gatewayLanAddress.split("\\.")[3]))) {
|
||||||
|
String sNodeId = node + SoulissBindingConstants.UUID_NODE_SLOT_SEPARATOR + slot;
|
||||||
|
|
||||||
|
ThingUID gatewayUID = gwHandler.getThing().getUID();
|
||||||
|
var slotLabel = "slot";
|
||||||
|
|
||||||
|
switch (typical) {
|
||||||
|
case SoulissProtocolConstants.SOULISS_T11:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T11_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T11: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T12:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T12_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T12: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T13:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T13_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T13: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T14:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T14_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T14: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T16:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T16_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T16: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T18:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T18_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T18: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T19:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T19_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T19: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T1A:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T1A_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T1A: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T21:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T21_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T21: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T22:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T22_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T22: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T41_ANTITHEFT_MAIN:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T41_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T41: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T42_ANTITHEFT_PEER:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T42_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T42: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T31:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T31_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T31: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T52_TEMPERATURE_SENSOR:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T52_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T52: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T53_HUMIDITY_SENSOR:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T53_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T53: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T54_LUX_SENSOR:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T54_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T54: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T55_VOLTAGE_SENSOR:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T55_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T55: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T56_CURRENT_SENSOR:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T56_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T56: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T57_POWER_SENSOR:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T57_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T57: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T61:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T61_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T61: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T62_TEMPERATURE_SENSOR:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T62_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T62: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T63_HUMIDITY_SENSOR:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T63_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T63: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T64_LUX_SENSOR:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T64_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T64: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T65_VOLTAGE_SENSOR:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T65_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T65: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T66_CURRENT_SENSOR:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T66_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T66: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T67_POWER_SENSOR:
|
||||||
|
thingUID = new ThingUID(SoulissBindingConstants.T67_THING_TYPE, gatewayUID, sNodeId);
|
||||||
|
label = "T67: node " + node + slotLabel + slot;
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
logger.debug("no supported things found ...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (thingUID != null) {
|
||||||
|
label = "[" + gwHandler.getThing().getUID().getAsString() + "] " + label;
|
||||||
|
var uniqueId = "N" + Byte.toString(node) + "S" + Byte.toString(slot);
|
||||||
|
discoveryResult = DiscoveryResultBuilder.create(thingUID).withLabel(label)
|
||||||
|
.withProperty(SoulissBindingConstants.PROPERTY_NODE, node)
|
||||||
|
.withProperty(SoulissBindingConstants.PROPERTY_SLOT, slot)
|
||||||
|
.withProperty(SoulissBindingConstants.PROPERTY_UNIQUEID, uniqueId)
|
||||||
|
.withRepresentationProperty(SoulissBindingConstants.PROPERTY_UNIQUEID)
|
||||||
|
.withBridge(gwHandler.getThing().getUID()).build();
|
||||||
|
thingDiscovered(discoveryResult);
|
||||||
|
gwHandler.setThereIsAThingDetection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setThingHandler(ThingHandler handler) {
|
||||||
|
if (handler instanceof SoulissGatewayHandler) {
|
||||||
|
var localGwHandler = this.soulissGwHandler;
|
||||||
|
localGwHandler = (SoulissGatewayHandler) handler;
|
||||||
|
localGwHandler.discoverResult = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable ThingHandler getThingHandler() {
|
||||||
|
return soulissGwHandler;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,248 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.config.GatewayConfig;
|
||||||
|
import org.openhab.binding.souliss.internal.discovery.DiscoverResult;
|
||||||
|
import org.openhab.binding.souliss.internal.discovery.SoulissGatewayDiscovery;
|
||||||
|
import org.openhab.binding.souliss.internal.protocol.CommonCommands;
|
||||||
|
import org.openhab.binding.souliss.internal.protocol.SendDispatcherRunnable;
|
||||||
|
import org.openhab.binding.souliss.internal.protocol.UDPListenDiscoverRunnable;
|
||||||
|
import org.openhab.core.common.NamedThreadFactory;
|
||||||
|
import org.openhab.core.thing.Bridge;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.thing.ThingStatusDetail;
|
||||||
|
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissGatewayHandler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissGatewayHandler extends BaseBridgeHandler {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(SoulissGatewayHandler.class);
|
||||||
|
|
||||||
|
private final CommonCommands commonCommands = new CommonCommands();
|
||||||
|
|
||||||
|
private @Nullable ExecutorService udpExecutorService;
|
||||||
|
|
||||||
|
private @Nullable Future<?> udpListenerJob;
|
||||||
|
private @Nullable ScheduledFuture<?> pingScheduler;
|
||||||
|
private @Nullable ScheduledFuture<?> subscriptionScheduler;
|
||||||
|
private @Nullable ScheduledFuture<?> healthScheduler;
|
||||||
|
|
||||||
|
boolean bGatewayDetected = false;
|
||||||
|
|
||||||
|
private @Nullable SoulissGatewayDiscovery discoveryService;
|
||||||
|
|
||||||
|
public @Nullable DiscoverResult discoverResult = null;
|
||||||
|
|
||||||
|
public boolean thereIsAThingDetection = true;
|
||||||
|
|
||||||
|
private Bridge bridge;
|
||||||
|
|
||||||
|
private int nodes = 0;
|
||||||
|
private int maxTypicalXnode = 24;
|
||||||
|
private int countPingKo = 0;
|
||||||
|
|
||||||
|
private GatewayConfig gwConfig = new GatewayConfig();
|
||||||
|
|
||||||
|
public GatewayConfig getGwConfig() {
|
||||||
|
return gwConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SoulissGatewayHandler(Bridge br) {
|
||||||
|
super(br);
|
||||||
|
bridge = br;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||||
|
return Collections.singleton(SoulissGatewayDiscovery.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
gwConfig = getConfigAs(GatewayConfig.class);
|
||||||
|
|
||||||
|
logger.debug("Starting UDP server on Souliss Default Port for Topics (Publish&Subcribe)");
|
||||||
|
|
||||||
|
// new runnable udp listener
|
||||||
|
var udpServerDefaultPortRunnableClass = new UDPListenDiscoverRunnable(this.bridge, this.discoverResult);
|
||||||
|
// and exec on thread
|
||||||
|
var localUdpListenerJob = this.udpListenerJob;
|
||||||
|
if (localUdpListenerJob == null || localUdpListenerJob.isCancelled()) {
|
||||||
|
var localUdpExecutorService = this.udpExecutorService;
|
||||||
|
localUdpExecutorService = Executors
|
||||||
|
.newSingleThreadExecutor(new NamedThreadFactory(getThing().getUID().getAsString()));
|
||||||
|
localUdpExecutorService.submit(udpServerDefaultPortRunnableClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
// JOB PING
|
||||||
|
var soulissGatewayJobPingRunnable = new SoulissGatewayJobPing(this.bridge);
|
||||||
|
pingScheduler = scheduler.scheduleWithFixedDelay(soulissGatewayJobPingRunnable, 2, this.gwConfig.pingInterval,
|
||||||
|
TimeUnit.SECONDS);
|
||||||
|
// JOB SUBSCRIPTION
|
||||||
|
var soulissGatewayJobSubscriptionRunnable = new SoulissGatewayJobSubscription(bridge);
|
||||||
|
subscriptionScheduler = scheduler.scheduleWithFixedDelay(soulissGatewayJobSubscriptionRunnable, 5,
|
||||||
|
this.gwConfig.subscriptionInterval, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// JOB HEALTH OF NODES
|
||||||
|
var soulissGatewayJobHealthyRunnable = new SoulissGatewayJobHealthy(this.bridge);
|
||||||
|
healthScheduler = scheduler.scheduleWithFixedDelay(soulissGatewayJobHealthyRunnable, 5,
|
||||||
|
this.gwConfig.healthyInterval, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
var soulissSendDispatcherRunnable = new SendDispatcherRunnable(this.bridge);
|
||||||
|
scheduler.scheduleWithFixedDelay(soulissSendDispatcherRunnable, 15,
|
||||||
|
SoulissBindingConstants.SEND_DISPATCHER_MIN_DELAY_CYCLE_IN_MILLIS, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dbStructAnswerReceived() {
|
||||||
|
commonCommands.sendTypicalRequestFrame(this.gwConfig, nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNodes(int nodes) {
|
||||||
|
this.nodes = nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNodes() {
|
||||||
|
var maxNode = 0;
|
||||||
|
for (Thing thing : getThing().getThings()) {
|
||||||
|
if (thing.getThingTypeUID().equals(SoulissBindingConstants.TOPICS_THING_TYPE)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var cfg = thing.getConfiguration();
|
||||||
|
var props = cfg.getProperties();
|
||||||
|
var pNode = props.get("node");
|
||||||
|
if (pNode != null) {
|
||||||
|
var thingNode = Integer.parseInt(pNode.toString());
|
||||||
|
|
||||||
|
if (thingNode > maxNode) {
|
||||||
|
maxNode = thingNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// at the end the length of the list will be equal to the number of present nodes
|
||||||
|
}
|
||||||
|
return maxNode + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxTypicalXnode(int maxTypicalXnode) {
|
||||||
|
this.maxTypicalXnode = maxTypicalXnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxTypicalXnode() {
|
||||||
|
return maxTypicalXnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link gatewayDetected} is used to notify that UDPServer decoded a Ping Response from gateway
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void gatewayDetected() {
|
||||||
|
updateStatus(ThingStatus.ONLINE);
|
||||||
|
// reset counter
|
||||||
|
countPingKo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pingSent() {
|
||||||
|
if (++countPingKo > 3) {
|
||||||
|
var bridgeHandler = bridge.getHandler();
|
||||||
|
if (bridgeHandler != null) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
|
"Gateway " + bridgeHandler.getThing().getUID() + " do not respond to " + countPingKo + " ping");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendSubscription() {
|
||||||
|
if (this.gwConfig.gatewayLanAddress.length() > 0) {
|
||||||
|
int totNodes = getNodes();
|
||||||
|
commonCommands.sendSUBSCRIPTIONframe(this.gwConfig, totNodes);
|
||||||
|
}
|
||||||
|
logger.debug("Sent subscription packet");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setThereIsAThingDetection() {
|
||||||
|
thereIsAThingDetection = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetThereIsAThingDetection() {
|
||||||
|
thereIsAThingDetection = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable SoulissGatewayDiscovery getDiscoveryService() {
|
||||||
|
return this.discoveryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDiscoveryService(SoulissGatewayDiscovery discoveryService) {
|
||||||
|
this.discoveryService = discoveryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
var localPingScheduler = this.pingScheduler;
|
||||||
|
if (localPingScheduler != null) {
|
||||||
|
localPingScheduler.cancel(true);
|
||||||
|
}
|
||||||
|
var localSubscriptionScheduler = this.subscriptionScheduler;
|
||||||
|
if (localSubscriptionScheduler != null) {
|
||||||
|
localSubscriptionScheduler.cancel(true);
|
||||||
|
}
|
||||||
|
var localHealthScheduler = this.healthScheduler;
|
||||||
|
if (localHealthScheduler != null) {
|
||||||
|
localHealthScheduler.cancel(true);
|
||||||
|
}
|
||||||
|
var localUdpListenerJob = this.udpListenerJob;
|
||||||
|
if (localUdpListenerJob != null) {
|
||||||
|
localUdpListenerJob.cancel(true);
|
||||||
|
}
|
||||||
|
var localUdpExecutorService = this.udpExecutorService;
|
||||||
|
if (localUdpExecutorService != null) {
|
||||||
|
localUdpExecutorService.shutdownNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBridgeStatus(boolean isOnline) {
|
||||||
|
logger.debug("setBridgeStatus(): Setting Bridge to {}", isOnline ? ThingStatus.ONLINE : ThingStatus.OFFLINE);
|
||||||
|
|
||||||
|
updateStatus(isOnline ? ThingStatus.ONLINE : ThingStatus.OFFLINE);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.protocol.CommonCommands;
|
||||||
|
import org.openhab.core.thing.Bridge;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissGatewayJobHealthy implements Runnable {
|
||||||
|
|
||||||
|
private @Nullable SoulissGatewayHandler gwHandler;
|
||||||
|
|
||||||
|
private final CommonCommands commonCommands = new CommonCommands();
|
||||||
|
|
||||||
|
public SoulissGatewayJobHealthy(Bridge bridge) {
|
||||||
|
this.gwHandler = (SoulissGatewayHandler) bridge.getHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
sendHealthyRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendHealthyRequest() {
|
||||||
|
var localGwHandler = this.gwHandler;
|
||||||
|
// sending healthy packet
|
||||||
|
if ((localGwHandler != null) && (localGwHandler.getGwConfig().gatewayLanAddress.length() > 0)) {
|
||||||
|
commonCommands.sendHealthyRequestFrame(localGwHandler.getGwConfig(), localGwHandler.getNodes());
|
||||||
|
// healthy packet sent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.protocol.CommonCommands;
|
||||||
|
import org.openhab.core.thing.Bridge;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissGatewayJobPing implements Runnable {
|
||||||
|
|
||||||
|
private @Nullable SoulissGatewayHandler gwHandler;
|
||||||
|
|
||||||
|
private final CommonCommands commonCommands = new CommonCommands();
|
||||||
|
|
||||||
|
public SoulissGatewayJobPing(Bridge bridge) {
|
||||||
|
var bridgeHandler = bridge.getHandler();
|
||||||
|
if (bridgeHandler != null) {
|
||||||
|
gwHandler = (SoulissGatewayHandler) bridgeHandler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
SoulissGatewayHandler localGwHandler = this.gwHandler;
|
||||||
|
if (localGwHandler != null) {
|
||||||
|
sendPing(localGwHandler);
|
||||||
|
|
||||||
|
localGwHandler.pingSent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendPing(SoulissGatewayHandler soulissGwHandler) {
|
||||||
|
// sending ping packet
|
||||||
|
|
||||||
|
if (soulissGwHandler.getGwConfig().gatewayLanAddress.length() > 0) {
|
||||||
|
commonCommands.sendPing(soulissGwHandler.getGwConfig());
|
||||||
|
// ping packet sent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.core.thing.Bridge;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissGatewayJobSubscription implements Runnable {
|
||||||
|
|
||||||
|
private @Nullable SoulissGatewayHandler gwHandler;
|
||||||
|
|
||||||
|
public SoulissGatewayJobSubscription(Bridge bridge) {
|
||||||
|
this.gwHandler = (SoulissGatewayHandler) bridge.getHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
sendSubscription();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendSubscription() {
|
||||||
|
SoulissGatewayHandler localGwHandler = this.gwHandler;
|
||||||
|
if (localGwHandler != null) {
|
||||||
|
localGwHandler.sendSubscription();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.library.types.DateTimeType;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class implements the base Souliss Action Message. All Action Messages derives from
|
||||||
|
* this class
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
* @author Tonino Fazio - @since 1.7.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public abstract class SoulissGenericActionMessage extends BaseThingHandler {
|
||||||
|
|
||||||
|
Thing thingGenActMsg;
|
||||||
|
|
||||||
|
private String sTopicNumber = "";
|
||||||
|
private String sTopicVariant = "";
|
||||||
|
|
||||||
|
private String timestamp = "";
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(SoulissGenericActionMessage.class);
|
||||||
|
|
||||||
|
protected SoulissGenericActionMessage(Thing pThing) {
|
||||||
|
super(pThing);
|
||||||
|
thingGenActMsg = pThing;
|
||||||
|
|
||||||
|
try {
|
||||||
|
var cfg = thingGenActMsg.getConfiguration();
|
||||||
|
var props = cfg.getProperties();
|
||||||
|
var pTopicNumber = props.get("number");
|
||||||
|
var pTopicVariant = props.get("number");
|
||||||
|
if (pTopicNumber != null) {
|
||||||
|
sTopicNumber = pTopicNumber.toString();
|
||||||
|
}
|
||||||
|
if (pTopicVariant != null) {
|
||||||
|
sTopicVariant = pTopicVariant.toString();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.debug("Item Definition Error. Use ex:'souliss:t11:thing_id'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the Topic Number
|
||||||
|
*/
|
||||||
|
public String getTopicNumber() {
|
||||||
|
return sTopicNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param the Topic Variant
|
||||||
|
*/
|
||||||
|
public String getTopicVariant() {
|
||||||
|
return sTopicVariant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTimeType getLastUpdateTime() {
|
||||||
|
return DateTimeType.valueOf(timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateTimeNow() {
|
||||||
|
timestamp = getTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a time stamp as "yyyy-MM-dd'T'HH:mm:ssz"
|
||||||
|
*
|
||||||
|
* @return String timestamp
|
||||||
|
*/
|
||||||
|
private static String getTimestamp() {
|
||||||
|
// Pattern : yyyy-MM-dd'T'HH:mm:ssz
|
||||||
|
var sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSz");
|
||||||
|
var n = new Date();
|
||||||
|
return sdf.format(n.getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void thingUpdated(Thing thing) {
|
||||||
|
this.thingGenActMsg = thing;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,214 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissProtocolConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.config.GatewayConfig;
|
||||||
|
import org.openhab.binding.souliss.internal.protocol.CommonCommands;
|
||||||
|
import org.openhab.core.library.types.DateTimeType;
|
||||||
|
import org.openhab.core.library.types.DecimalType;
|
||||||
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
import org.openhab.core.library.types.OpenClosedType;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.thing.ThingStatusDetail;
|
||||||
|
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class implements the base Souliss Typical All other Typicals derive from
|
||||||
|
* this class
|
||||||
|
*
|
||||||
|
* ...from wiki of Dario De Maio
|
||||||
|
* In Souliss the logics that drive your lights, curtains, LED, and
|
||||||
|
* others are pre-configured into so called Typicals. A Typical is a
|
||||||
|
* logic with a predefined set of inputs and outputs and a know
|
||||||
|
* behavior, are used to standardize the user interface and have a
|
||||||
|
* configuration-less behavior.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public abstract class SoulissGenericHandler extends BaseThingHandler implements TypicalCommonMethods {
|
||||||
|
|
||||||
|
private int iSlot;
|
||||||
|
private int iNode;
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(SoulissGenericHandler.class);
|
||||||
|
|
||||||
|
private final CommonCommands commonCommands = new CommonCommands();
|
||||||
|
|
||||||
|
// 0 means that Secure Send is disabled
|
||||||
|
boolean bSecureSend = false;
|
||||||
|
// true means that expected value is setpoint (only for T31, T19 and T6x)
|
||||||
|
boolean bExpectedValueSameAsSet = false;
|
||||||
|
|
||||||
|
protected SoulissGenericHandler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the iSlot
|
||||||
|
*/
|
||||||
|
public int getSlot() {
|
||||||
|
return iSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
try {
|
||||||
|
var cfg = thing.getConfiguration();
|
||||||
|
var props = cfg.getProperties();
|
||||||
|
|
||||||
|
var pNode = props.get("node");
|
||||||
|
var pSlot = props.get("slot");
|
||||||
|
|
||||||
|
if ((pNode != null) && (pSlot != null)) {
|
||||||
|
iNode = Integer.parseInt(pNode.toString());
|
||||||
|
iSlot = Integer.parseInt(pSlot.toString());
|
||||||
|
updateProperty(SoulissBindingConstants.PROPERTY_NODE, Integer.toString(iNode));
|
||||||
|
updateProperty(SoulissBindingConstants.PROPERTY_SLOT, Integer.toString(iSlot));
|
||||||
|
updateProperty(SoulissBindingConstants.PROPERTY_UNIQUEID,
|
||||||
|
"N" + Integer.toString(iNode) + "S" + Integer.toString(iSlot));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||||
|
"Error getting node/slot from souliss typical (thing config)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param SoulissNode
|
||||||
|
* the SoulissNodeID to get
|
||||||
|
*/
|
||||||
|
public int getNode() {
|
||||||
|
return iNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected synchronized void commandReadNodeTypsStates() {
|
||||||
|
var gwConfig = getGatewayConfig();
|
||||||
|
if (gwConfig != null) {
|
||||||
|
commonCommands.sendTypicalRequestFrame(gwConfig, this.getNode(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a command as hexadecimal, e.g.: SOULISS_T1N_ON_CMD = 0x02; short
|
||||||
|
* SOULISS_T1N_OFF_CMD = 0x04;
|
||||||
|
*
|
||||||
|
* @param command
|
||||||
|
*/
|
||||||
|
public void commandSEND(byte command) {
|
||||||
|
var gwConfig = getGatewayConfig();
|
||||||
|
if (gwConfig != null) {
|
||||||
|
commonCommands.sendFORCEFrame(gwConfig, this.getNode(), this.getSlot(), command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void commandSendRgb(byte command, byte r, byte g, byte b) {
|
||||||
|
var gwConfig = getGatewayConfig();
|
||||||
|
if (gwConfig != null) {
|
||||||
|
commonCommands.sendFORCEFrame(gwConfig, command, r, g, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void commandSEND(byte command, byte b1, byte b2) {
|
||||||
|
var gwConfig = getGatewayConfig();
|
||||||
|
if (gwConfig != null) {
|
||||||
|
commonCommands.sendFORCEFrameT31SetPoint(gwConfig, this.getNode(), this.getSlot(), command, b1, b2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void commandSEND(byte b1, byte b2) {
|
||||||
|
var gwConfig = getGatewayConfig();
|
||||||
|
if (gwConfig != null) {
|
||||||
|
commonCommands.sendFORCEFrameT61SetPoint(gwConfig, this.getNode(), this.getSlot(), b1, b2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a time stamp as "yyyy-MM-dd'T'HH:mm:ssz"
|
||||||
|
*
|
||||||
|
* @return String timestamp
|
||||||
|
*/
|
||||||
|
private static String getTimestamp() {
|
||||||
|
// Pattern : yyyy-MM-dd'T'HH:mm:ssz
|
||||||
|
var sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSz");
|
||||||
|
var n = new Date();
|
||||||
|
return sdf.format(n.getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void thingUpdated(Thing thing) {
|
||||||
|
updateThing(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable GatewayConfig getGatewayConfig() {
|
||||||
|
var bridge = getBridge();
|
||||||
|
if (bridge != null) {
|
||||||
|
SoulissGatewayHandler bridgeHandler = (SoulissGatewayHandler) bridge.getHandler();
|
||||||
|
if (bridgeHandler != null) {
|
||||||
|
return bridgeHandler.getGwConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable String getLabel() {
|
||||||
|
return getThing().getLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHealthy(byte shHealthy) {
|
||||||
|
this.updateState(SoulissBindingConstants.HEALTHY_CHANNEL, new DecimalType(shHealthy & 0xFF));
|
||||||
|
this.updateStatus(ThingStatus.ONLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastStatusStored() {
|
||||||
|
this.updateState(SoulissBindingConstants.LASTSTATUSSTORED_CHANNEL, DateTimeType.valueOf(getTimestamp()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected @Nullable OnOffType getOhStateOnOffFromSoulissVal(byte sVal) {
|
||||||
|
if (sVal == SoulissProtocolConstants.SOULISS_T1N_ON_COIL) {
|
||||||
|
return OnOffType.ON;
|
||||||
|
} else if (sVal == SoulissProtocolConstants.SOULISS_T1N_OFF_COIL) {
|
||||||
|
return OnOffType.OFF;
|
||||||
|
} else if (sVal == SoulissProtocolConstants.SOULISS_T1N_ON_FEEDBACK) {
|
||||||
|
return OnOffType.ON;
|
||||||
|
} else if (sVal == SoulissProtocolConstants.SOULISS_T1N_OFF_FEEDBACK) {
|
||||||
|
return OnOffType.OFF;
|
||||||
|
} else if (sVal == SoulissProtocolConstants.SOULISS_T4N_NOT_ARMED) {
|
||||||
|
return OnOffType.OFF;
|
||||||
|
} else if (sVal == SoulissProtocolConstants.SOULISS_T4N_ARMED) {
|
||||||
|
return OnOffType.ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected @Nullable OpenClosedType getOhStateOpenCloseFromSoulissVal(byte sVal) {
|
||||||
|
if (sVal == SoulissProtocolConstants.SOULISS_T1N_ON_COIL) {
|
||||||
|
return OpenClosedType.CLOSED;
|
||||||
|
} else if (sVal == SoulissProtocolConstants.SOULISS_T1N_OFF_COIL) {
|
||||||
|
return OpenClosedType.OPEN;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,139 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissProtocolConstants;
|
||||||
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.PrimitiveType;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT11Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT11Handler extends SoulissGenericHandler {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(SoulissT11Handler.class);
|
||||||
|
private byte t1nRawState = 0xF; // dummy value for first init
|
||||||
|
private byte xSleepTime = 0;
|
||||||
|
|
||||||
|
public SoulissT11Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
if (command instanceof RefreshType) {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SoulissBindingConstants.ONOFF_CHANNEL:
|
||||||
|
OnOffType val = getOhStateOnOffFromSoulissVal(t1nRawState);
|
||||||
|
if (val != null) {
|
||||||
|
updateState(channelUID, val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.debug("Unknown channel for T11 thing: {}", channelUID);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SoulissBindingConstants.ONOFF_CHANNEL:
|
||||||
|
if (command.equals(OnOffType.ON)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_ON_CMD);
|
||||||
|
} else if (command.equals(OnOffType.OFF)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_OFF_CMD);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SoulissBindingConstants.SLEEP_CHANNEL:
|
||||||
|
if (command.equals(OnOffType.ON)) {
|
||||||
|
commandSEND((byte) (SoulissProtocolConstants.SOULISS_T1N_TIMED + xSleepTime));
|
||||||
|
// set Off
|
||||||
|
updateState(channelUID, OnOffType.OFF);
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.debug("Unknown channel for T11 thing: {}", channelUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
|
||||||
|
var configurationMap = getThing().getConfiguration();
|
||||||
|
if (configurationMap.get(SoulissBindingConstants.SLEEP_CHANNEL) != null) {
|
||||||
|
xSleepTime = ((BigDecimal) configurationMap.get(SoulissBindingConstants.SLEEP_CHANNEL)).byteValue();
|
||||||
|
}
|
||||||
|
if (configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND) != null) {
|
||||||
|
bSecureSend = ((Boolean) configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND)).booleanValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getExpectedRawState(byte bCmd) {
|
||||||
|
if (bSecureSend) {
|
||||||
|
if (bCmd == SoulissProtocolConstants.SOULISS_T1N_ON_CMD) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T1N_ON_COIL;
|
||||||
|
} else if (bCmd == SoulissProtocolConstants.SOULISS_T1N_OFF_CMD) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T1N_OFF_COIL;
|
||||||
|
} else if (bCmd >= SoulissProtocolConstants.SOULISS_T1N_TIMED) {
|
||||||
|
// SLEEP
|
||||||
|
return SoulissProtocolConstants.SOULISS_T1N_ON_COIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setState(@Nullable PrimitiveType state) {
|
||||||
|
if (state != null) {
|
||||||
|
this.updateState(SoulissBindingConstants.SLEEP_CHANNEL, OnOffType.OFF);
|
||||||
|
this.updateState(SoulissBindingConstants.ONOFF_CHANNEL, (OnOffType) state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawState(byte rawState) {
|
||||||
|
// update Last Status stored time
|
||||||
|
super.setLastStatusStored();
|
||||||
|
// update item state only if it is different from previous
|
||||||
|
if (t1nRawState != rawState) {
|
||||||
|
this.setState(getOhStateOnOffFromSoulissVal(rawState));
|
||||||
|
}
|
||||||
|
t1nRawState = rawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getRawState() {
|
||||||
|
return t1nRawState;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,176 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissProtocolConstants;
|
||||||
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.PrimitiveType;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT12Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT12Handler extends SoulissGenericHandler {
|
||||||
|
|
||||||
|
private byte t1nRawState = 0xF;
|
||||||
|
private byte xSleepTime = 0;
|
||||||
|
|
||||||
|
public SoulissT12Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
|
||||||
|
var configurationMap = getThing().getConfiguration();
|
||||||
|
if (configurationMap.get(SoulissBindingConstants.SLEEP_CHANNEL) != null) {
|
||||||
|
xSleepTime = ((BigDecimal) configurationMap.get(SoulissBindingConstants.SLEEP_CHANNEL)).byteValue();
|
||||||
|
}
|
||||||
|
if (configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND) != null) {
|
||||||
|
bSecureSend = ((Boolean) configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND)).booleanValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
if (command instanceof RefreshType) {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SoulissBindingConstants.ONOFF_CHANNEL:
|
||||||
|
switch (t1nRawState) {
|
||||||
|
case SoulissProtocolConstants.SOULISS_T1N_ON_COIL_AUTO:
|
||||||
|
case SoulissProtocolConstants.SOULISS_T1N_ON_COIL:
|
||||||
|
this.setState(OnOffType.ON);
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T1N_OFF_COIL_AUTO:
|
||||||
|
case SoulissProtocolConstants.SOULISS_T1N_OFF_COIL:
|
||||||
|
this.setState(OnOffType.OFF);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.AUTOMODE_CHANNEL:
|
||||||
|
switch (t1nRawState) {
|
||||||
|
case SoulissProtocolConstants.SOULISS_T1N_ON_COIL_AUTO:
|
||||||
|
case SoulissProtocolConstants.SOULISS_T1N_OFF_COIL_AUTO:
|
||||||
|
this.setStateAutomode(OnOffType.ON);
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T1N_ON_COIL:
|
||||||
|
case SoulissProtocolConstants.SOULISS_T1N_OFF_COIL:
|
||||||
|
this.setStateAutomode(OnOffType.OFF);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
|
||||||
|
{
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SoulissBindingConstants.ONOFF_CHANNEL:
|
||||||
|
if (command.equals(OnOffType.ON)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_ON_CMD);
|
||||||
|
} else if (command.equals(OnOffType.OFF)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_OFF_CMD);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.AUTOMODE_CHANNEL:
|
||||||
|
if (command.equals(OnOffType.ON)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_AUTO_CMD);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.SLEEP_CHANNEL:
|
||||||
|
if (command.equals(OnOffType.ON)) {
|
||||||
|
commandSEND((byte) (SoulissProtocolConstants.SOULISS_T1N_TIMED + xSleepTime));
|
||||||
|
// set Off
|
||||||
|
updateState(channelUID, OnOffType.OFF);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(PrimitiveType state) {
|
||||||
|
this.updateState(SoulissBindingConstants.ONOFF_CHANNEL, (OnOffType) state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStateAutomode(PrimitiveType state) {
|
||||||
|
this.updateState(SoulissBindingConstants.AUTOMODE_CHANNEL, (OnOffType) state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawState(byte rawState) {
|
||||||
|
// update Last Status stored time
|
||||||
|
super.setLastStatusStored();
|
||||||
|
|
||||||
|
// update item state only if it is different from previous
|
||||||
|
if (t1nRawState != rawState) {
|
||||||
|
if (rawState == SoulissProtocolConstants.SOULISS_T1N_ON_COIL_AUTO) {
|
||||||
|
this.setState(OnOffType.ON);
|
||||||
|
this.setStateAutomode(OnOffType.ON);
|
||||||
|
} else if (rawState == SoulissProtocolConstants.SOULISS_T1N_OFF_COIL_AUTO) {
|
||||||
|
this.setState(OnOffType.OFF);
|
||||||
|
this.setStateAutomode(OnOffType.ON);
|
||||||
|
} else if (rawState == SoulissProtocolConstants.SOULISS_T1N_ON_COIL) {
|
||||||
|
this.setState(OnOffType.ON);
|
||||||
|
this.setStateAutomode(OnOffType.OFF);
|
||||||
|
} else if (rawState == SoulissProtocolConstants.SOULISS_T1N_OFF_COIL) {
|
||||||
|
this.setState(OnOffType.OFF);
|
||||||
|
this.setStateAutomode(OnOffType.OFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t1nRawState = rawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getRawState() {
|
||||||
|
return t1nRawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getExpectedRawState(byte bCommand) {
|
||||||
|
if (bSecureSend) {
|
||||||
|
if (bCommand == SoulissProtocolConstants.SOULISS_T1N_ON_CMD) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T1N_ON_COIL;
|
||||||
|
} else if (bCommand == SoulissProtocolConstants.SOULISS_T1N_OFF_CMD) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T1N_OFF_COIL;
|
||||||
|
} else if (bCommand >= SoulissProtocolConstants.SOULISS_T1N_TIMED) {
|
||||||
|
// SLEEP
|
||||||
|
return SoulissProtocolConstants.SOULISS_T1N_ON_COIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
import org.openhab.core.library.types.OpenClosedType;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.PrimitiveType;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT13Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT13Handler extends SoulissGenericHandler {
|
||||||
|
|
||||||
|
private byte t1nRawState = 0xF;
|
||||||
|
|
||||||
|
public SoulissT13Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(@Nullable PrimitiveType state) {
|
||||||
|
super.setLastStatusStored();
|
||||||
|
if (state != null) {
|
||||||
|
if (state instanceof OnOffType) {
|
||||||
|
this.updateState(SoulissBindingConstants.STATEONOFF_CHANNEL, (OnOffType) state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state instanceof OpenClosedType) {
|
||||||
|
this.updateState(SoulissBindingConstants.STATEOPENCLOSE_CHANNEL, (OpenClosedType) state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
if (command instanceof RefreshType) {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SoulissBindingConstants.STATEONOFF_CHANNEL:
|
||||||
|
OnOffType valonOff = getOhStateOnOffFromSoulissVal(t1nRawState);
|
||||||
|
if (valonOff != null) {
|
||||||
|
updateState(channelUID, valonOff);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.STATEOPENCLOSE_CHANNEL:
|
||||||
|
OpenClosedType valOpenClose = getOhStateOpenCloseFromSoulissVal(t1nRawState);
|
||||||
|
if (valOpenClose != null) {
|
||||||
|
updateState(channelUID, valOpenClose);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawState(byte rawState) {
|
||||||
|
// update Last Status stored time
|
||||||
|
super.setLastStatusStored();
|
||||||
|
// update item state only if it is different from previous
|
||||||
|
if (t1nRawState != rawState) {
|
||||||
|
this.setState(getOhStateOpenCloseFromSoulissVal(rawState));
|
||||||
|
this.setState(getOhStateOnOffFromSoulissVal(rawState));
|
||||||
|
}
|
||||||
|
t1nRawState = rawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getRawState() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getExpectedRawState(byte bCommand) {
|
||||||
|
// Secure Send is disabled
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,107 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissProtocolConstants;
|
||||||
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.PrimitiveType;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT14Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT14Handler extends SoulissGenericHandler {
|
||||||
|
|
||||||
|
private byte t1nRawState = 0xF;
|
||||||
|
|
||||||
|
public SoulissT14Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
if (command instanceof RefreshType) {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SoulissBindingConstants.PULSE_CHANNEL:
|
||||||
|
OnOffType valPulse = getOhStateOnOffFromSoulissVal(t1nRawState);
|
||||||
|
if (valPulse != null) {
|
||||||
|
updateState(channelUID, valPulse);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SoulissBindingConstants.PULSE_CHANNEL:
|
||||||
|
if (command.equals(OnOffType.ON)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_ON_CMD);
|
||||||
|
} else if (command.equals(OnOffType.OFF)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_OFF_CMD);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(@Nullable PrimitiveType state) {
|
||||||
|
super.setLastStatusStored();
|
||||||
|
if (state != null) {
|
||||||
|
this.updateState(SoulissBindingConstants.PULSE_CHANNEL, (OnOffType) state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawState(byte rawState) {
|
||||||
|
// update Last Status stored time
|
||||||
|
super.setLastStatusStored();
|
||||||
|
// update item state only if it is different from previous
|
||||||
|
if (t1nRawState != rawState) {
|
||||||
|
this.setState(getOhStateOnOffFromSoulissVal(rawState));
|
||||||
|
}
|
||||||
|
t1nRawState = rawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getRawState() {
|
||||||
|
return t1nRawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getExpectedRawState(byte bCommand) {
|
||||||
|
// Secure Send is disabled for T14
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,233 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissProtocolConstants;
|
||||||
|
import org.openhab.core.library.types.HSBType;
|
||||||
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
import org.openhab.core.library.types.PercentType;
|
||||||
|
import org.openhab.core.library.types.UpDownType;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.PrimitiveType;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT16Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT16Handler extends SoulissGenericHandler {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(SoulissT16Handler.class);
|
||||||
|
private byte t1nRawStateByte0 = 0xF;
|
||||||
|
private byte t1nRawStateRedByte1 = 0x00;
|
||||||
|
private byte t1nRawStateGreenByte2 = 0x00;
|
||||||
|
private byte t1nRawStateBluByte3 = 0x00;
|
||||||
|
|
||||||
|
private HSBType hsbState = HSBType.WHITE;
|
||||||
|
|
||||||
|
byte xSleepTime = 0;
|
||||||
|
|
||||||
|
public SoulissT16Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
if (command instanceof RefreshType) {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SoulissBindingConstants.ONOFF_CHANNEL:
|
||||||
|
OnOffType valOnOff = getOhStateOnOffFromSoulissVal(t1nRawStateByte0);
|
||||||
|
if (valOnOff != null) {
|
||||||
|
updateState(channelUID, valOnOff);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.LED_COLOR_CHANNEL:
|
||||||
|
updateState(channelUID, gethsb(t1nRawStateRedByte1, t1nRawStateGreenByte2, t1nRawStateBluByte3));
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.DIMMER_BRIGHTNESS_CHANNEL:
|
||||||
|
updateState(channelUID,
|
||||||
|
PercentType.valueOf(gethsb(t1nRawStateRedByte1, t1nRawStateGreenByte2, t1nRawStateBluByte3)
|
||||||
|
.getBrightness().toString()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SoulissBindingConstants.ONOFF_CHANNEL:
|
||||||
|
if (command.equals(OnOffType.ON)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_ON_CMD);
|
||||||
|
|
||||||
|
} else if (command.equals(OnOffType.OFF)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_OFF_CMD);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.WHITE_MODE_CHANNEL:
|
||||||
|
if (command instanceof OnOffType) {
|
||||||
|
hsbState = HSBType.fromRGB(255, 255, 255);
|
||||||
|
commandSendRgb(SoulissProtocolConstants.SOULISS_T1N_SET, (byte) 255, (byte) 255, (byte) 255);
|
||||||
|
updateState(SoulissBindingConstants.LED_COLOR_CHANNEL, hsbState);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.SLEEP_CHANNEL:
|
||||||
|
if (command instanceof OnOffType) {
|
||||||
|
commandSEND((byte) (SoulissProtocolConstants.SOULISS_T1N_TIMED + xSleepTime));
|
||||||
|
// set Off
|
||||||
|
updateState(channelUID, OnOffType.OFF);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SoulissBindingConstants.DIMMER_BRIGHTNESS_CHANNEL:
|
||||||
|
if (command instanceof PercentType) {
|
||||||
|
updateState(SoulissBindingConstants.LED_COLOR_CHANNEL,
|
||||||
|
gethsb(t1nRawStateRedByte1, t1nRawStateGreenByte2, t1nRawStateBluByte3));
|
||||||
|
commandSendRgb(SoulissProtocolConstants.SOULISS_T1N_SET,
|
||||||
|
(byte) (hsbState.getRed().shortValue() * (255.00 / 100)),
|
||||||
|
(byte) (hsbState.getGreen().shortValue() * (255.00 / 100)),
|
||||||
|
(byte) (hsbState.getBlue().shortValue() * (255.00 / 100)));
|
||||||
|
|
||||||
|
} else if (command.equals(OnOffType.ON)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_ON_CMD);
|
||||||
|
|
||||||
|
} else if (command.equals(OnOffType.OFF)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_OFF_CMD);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SoulissBindingConstants.ROLLER_BRIGHTNESS_CHANNEL:
|
||||||
|
if (command.equals(UpDownType.UP)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_BRIGHT_UP);
|
||||||
|
} else if (command.equals(UpDownType.DOWN)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_BRIGHT_DOWN);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SoulissBindingConstants.LED_COLOR_CHANNEL:
|
||||||
|
if (command instanceof HSBType) {
|
||||||
|
HSBType localHsbState = (HSBType) command;
|
||||||
|
|
||||||
|
updateState(SoulissBindingConstants.DIMMER_BRIGHTNESS_CHANNEL,
|
||||||
|
PercentType.valueOf(hsbState.getBrightness().toString()));
|
||||||
|
commandSendRgb(SoulissProtocolConstants.SOULISS_T1N_SET,
|
||||||
|
(byte) (localHsbState.getRed().shortValue() * 255.00 / 100),
|
||||||
|
(byte) (localHsbState.getGreen().shortValue() * 255.00 / 100),
|
||||||
|
(byte) (localHsbState.getBlue().shortValue() * 255.00 / 100));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
|
||||||
|
var configurationMap = getThing().getConfiguration();
|
||||||
|
|
||||||
|
if (configurationMap.get(SoulissBindingConstants.SLEEP_CHANNEL) != null) {
|
||||||
|
xSleepTime = ((BigDecimal) configurationMap.get(SoulissBindingConstants.SLEEP_CHANNEL)).byteValue();
|
||||||
|
}
|
||||||
|
if (configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND) != null) {
|
||||||
|
bSecureSend = ((Boolean) configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND)).booleanValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setState(@Nullable PrimitiveType state) {
|
||||||
|
super.setLastStatusStored();
|
||||||
|
updateState(SoulissBindingConstants.SLEEP_CHANNEL, OnOffType.OFF);
|
||||||
|
if (state != null) {
|
||||||
|
logger.debug("T16, setting state to {}", state.toFullString());
|
||||||
|
this.updateState(SoulissBindingConstants.ONOFF_CHANNEL, (OnOffType) state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawState(byte rawState) {
|
||||||
|
throw new UnsupportedOperationException("Not Implemented, yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRawStateCommand(byte rawStateByte0) {
|
||||||
|
super.setLastStatusStored();
|
||||||
|
if (rawStateByte0 != t1nRawStateByte0) {
|
||||||
|
this.setState(getOhStateOnOffFromSoulissVal(rawStateByte0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRawStateRgb(byte rawStateRedByte1, byte rawStateGreenByte2, byte rawStateBluByte3) {
|
||||||
|
super.setLastStatusStored();
|
||||||
|
|
||||||
|
if (rawStateRedByte1 != t1nRawStateRedByte1 || rawStateGreenByte2 != t1nRawStateGreenByte2
|
||||||
|
|| rawStateBluByte3 != t1nRawStateBluByte3) {
|
||||||
|
HSBType localHsbState = gethsb(rawStateRedByte1, rawStateGreenByte2, rawStateBluByte3);
|
||||||
|
logger.debug("T16, setting color to {},{},{}", rawStateRedByte1, rawStateGreenByte2, rawStateBluByte3);
|
||||||
|
|
||||||
|
updateState(SoulissBindingConstants.DIMMER_BRIGHTNESS_CHANNEL,
|
||||||
|
PercentType.valueOf(localHsbState.getBrightness().toString()));
|
||||||
|
|
||||||
|
updateState(SoulissBindingConstants.LED_COLOR_CHANNEL, localHsbState);
|
||||||
|
}
|
||||||
|
|
||||||
|
t1nRawStateRedByte1 = rawStateRedByte1;
|
||||||
|
t1nRawStateGreenByte2 = rawStateGreenByte2;
|
||||||
|
t1nRawStateBluByte3 = rawStateBluByte3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getRawState() {
|
||||||
|
throw new UnsupportedOperationException("Not Implemented, yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getRawStateCommand() {
|
||||||
|
return t1nRawStateByte0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getRawStateValues() {
|
||||||
|
return new byte[] { t1nRawStateRedByte1, t1nRawStateGreenByte2, t1nRawStateBluByte3 };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getExpectedRawState(byte bCmd) {
|
||||||
|
if (bSecureSend) {
|
||||||
|
if (bCmd == SoulissProtocolConstants.SOULISS_T1N_ON_CMD) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T1N_ON_COIL;
|
||||||
|
} else if (bCmd == SoulissProtocolConstants.SOULISS_T1N_OFF_CMD) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T1N_OFF_COIL;
|
||||||
|
} else if (bCmd >= SoulissProtocolConstants.SOULISS_T1N_TIMED) {
|
||||||
|
// SLEEP
|
||||||
|
return SoulissProtocolConstants.SOULISS_T1N_ON_COIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HSBType gethsb(byte rawStateRedByte1, byte rawStateGreenByte2, byte rawStateBluByte3) {
|
||||||
|
return HSBType.fromRGB(rawStateRedByte1, rawStateGreenByte2, rawStateBluByte3);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,128 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissProtocolConstants;
|
||||||
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.PrimitiveType;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT18Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT18Handler extends SoulissGenericHandler {
|
||||||
|
|
||||||
|
byte t1nRawState = 0xF;
|
||||||
|
byte xSleepTime = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
|
||||||
|
var configurationMap = getThing().getConfiguration();
|
||||||
|
|
||||||
|
if (configurationMap.get(SoulissBindingConstants.SLEEP_CHANNEL) != null) {
|
||||||
|
xSleepTime = ((BigDecimal) configurationMap.get(SoulissBindingConstants.SLEEP_CHANNEL)).byteValue();
|
||||||
|
}
|
||||||
|
if (configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND) != null) {
|
||||||
|
bSecureSend = ((Boolean) configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND)).booleanValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SoulissT18Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
if (command instanceof RefreshType) {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SoulissBindingConstants.PULSE_CHANNEL:
|
||||||
|
OnOffType valPulse = getOhStateOnOffFromSoulissVal(t1nRawState);
|
||||||
|
if (valPulse != null) {
|
||||||
|
updateState(channelUID, valPulse);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SoulissBindingConstants.ONOFF_CHANNEL:
|
||||||
|
if (command.equals(OnOffType.ON)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_ON_CMD);
|
||||||
|
} else if (command.equals(OnOffType.OFF)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_OFF_CMD);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setState(@Nullable PrimitiveType state) {
|
||||||
|
if (state != null) {
|
||||||
|
updateState(SoulissBindingConstants.SLEEP_CHANNEL, OnOffType.OFF);
|
||||||
|
this.updateState(SoulissBindingConstants.ONOFF_CHANNEL, (OnOffType) state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawState(byte rawState) {
|
||||||
|
// update Last Status stored time
|
||||||
|
super.setLastStatusStored();
|
||||||
|
// update item state only if it is different from previous
|
||||||
|
if (t1nRawState != rawState) {
|
||||||
|
this.setState(getOhStateOnOffFromSoulissVal(rawState));
|
||||||
|
}
|
||||||
|
t1nRawState = rawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getRawState() {
|
||||||
|
return t1nRawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getExpectedRawState(byte bCmd) {
|
||||||
|
if (bSecureSend) {
|
||||||
|
if (bCmd == SoulissProtocolConstants.SOULISS_T1N_ON_CMD) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T1N_ON_FEEDBACK;
|
||||||
|
} else if (bCmd == SoulissProtocolConstants.SOULISS_T1N_OFF_CMD) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T1N_OFF_FEEDBACK;
|
||||||
|
} else if (bCmd >= SoulissProtocolConstants.SOULISS_T1N_TIMED) {
|
||||||
|
// SLEEP
|
||||||
|
return SoulissProtocolConstants.SOULISS_T1N_ON_FEEDBACK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,183 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissProtocolConstants;
|
||||||
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
import org.openhab.core.library.types.PercentType;
|
||||||
|
import org.openhab.core.library.types.UpDownType;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.PrimitiveType;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT19Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT19Handler extends SoulissGenericHandler {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(SoulissT19Handler.class);
|
||||||
|
byte t1nRawStateByte0 = 0xF;
|
||||||
|
byte t1nRawStateBrigthnessByte1 = 0x00;
|
||||||
|
|
||||||
|
byte xSleepTime = 0;
|
||||||
|
|
||||||
|
public SoulissT19Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
if (command instanceof RefreshType) {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SoulissBindingConstants.ONOFF_CHANNEL:
|
||||||
|
OnOffType valOnOff = getOhStateOnOffFromSoulissVal(t1nRawStateByte0);
|
||||||
|
if (valOnOff != null) {
|
||||||
|
updateState(channelUID, valOnOff);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.DIMMER_BRIGHTNESS_CHANNEL:
|
||||||
|
updateState(SoulissBindingConstants.DIMMER_BRIGHTNESS_CHANNEL,
|
||||||
|
PercentType.valueOf(String.valueOf((t1nRawStateBrigthnessByte1 / 255) * 100)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SoulissBindingConstants.ONOFF_CHANNEL:
|
||||||
|
if (command.equals(OnOffType.ON)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_ON_CMD);
|
||||||
|
|
||||||
|
} else if (command.equals(OnOffType.OFF)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_OFF_CMD);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SoulissBindingConstants.DIMMER_BRIGHTNESS_CHANNEL:
|
||||||
|
if (command instanceof PercentType) {
|
||||||
|
updateState(SoulissBindingConstants.DIMMER_BRIGHTNESS_CHANNEL, (PercentType) command);
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_SET,
|
||||||
|
(byte) (((PercentType) command).shortValue() * 255.00 / 100.00));
|
||||||
|
} else if (command.equals(OnOffType.ON)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_ON_CMD);
|
||||||
|
|
||||||
|
} else if (command.equals(OnOffType.OFF)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_OFF_CMD);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SoulissBindingConstants.ROLLER_BRIGHTNESS_CHANNEL:
|
||||||
|
if (command.equals(UpDownType.UP)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_BRIGHT_UP);
|
||||||
|
} else if (command.equals(UpDownType.DOWN)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T1N_BRIGHT_DOWN);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.SLEEP_CHANNEL:
|
||||||
|
if (command instanceof OnOffType) {
|
||||||
|
commandSEND((byte) (SoulissProtocolConstants.SOULISS_T1N_TIMED + xSleepTime));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
|
||||||
|
var configurationMap = getThing().getConfiguration();
|
||||||
|
if (configurationMap.get(SoulissBindingConstants.SLEEP_CHANNEL) != null) {
|
||||||
|
xSleepTime = ((BigDecimal) configurationMap.get(SoulissBindingConstants.SLEEP_CHANNEL)).byteValue();
|
||||||
|
}
|
||||||
|
if (configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND) != null) {
|
||||||
|
bSecureSend = ((Boolean) configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND)).booleanValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(@Nullable PrimitiveType state) {
|
||||||
|
super.setLastStatusStored();
|
||||||
|
if (state != null) {
|
||||||
|
updateState(SoulissBindingConstants.SLEEP_CHANNEL, OnOffType.OFF);
|
||||||
|
logger.debug("T19, setting state to {}", state.toFullString());
|
||||||
|
this.updateState(SoulissBindingConstants.ONOFF_CHANNEL, (OnOffType) state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRawStateDimmerValue(byte dimmerValue) {
|
||||||
|
try {
|
||||||
|
if (dimmerValue != t1nRawStateByte0 && dimmerValue >= 0) {
|
||||||
|
logger.debug("T19, setting dimmer to {}", dimmerValue);
|
||||||
|
updateState(SoulissBindingConstants.DIMMER_BRIGHTNESS_CHANNEL,
|
||||||
|
PercentType.valueOf(String.valueOf(Math.round(((double) dimmerValue / 255) * 100))));
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.warn("UUID: {}, had an update dimmer state error:{}", this.getThing().getUID().getAsString(),
|
||||||
|
ex.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawState(byte rawState) {
|
||||||
|
// update Last Status stored time
|
||||||
|
super.setLastStatusStored();
|
||||||
|
// update item state only if it is different from previous
|
||||||
|
if (t1nRawStateByte0 != rawState) {
|
||||||
|
this.setState(getOhStateOnOffFromSoulissVal(rawState));
|
||||||
|
}
|
||||||
|
t1nRawStateByte0 = rawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getRawState() {
|
||||||
|
return t1nRawStateByte0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getRawStateDimmerValue() {
|
||||||
|
return t1nRawStateBrigthnessByte1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getExpectedRawState(byte bCmd) {
|
||||||
|
if (bSecureSend) {
|
||||||
|
if (bCmd == SoulissProtocolConstants.SOULISS_T1N_ON_CMD) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T1N_ON_COIL;
|
||||||
|
} else if (bCmd == SoulissProtocolConstants.SOULISS_T1N_OFF_CMD) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T1N_OFF_COIL;
|
||||||
|
} else if (bCmd >= SoulissProtocolConstants.SOULISS_T1N_TIMED) {
|
||||||
|
// SLEEP
|
||||||
|
return SoulissProtocolConstants.SOULISS_T1N_ON_COIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.core.library.types.OpenClosedType;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT1AHandler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Luca Remigio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT1AHandler extends SoulissGenericHandler {
|
||||||
|
byte t1nRawState = 0xF;
|
||||||
|
|
||||||
|
public SoulissT1AHandler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
throw new UnsupportedOperationException("Unsupported operation. Read Only");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OpenClosedType getTypeFromBool(boolean value) {
|
||||||
|
if (!value) {
|
||||||
|
return OpenClosedType.CLOSED;
|
||||||
|
}
|
||||||
|
return OpenClosedType.OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean getBitState(int value, int bit) {
|
||||||
|
return ((value & (1L << bit)) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawState(byte rawState) {
|
||||||
|
// update Last Status stored time
|
||||||
|
super.setLastStatusStored();
|
||||||
|
// update item state only if it is different from previous
|
||||||
|
if (t1nRawState != rawState) {
|
||||||
|
this.updateState(SoulissBindingConstants.T1A_1_CHANNEL, getTypeFromBool(getBitState(rawState, 0)));
|
||||||
|
this.updateState(SoulissBindingConstants.T1A_2_CHANNEL, getTypeFromBool(getBitState(rawState, 1)));
|
||||||
|
this.updateState(SoulissBindingConstants.T1A_3_CHANNEL, getTypeFromBool(getBitState(rawState, 2)));
|
||||||
|
this.updateState(SoulissBindingConstants.T1A_4_CHANNEL, getTypeFromBool(getBitState(rawState, 3)));
|
||||||
|
this.updateState(SoulissBindingConstants.T1A_5_CHANNEL, getTypeFromBool(getBitState(rawState, 4)));
|
||||||
|
this.updateState(SoulissBindingConstants.T1A_6_CHANNEL, getTypeFromBool(getBitState(rawState, 5)));
|
||||||
|
this.updateState(SoulissBindingConstants.T1A_7_CHANNEL, getTypeFromBool(getBitState(rawState, 6)));
|
||||||
|
this.updateState(SoulissBindingConstants.T1A_8_CHANNEL, getTypeFromBool(getBitState(rawState, 7)));
|
||||||
|
}
|
||||||
|
t1nRawState = rawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getRawState() {
|
||||||
|
return t1nRawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getExpectedRawState(byte bCommand) {
|
||||||
|
// Secure Send is disabled
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,202 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissProtocolConstants;
|
||||||
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
import org.openhab.core.library.types.PercentType;
|
||||||
|
import org.openhab.core.library.types.StopMoveType;
|
||||||
|
import org.openhab.core.library.types.StringType;
|
||||||
|
import org.openhab.core.library.types.UpDownType;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.PrimitiveType;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT22Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT22Handler extends SoulissGenericHandler {
|
||||||
|
byte t2nRawState = 0xF;
|
||||||
|
|
||||||
|
public SoulissT22Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
|
||||||
|
var configurationMap = getThing().getConfiguration();
|
||||||
|
if (configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND) != null) {
|
||||||
|
bSecureSend = ((Boolean) configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND)).booleanValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
if (command instanceof RefreshType) {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SoulissBindingConstants.ROLLERSHUTTER_CHANNEL:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
case SoulissBindingConstants.ROLLERSHUTTER_CHANNEL:
|
||||||
|
if (command.equals(UpDownType.UP)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T2N_OPEN_CMD);
|
||||||
|
} else if (command.equals(UpDownType.DOWN)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T2N_CLOSE_CMD);
|
||||||
|
} else if (command.equals(StopMoveType.STOP)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T2N_STOP_CMD);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.ONOFF_CHANNEL:
|
||||||
|
if (command.equals(OnOffType.ON)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T2N_OPEN_CMD_LOCAL);
|
||||||
|
} else if (command.equals(OnOffType.OFF)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T2N_CLOSE_CMD_LOCAL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(PrimitiveType state) {
|
||||||
|
if (state instanceof PercentType) {
|
||||||
|
this.updateState(SoulissBindingConstants.ROLLERSHUTTER_CHANNEL, (PercentType) state);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStateMessage(String rollershutterMessage) {
|
||||||
|
this.updateState(SoulissBindingConstants.ROLLERSHUTTER_STATE_CHANNEL_CHANNEL,
|
||||||
|
StringType.valueOf(rollershutterMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawState(byte rawState) {
|
||||||
|
// update Last Status stored time
|
||||||
|
super.setLastStatusStored();
|
||||||
|
// update item state only if it is different from previous
|
||||||
|
if (t2nRawState != rawState) {
|
||||||
|
var val = getOhStateT22FromSoulissVal(rawState);
|
||||||
|
this.setState(val);
|
||||||
|
|
||||||
|
if (rawState == SoulissProtocolConstants.SOULISS_T2N_OPEN_CMD) {
|
||||||
|
this.setStateMessage(SoulissBindingConstants.ROLLERSHUTTER_MESSAGE_OPENING_CHANNEL);
|
||||||
|
} else if (rawState == SoulissProtocolConstants.SOULISS_T2N_CLOSE_CMD) {
|
||||||
|
this.setStateMessage(SoulissBindingConstants.ROLLERSHUTTER_MESSAGE_CLOSING_CHANNEL);
|
||||||
|
}
|
||||||
|
switch (rawState) {
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_COIL_STOP:
|
||||||
|
this.setStateMessage(SoulissBindingConstants.ROLLERSHUTTER_MESSAGE_STOP_CHANNEL);
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_COIL_OFF:
|
||||||
|
this.setStateMessage(SoulissBindingConstants.ROLLERSHUTTER_MESSAGE_OPENING_CHANNEL);
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_LIMSWITCH_CLOSE:
|
||||||
|
this.setStateMessage(SoulissBindingConstants.ROLLERSHUTTER_MESSAGE_LIMITSWITCH_CLOSE_CHANNEL);
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_LIMSWITCH_OPEN:
|
||||||
|
this.setStateMessage(SoulissBindingConstants.ROLLERSHUTTER_MESSAGE_LIMITSWITCH_OPEN_CHANNEL);
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_NOLIMSWITCH:
|
||||||
|
this.setStateMessage(SoulissBindingConstants.ROLLERSHUTTER_MESSAGE_LIMITSWITCH_OPEN_CHANNEL);
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_TIMER_OFF:
|
||||||
|
this.setStateMessage(SoulissBindingConstants.ROLLERSHUTTER_MESSAGE_TIMER_OFF);
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_STATE_OPEN:
|
||||||
|
this.setStateMessage(SoulissBindingConstants.ROLLERSHUTTER_MESSAGE_STATE_OPEN_CHANNEL);
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_STATE_CLOSE:
|
||||||
|
this.setStateMessage(SoulissBindingConstants.ROLLERSHUTTER_MESSAGE_STATE_CLOSE_CHANNEL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
t2nRawState = rawState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PercentType getOhStateT22FromSoulissVal(short sVal) {
|
||||||
|
var iState = 0;
|
||||||
|
switch (sVal) {
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_COIL_OPEN:
|
||||||
|
iState = 0;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_COIL_CLOSE:
|
||||||
|
iState = 100;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_COIL_STOP:
|
||||||
|
iState = 50;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_LIMSWITCH_CLOSE:
|
||||||
|
iState = 100;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_LIMSWITCH_OPEN:
|
||||||
|
iState = 0;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_NOLIMSWITCH:
|
||||||
|
iState = 50;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_TIMER_OFF:
|
||||||
|
iState = 50;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_STATE_OPEN:
|
||||||
|
iState = 0;
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T2N_STATE_CLOSE:
|
||||||
|
iState = 100;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return PercentType.valueOf(String.valueOf(iState));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getRawState() {
|
||||||
|
return t2nRawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getExpectedRawState(byte bCmd) {
|
||||||
|
if (bSecureSend) {
|
||||||
|
if (bCmd == SoulissProtocolConstants.SOULISS_T2N_OPEN_CMD) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T2N_COIL_OPEN;
|
||||||
|
} else if (bCmd == SoulissProtocolConstants.SOULISS_T2N_CLOSE_CMD) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T2N_COIL_CLOSE;
|
||||||
|
} else if (bCmd >= SoulissProtocolConstants.SOULISS_T2N_STOP_CMD) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T2N_COIL_STOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,320 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import javax.measure.quantity.Temperature;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissProtocolConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.protocol.HalfFloatUtils;
|
||||||
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
import org.openhab.core.library.types.QuantityType;
|
||||||
|
import org.openhab.core.library.types.StringType;
|
||||||
|
import org.openhab.core.library.unit.SIUnits;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.PrimitiveType;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT31Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Luca Remigio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT31Handler extends SoulissGenericHandler {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(SoulissT31Handler.class);
|
||||||
|
|
||||||
|
QuantityType<Temperature> setMeasuredValue = new QuantityType<>("0");
|
||||||
|
QuantityType<Temperature> setPointValue = new QuantityType<>("0");
|
||||||
|
StringType fanStateValue = StringType.EMPTY;
|
||||||
|
StringType powerState = StringType.EMPTY;
|
||||||
|
StringType fireState = StringType.EMPTY;
|
||||||
|
|
||||||
|
StringType lastModeState = StringType.EMPTY;
|
||||||
|
StringType modeStateValue = StringType.EMPTY;
|
||||||
|
|
||||||
|
public SoulissT31Handler(Thing pThing) {
|
||||||
|
super(pThing);
|
||||||
|
thing = pThing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// called on every status change or change request
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
if (!(command instanceof RefreshType)) {
|
||||||
|
switch (channelUID.getId()) {
|
||||||
|
// FAN
|
||||||
|
case SoulissBindingConstants.T31_SYSTEM_CHANNEL:
|
||||||
|
if (command.equals(OnOffType.OFF)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T3N_SHUTDOWN);
|
||||||
|
} else {
|
||||||
|
if (modeStateValue.toString()
|
||||||
|
.equals(SoulissBindingConstants.T31_HEATINGMODE_MESSAGE_MODE_CHANNEL)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T3N_HEATING);
|
||||||
|
} else {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T3N_COOLING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T31_MODE_CHANNEL:
|
||||||
|
if (command.toString().equals(SoulissBindingConstants.T31_HEATINGMODE_MESSAGE_MODE_CHANNEL)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T3N_HEATING);
|
||||||
|
} else {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T3N_COOLING);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T31_BUTTON_CHANNEL:
|
||||||
|
if (command.equals(OnOffType.ON)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T3N_AS_MEASURED);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T31_FAN_CHANNEL:
|
||||||
|
switch (command.toString()) {
|
||||||
|
case SoulissBindingConstants.T31_FANHIGH_MESSAGE_FAN_CHANNEL:
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_MANUAL);
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_HIGH);
|
||||||
|
fanStateValue = StringType.valueOf(SoulissBindingConstants.T31_FANHIGH_MESSAGE_FAN_CHANNEL);
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T31_FANMEDIUM_MESSAGE_FAN_CHANNEL:
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_MANUAL);
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_MED);
|
||||||
|
fanStateValue = StringType
|
||||||
|
.valueOf(SoulissBindingConstants.T31_FANMEDIUM_MESSAGE_FAN_CHANNEL);
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T31_FANLOW_MESSAGE_FAN_CHANNEL:
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_MANUAL);
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_LOW);
|
||||||
|
fanStateValue = StringType.valueOf(SoulissBindingConstants.T31_FANLOW_MESSAGE_FAN_CHANNEL);
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T31_FANAUTO_MESSAGE_FAN_CHANNEL:
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_AUTO);
|
||||||
|
fanStateValue = StringType.valueOf(SoulissBindingConstants.T31_FANAUTO_MESSAGE_FAN_CHANNEL);
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T31_FANOFF_MESSAGE_FAN_CHANNEL:
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T3N_FAN_OFF);
|
||||||
|
fanStateValue = StringType.valueOf(SoulissBindingConstants.T31_FANOFF_MESSAGE_FAN_CHANNEL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.debug("Fan Channel handle not recognized, skipping..");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T31_SETPOINT_CHANNEL:
|
||||||
|
if (command instanceof QuantityType<?>) {
|
||||||
|
int uu = HalfFloatUtils.fromFloat(((QuantityType<?>) command).floatValue());
|
||||||
|
byte b2 = (byte) (uu >> 8);
|
||||||
|
byte b1 = (byte) uu;
|
||||||
|
// setpoint command
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T31_USE_OF_SLOT_SETPOINT_COMMAND, b1, b2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
logger.debug("state not recognized! skipping..");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
|
||||||
|
var configurationMap = getThing().getConfiguration();
|
||||||
|
if (configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND) != null) {
|
||||||
|
bSecureSend = ((Boolean) configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND)).booleanValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(PrimitiveType state) {
|
||||||
|
this.updateState(SoulissBindingConstants.T31_BUTTON_CHANNEL, OnOffType.OFF);
|
||||||
|
|
||||||
|
super.setLastStatusStored();
|
||||||
|
if (state instanceof StringType) {
|
||||||
|
switch (state.toString()) {
|
||||||
|
case SoulissBindingConstants.T31_FANLOW_MESSAGE_FAN_CHANNEL:
|
||||||
|
case SoulissBindingConstants.T31_FANMEDIUM_MESSAGE_FAN_CHANNEL:
|
||||||
|
case SoulissBindingConstants.T31_FANHIGH_MESSAGE_FAN_CHANNEL:
|
||||||
|
case SoulissBindingConstants.T31_FANAUTO_MESSAGE_FAN_CHANNEL:
|
||||||
|
case SoulissBindingConstants.T31_FANOFF_MESSAGE_FAN_CHANNEL:
|
||||||
|
if (!fanStateValue.equals(state)) {
|
||||||
|
this.updateState(SoulissBindingConstants.T31_FAN_CHANNEL, (StringType) state);
|
||||||
|
fanStateValue = (StringType) state;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SoulissBindingConstants.T31_HEATINGMODE_MESSAGE_MODE_CHANNEL:
|
||||||
|
case SoulissBindingConstants.T31_COOLINGMODE_MESSAGE_MODE_CHANNEL:
|
||||||
|
if (!modeStateValue.equals(state)) {
|
||||||
|
this.updateState(SoulissBindingConstants.T31_MODE_CHANNEL, (StringType) state);
|
||||||
|
modeStateValue = (StringType) state;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SoulissBindingConstants.T31_OFF_MESSAGE_SYSTEM_CHANNEL:
|
||||||
|
if (!powerState.equals(state)) {
|
||||||
|
this.updateState(SoulissBindingConstants.T31_SYSTEM_CHANNEL, OnOffType.OFF);
|
||||||
|
powerState = (StringType) state;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T31_ON_MESSAGE_SYSTEM_CHANNEL:
|
||||||
|
if (!powerState.equals(state)) {
|
||||||
|
this.updateState(SoulissBindingConstants.T31_SYSTEM_CHANNEL, OnOffType.ON);
|
||||||
|
powerState = (StringType) state;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SoulissBindingConstants.T31_ON_MESSAGE_FIRE_CHANNEL:
|
||||||
|
if (!fireState.equals(state)) {
|
||||||
|
this.updateState(SoulissBindingConstants.T31_FIRE_CHANNEL, OnOffType.ON);
|
||||||
|
powerState = (StringType) state;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T31_OFF_MESSAGE_FIRE_CHANNEL:
|
||||||
|
if (!fireState.equals(state)) {
|
||||||
|
this.updateState(SoulissBindingConstants.T31_FIRE_CHANNEL, OnOffType.OFF);
|
||||||
|
powerState = (StringType) state;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMeasuredValue(QuantityType<Temperature> valueOf) {
|
||||||
|
if ((valueOf instanceof QuantityType<?>) && (!setMeasuredValue.equals(valueOf))) {
|
||||||
|
this.updateState(SoulissBindingConstants.T31_VALUE_CHANNEL, valueOf);
|
||||||
|
setMeasuredValue = valueOf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSetpointValue(QuantityType<Temperature> valueOf) {
|
||||||
|
if ((valueOf instanceof QuantityType<?>) && (!setPointValue.equals(valueOf))) {
|
||||||
|
this.updateState(SoulissBindingConstants.T31_SETPOINT_CHANNEL, valueOf);
|
||||||
|
setPointValue = valueOf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRawStateValues(byte rawStateByte0, float valTemp, float valSetPoint) {
|
||||||
|
var sMessage = "";
|
||||||
|
switch (getBitState(rawStateByte0, 0)) {
|
||||||
|
case 0:
|
||||||
|
sMessage = SoulissBindingConstants.T31_OFF_MESSAGE_SYSTEM_CHANNEL;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
sMessage = SoulissBindingConstants.T31_ON_MESSAGE_SYSTEM_CHANNEL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.debug("System Channel on/off not recognized, skipping");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.setState(StringType.valueOf(sMessage));
|
||||||
|
|
||||||
|
switch (getBitState(rawStateByte0, 7)) {
|
||||||
|
case 0:
|
||||||
|
sMessage = SoulissBindingConstants.T31_HEATINGMODE_MESSAGE_MODE_CHANNEL;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
sMessage = SoulissBindingConstants.T31_COOLINGMODE_MESSAGE_MODE_CHANNEL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.debug("Mode not recognized, skipping");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.setState(StringType.valueOf(sMessage));
|
||||||
|
|
||||||
|
// button indicating whether the system is running or not
|
||||||
|
switch (getBitState(rawStateByte0, 1) + getBitState(rawStateByte0, 2)) {
|
||||||
|
case 0:
|
||||||
|
sMessage = SoulissBindingConstants.T31_OFF_MESSAGE_FIRE_CHANNEL;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
sMessage = SoulissBindingConstants.T31_ON_MESSAGE_FIRE_CHANNEL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.debug("Fire not recognized, skipping");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.setState(StringType.valueOf(sMessage));
|
||||||
|
|
||||||
|
// FAN SPEED
|
||||||
|
switch (getBitState(rawStateByte0, 3) + getBitState(rawStateByte0, 4) + getBitState(rawStateByte0, 5)) {
|
||||||
|
case 0:
|
||||||
|
sMessage = SoulissBindingConstants.T31_FANOFF_MESSAGE_FAN_CHANNEL;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
sMessage = SoulissBindingConstants.T31_FANLOW_MESSAGE_FAN_CHANNEL;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
sMessage = SoulissBindingConstants.T31_FANMEDIUM_MESSAGE_FAN_CHANNEL;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
sMessage = SoulissBindingConstants.T31_FANHIGH_MESSAGE_FAN_CHANNEL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.debug("Fan speed not recognized, skipping");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState(StringType.valueOf(sMessage));
|
||||||
|
|
||||||
|
// SLOT 1-2: Temperature Value
|
||||||
|
if (!Float.isNaN(valTemp)) {
|
||||||
|
this.setMeasuredValue(QuantityType.valueOf(valTemp, SIUnits.CELSIUS));
|
||||||
|
}
|
||||||
|
|
||||||
|
// SLOT 3-4: Setpoint Value
|
||||||
|
if (!Float.isNaN(valSetPoint)) {
|
||||||
|
this.setSetpointValue(QuantityType.valueOf(valSetPoint, SIUnits.CELSIUS));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getRawState() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getExpectedRawState(byte bCommand) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getBitState(byte vRaw, int iBit) {
|
||||||
|
final var maskBit1 = 0x1;
|
||||||
|
|
||||||
|
if (((vRaw >>> iBit) & maskBit1) == 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawState(byte rawState) {
|
||||||
|
throw new UnsupportedOperationException("Not Implemented, yet.");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,142 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissProtocolConstants;
|
||||||
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
import org.openhab.core.library.types.StringType;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.PrimitiveType;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT41Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Luca Remigio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT41Handler extends SoulissGenericHandler {
|
||||||
|
|
||||||
|
byte t4nRawState = 0xF;
|
||||||
|
|
||||||
|
public SoulissT41Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
// called on every status change or change request
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
if (!(command instanceof RefreshType)) {
|
||||||
|
if (channelUID.getId().equals(SoulissBindingConstants.T4N_ONOFFALARM_CHANNEL)) {
|
||||||
|
if (command instanceof OnOffType) {
|
||||||
|
if (command.equals(OnOffType.OFF)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T4N_NOT_ARMED);
|
||||||
|
} else if (command.equals(OnOffType.ON)) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T4N_ARMED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ((channelUID.getAsString().split(":")[3].equals(SoulissBindingConstants.T4N_REARMALARM_CHANNEL))
|
||||||
|
&& (command instanceof OnOffType) && (command.equals(OnOffType.OFF))) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T4N_REARM);
|
||||||
|
this.setState(StringType.valueOf(SoulissBindingConstants.T4N_REARMOFF_MESSAGE_CHANNEL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
|
||||||
|
var configurationMap = getThing().getConfiguration();
|
||||||
|
if (configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND) != null) {
|
||||||
|
bSecureSend = ((Boolean) configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND)).booleanValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(PrimitiveType state) {
|
||||||
|
if (state instanceof OnOffType) {
|
||||||
|
this.updateState(SoulissBindingConstants.T4N_ONOFFALARM_CHANNEL, (OnOffType) state);
|
||||||
|
} else if (state instanceof StringType) {
|
||||||
|
switch (String.valueOf(state)) {
|
||||||
|
case SoulissBindingConstants.T4N_ALARMON_MESSAGE_CHANNEL:
|
||||||
|
this.updateState(SoulissBindingConstants.T4N_STATUSALARM_CHANNEL, OnOffType.ON);
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T4N_ALARMOFF_MESSAGE_CHANNEL:
|
||||||
|
this.updateState(SoulissBindingConstants.T4N_STATUSALARM_CHANNEL, OnOffType.OFF);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// // Reset the rearm button. This is because if pressed, it does not turn off by itself
|
||||||
|
updateState(SoulissBindingConstants.T4N_REARMALARM_CHANNEL, OnOffType.OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawState(byte rawState) {
|
||||||
|
// update Last Status stored time
|
||||||
|
super.setLastStatusStored();
|
||||||
|
// update item state only if it is different from previous
|
||||||
|
if (t4nRawState != rawState) {
|
||||||
|
switch (rawState) {
|
||||||
|
case SoulissProtocolConstants.SOULISS_T4N_NO_ANTITHEFT:
|
||||||
|
this.setState(OnOffType.OFF);
|
||||||
|
this.setState(StringType.valueOf(SoulissBindingConstants.T4N_ALARMOFF_MESSAGE_CHANNEL));
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T4N_ANTITHEFT:
|
||||||
|
this.setState(OnOffType.ON);
|
||||||
|
this.setState(StringType.valueOf(SoulissBindingConstants.T4N_ALARMOFF_MESSAGE_CHANNEL));
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T4N_IN_ALARM:
|
||||||
|
this.setState(StringType.valueOf(SoulissBindingConstants.T4N_ALARMON_MESSAGE_CHANNEL));
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T4N_ARMED:
|
||||||
|
this.setState(StringType.valueOf(SoulissBindingConstants.T4N_ARMED_MESSAGE_CHANNEL));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t4nRawState = rawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getRawState() {
|
||||||
|
return t4nRawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getExpectedRawState(byte bCmd) {
|
||||||
|
if (bSecureSend) {
|
||||||
|
if (bCmd == SoulissProtocolConstants.SOULISS_T4N_ARMED) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T4N_ANTITHEFT;
|
||||||
|
} else if (bCmd == SoulissProtocolConstants.SOULISS_T4N_NOT_ARMED) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T4N_NO_ANTITHEFT;
|
||||||
|
} else if (bCmd >= SoulissProtocolConstants.SOULISS_T4N_REARM) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T4N_ANTITHEFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissProtocolConstants;
|
||||||
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
import org.openhab.core.library.types.StringType;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.PrimitiveType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT42Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT42Handler extends SoulissGenericHandler {
|
||||||
|
byte t4nRawState = 0xF;
|
||||||
|
|
||||||
|
public SoulissT42Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
// called on every status change or change request
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
if ((channelUID.getAsString().split(":")[3].equals(SoulissBindingConstants.T4N_REARMALARM_CHANNEL))
|
||||||
|
&& (command instanceof OnOffType) && (command.equals(OnOffType.ON))) {
|
||||||
|
commandSEND(SoulissProtocolConstants.SOULISS_T4N_REARM);
|
||||||
|
this.setState(StringType.valueOf(SoulissBindingConstants.T4N_REARMOFF_MESSAGE_CHANNEL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
|
||||||
|
var configurationMap = getThing().getConfiguration();
|
||||||
|
if (configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND) != null) {
|
||||||
|
bSecureSend = ((Boolean) configurationMap.get(SoulissBindingConstants.CONFIG_SECURE_SEND)).booleanValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(PrimitiveType state) {
|
||||||
|
if (state instanceof StringType) {
|
||||||
|
switch (String.valueOf(state)) {
|
||||||
|
case SoulissBindingConstants.T4N_ALARMON_MESSAGE_CHANNEL:
|
||||||
|
this.updateState(SoulissBindingConstants.T4N_STATUSALARM_CHANNEL, OnOffType.ON);
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T4N_ALARMOFF_MESSAGE_CHANNEL:
|
||||||
|
this.updateState(SoulissBindingConstants.T4N_STATUSALARM_CHANNEL, OnOffType.OFF);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Reset the rearm button. This is because if pressed, it does not turn off by itself
|
||||||
|
updateState(SoulissBindingConstants.T4N_REARMALARM_CHANNEL, OnOffType.OFF);
|
||||||
|
|
||||||
|
super.setLastStatusStored();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawState(byte rawState) {
|
||||||
|
// update Last Status stored time
|
||||||
|
super.setLastStatusStored();
|
||||||
|
// update item state only if it is different from previous
|
||||||
|
if (t4nRawState != rawState) {
|
||||||
|
OnOffType onOffVal = getOhStateOnOffFromSoulissVal(rawState);
|
||||||
|
if (onOffVal != null) {
|
||||||
|
this.setState(onOffVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t4nRawState = rawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getRawState() {
|
||||||
|
return t4nRawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getExpectedRawState(byte bCmd) {
|
||||||
|
if ((bSecureSend) && (bCmd == SoulissProtocolConstants.SOULISS_T4N_REARM)) {
|
||||||
|
return SoulissProtocolConstants.SOULISS_T4N_ANTITHEFT;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT51Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT51Handler extends SoulissT5nHandler {
|
||||||
|
|
||||||
|
public SoulissT51Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT52Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT52Handler extends SoulissT5nHandler {
|
||||||
|
|
||||||
|
public SoulissT52Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT53Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT53Handler extends SoulissT5nHandler {
|
||||||
|
|
||||||
|
public SoulissT53Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT54Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT54Handler extends SoulissT5nHandler {
|
||||||
|
|
||||||
|
public SoulissT54Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT55Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT55Handler extends SoulissT5nHandler {
|
||||||
|
|
||||||
|
public SoulissT55Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT56Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT56Handler extends SoulissT5nHandler {
|
||||||
|
|
||||||
|
public SoulissT56Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT57Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT57Handler extends SoulissT5nHandler {
|
||||||
|
|
||||||
|
public SoulissT57Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT58Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT58Handler extends SoulissT5nHandler {
|
||||||
|
|
||||||
|
public SoulissT58Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.core.library.types.QuantityType;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT5nHandler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT5nHandler extends SoulissGenericHandler {
|
||||||
|
|
||||||
|
private float fVal = 0xF;
|
||||||
|
|
||||||
|
public SoulissT5nHandler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(QuantityType<?> state) {
|
||||||
|
this.updateState(SoulissBindingConstants.T5N_VALUE_CHANNEL, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawState(byte rawState) {
|
||||||
|
throw new UnsupportedOperationException("Not Implemented, yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFloatValue(float valueOf) {
|
||||||
|
super.setLastStatusStored();
|
||||||
|
if (fVal != valueOf) {
|
||||||
|
this.setState(QuantityType.valueOf(Float.toString(valueOf)));
|
||||||
|
fVal = valueOf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getRawState() {
|
||||||
|
throw new UnsupportedOperationException("Not Implemented, yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getFloatState() {
|
||||||
|
return fVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getExpectedRawState(byte bCommand) {
|
||||||
|
// Secure Send is disabled
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
throw new UnsupportedOperationException("Unsupported operation. Read Only");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT61Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Luca Remigio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT61Handler extends SoulissT6nHandler {
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
public SoulissT61Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT62Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Luca Remigio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT62Handler extends SoulissT6nHandler {
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
public SoulissT62Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT63Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Luca Remigio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT63Handler extends SoulissT6nHandler {
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
public SoulissT63Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT64Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Luca Remigio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT64Handler extends SoulissT6nHandler {
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
public SoulissT64Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT65Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Luca Remigio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT65Handler extends SoulissT6nHandler {
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
public SoulissT65Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT66Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Luca Remigio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT66Handler extends SoulissT6nHandler {
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
public SoulissT66Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT67Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Luca Remigio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT67Handler extends SoulissT6nHandler {
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
public SoulissT67Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT68Handler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Luca Remigio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT68Handler extends SoulissT6nHandler {
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
public SoulissT68Handler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.protocol.HalfFloatUtils;
|
||||||
|
import org.openhab.core.library.types.DecimalType;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.PrimitiveType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissT6nHandler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Luca Remigio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissT6nHandler extends SoulissGenericHandler {
|
||||||
|
|
||||||
|
private float fSetPointValue = 0xFFFF;
|
||||||
|
|
||||||
|
public SoulissT6nHandler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
if (command instanceof DecimalType) {
|
||||||
|
int uu = HalfFloatUtils.fromFloat(((DecimalType) command).floatValue());
|
||||||
|
byte b2 = (byte) (uu >> 8);
|
||||||
|
byte b1 = (byte) uu;
|
||||||
|
// setpoint command
|
||||||
|
commandSEND(b1, b2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
super.initialize();
|
||||||
|
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(PrimitiveType state) {
|
||||||
|
this.updateState(SoulissBindingConstants.T6N_VALUE_CHANNEL, (DecimalType) state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawState(byte rawState) {
|
||||||
|
throw new UnsupportedOperationException("Not Implemented, yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFloatValue(float valueOf) {
|
||||||
|
super.setLastStatusStored();
|
||||||
|
if (fSetPointValue != valueOf) {
|
||||||
|
this.setState(DecimalType.valueOf(Float.toString(valueOf)));
|
||||||
|
fSetPointValue = valueOf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getRawState() {
|
||||||
|
throw new UnsupportedOperationException("Not Implemented, yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getFloatState() {
|
||||||
|
return fSetPointValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getExpectedRawState(byte bCommand) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.core.library.types.DecimalType;
|
||||||
|
import org.openhab.core.thing.ChannelUID;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.PrimitiveType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SoulissTopicsHandler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Luca Remigio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SoulissTopicsHandler extends SoulissGenericActionMessage implements TypicalCommonMethods {
|
||||||
|
|
||||||
|
private float fSetPointValue = 0xFFFF;
|
||||||
|
|
||||||
|
public SoulissTopicsHandler(Thing pThing) {
|
||||||
|
super(pThing);
|
||||||
|
thingGenActMsg = pThing;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
// status online
|
||||||
|
updateStatus(ThingStatus.ONLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(PrimitiveType state) {
|
||||||
|
this.updateState(SoulissBindingConstants.T5N_VALUE_CHANNEL, (DecimalType) state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFloatValue(float valueOf) {
|
||||||
|
this.updateState(SoulissBindingConstants.LASTSTATUSSTORED_CHANNEL, this.getLastUpdateTime());
|
||||||
|
if (fSetPointValue != valueOf) {
|
||||||
|
this.setState(DecimalType.valueOf(Float.toString(valueOf)));
|
||||||
|
fSetPointValue = valueOf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getFloatState() {
|
||||||
|
return fSetPointValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRawState(byte rawState) {
|
||||||
|
throw new UnsupportedOperationException("Not Implemented, yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getRawState() {
|
||||||
|
throw new UnsupportedOperationException("Not Implemented, yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getExpectedRawState(byte bCommand) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
=======
|
||||||
|
* Copyright (c) 2014-2019 by the respective copyright holders.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.handler;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result callback interface.
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public interface TypicalCommonMethods {
|
||||||
|
void setRawState(byte rawState);
|
||||||
|
|
||||||
|
byte getRawState();
|
||||||
|
|
||||||
|
byte getExpectedRawState(byte bCommand);
|
||||||
|
}
|
@ -0,0 +1,499 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.protocol;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.DatagramPacket;
|
||||||
|
import java.net.DatagramSocket;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.InterfaceAddress;
|
||||||
|
import java.net.NetworkInterface;
|
||||||
|
import java.net.SocketException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.nio.channels.DatagramChannel;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissUDPConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.config.GatewayConfig;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provide to construct MaCaco and UDP frame
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
* @author Alessandro Del Pex - Souliss App
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class CommonCommands {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(CommonCommands.class);
|
||||||
|
|
||||||
|
private static final String LITERAL_SEND_FRAME = "sendFORCEFrame - {}, soulissNodeIPAddressOnLAN: {}";
|
||||||
|
|
||||||
|
public final void sendFORCEFrame(GatewayConfig gwConfig, int idNode, int slot, byte shortCommand) {
|
||||||
|
sendFORCEFrame(gwConfig, idNode, slot, shortCommand, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* used for set dimmer value. It set command at first byte and dimmerVal to
|
||||||
|
* second byte
|
||||||
|
*/
|
||||||
|
public final void sendFORCEFrame(GatewayConfig gwConfig, int idNode, int slot, byte shortCommand, byte lDimmer) {
|
||||||
|
sendFORCEFrame(gwConfig, idNode, slot, shortCommand, lDimmer, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* send force frame with command and RGB value
|
||||||
|
*/
|
||||||
|
public final void sendFORCEFrame(GatewayConfig gwConfig, int idNode, int slot, byte shortCommand,
|
||||||
|
@Nullable Byte byte1, @Nullable Byte byte2, @Nullable Byte byte3) {
|
||||||
|
ArrayList<Byte> macacoFrame = new ArrayList<>();
|
||||||
|
macacoFrame.add(SoulissUDPConstants.SOULISS_UDP_FUNCTION_FORCE);
|
||||||
|
|
||||||
|
// PUTIN, STARTOFFEST, NUMBEROF
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x0);
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x0);
|
||||||
|
|
||||||
|
macacoFrame.add((byte) (idNode));// Start Offset
|
||||||
|
|
||||||
|
if (byte1 == null && byte2 == null && byte3 == null) {
|
||||||
|
// Number Of
|
||||||
|
macacoFrame.add((byte) ((byte) slot + 1));
|
||||||
|
} else if (byte2 == null && byte3 == null) {
|
||||||
|
// Number Of byte of payload= command + set byte
|
||||||
|
macacoFrame.add((byte) ((byte) slot + 2));
|
||||||
|
} else {
|
||||||
|
// Number Of byte of payload= OnOFF + Red + Green + Blu
|
||||||
|
macacoFrame.add((byte) ((byte) slot + 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i <= slot - 1; i++) {
|
||||||
|
// I set the bytes preceding the slot to be modified to zero
|
||||||
|
macacoFrame.add((byte) 00);
|
||||||
|
}
|
||||||
|
// PAYLOAD
|
||||||
|
macacoFrame.add(shortCommand);
|
||||||
|
|
||||||
|
if (byte1 != null && byte2 != null && byte3 != null) {
|
||||||
|
// PAYLOAD RED
|
||||||
|
macacoFrame.add(byte1);
|
||||||
|
// PAYLOAD GREEN
|
||||||
|
macacoFrame.add(byte2);
|
||||||
|
// PAYLOAD BLUE
|
||||||
|
macacoFrame.add(byte3);
|
||||||
|
} else if (byte1 != null) {
|
||||||
|
// PAYLOAD DIMMER
|
||||||
|
macacoFrame.add(byte1);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(LITERAL_SEND_FRAME, macacoToString(macacoFrame), gwConfig);
|
||||||
|
queueToDispatcher(macacoFrame, gwConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* T61 send frame to push the setpoint value
|
||||||
|
*/
|
||||||
|
|
||||||
|
public final void sendFORCEFrameT61SetPoint(GatewayConfig gwConfig, int idNode, int slot, Byte byte1, Byte byte2) {
|
||||||
|
ArrayList<Byte> macacoFrame = new ArrayList<>();
|
||||||
|
macacoFrame.add(SoulissUDPConstants.SOULISS_UDP_FUNCTION_FORCE);
|
||||||
|
|
||||||
|
// PUTIN, STARTOFFEST, NUMBEROF
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
// Start Offset
|
||||||
|
macacoFrame.add((byte) (idNode));
|
||||||
|
// Number Of byte of payload= command + set byte
|
||||||
|
macacoFrame.add((byte) ((byte) slot + 2));
|
||||||
|
|
||||||
|
for (var i = 0; i <= slot - 1; i++) {
|
||||||
|
// I set the bytes preceding the slot to be modified to zero
|
||||||
|
macacoFrame.add((byte) 00);
|
||||||
|
}
|
||||||
|
// PAYLOAD
|
||||||
|
// first byte Setpoint Value
|
||||||
|
macacoFrame.add(byte1);
|
||||||
|
// second byte Setpoint Value
|
||||||
|
macacoFrame.add(byte2);
|
||||||
|
|
||||||
|
logger.debug(LITERAL_SEND_FRAME, macacoToString(macacoFrame), gwConfig);
|
||||||
|
|
||||||
|
queueToDispatcher(macacoFrame, gwConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* T31 send force frame with command and setpoint float
|
||||||
|
*/
|
||||||
|
public final void sendFORCEFrameT31SetPoint(GatewayConfig gwConfig, int idNode, int slot, byte shortCommand,
|
||||||
|
Byte byte1, Byte byte2) {
|
||||||
|
ArrayList<Byte> macacoFrame = new ArrayList<>();
|
||||||
|
macacoFrame.add(SoulissUDPConstants.SOULISS_UDP_FUNCTION_FORCE);
|
||||||
|
|
||||||
|
// PUTIN, STARTOFFEST, NUMBEROF
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
|
||||||
|
// Start Offset
|
||||||
|
macacoFrame.add((byte) (idNode));
|
||||||
|
// Number Of byte of payload= command + set byte
|
||||||
|
macacoFrame.add((byte) ((byte) slot + 5));
|
||||||
|
|
||||||
|
for (var i = 0; i <= slot - 1; i++) {
|
||||||
|
// prvious byte to zero
|
||||||
|
macacoFrame.add((byte) 00);
|
||||||
|
// slot to be changed
|
||||||
|
}
|
||||||
|
// PAYLOAD
|
||||||
|
macacoFrame.add(shortCommand);
|
||||||
|
|
||||||
|
// Empty - Temperature Measured Value
|
||||||
|
macacoFrame.add((byte) 0x0);
|
||||||
|
// Empty - Temperature Measured Value
|
||||||
|
macacoFrame.add((byte) 0x0);
|
||||||
|
// Temperature Setpoint Value
|
||||||
|
macacoFrame.add(byte1);
|
||||||
|
// Temperature Setpoint Value
|
||||||
|
macacoFrame.add(byte2);
|
||||||
|
|
||||||
|
logger.debug(LITERAL_SEND_FRAME, macacoToString(macacoFrame), gwConfig);
|
||||||
|
queueToDispatcher(macacoFrame, gwConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void sendDBStructFrame(GatewayConfig gwConfig) {
|
||||||
|
ArrayList<Byte> macacoFrame = new ArrayList<>();
|
||||||
|
macacoFrame.add((byte) SoulissUDPConstants.SOULISS_UDP_FUNCTION_DBSTRUCT_REQ);
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x0);
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x0);
|
||||||
|
// Start Offset
|
||||||
|
macacoFrame.add((byte) 0x0);
|
||||||
|
// Number Of
|
||||||
|
macacoFrame.add((byte) 0x0);
|
||||||
|
|
||||||
|
logger.debug("sendDBStructFrame - {}, soulissNodeIPAddressOnLAN: {}", macacoToString(macacoFrame), gwConfig);
|
||||||
|
queueToDispatcher(macacoFrame, gwConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Queue command to Dispatcher (for securesend retransmission)
|
||||||
|
*/
|
||||||
|
private final void queueToDispatcher(ArrayList<Byte> macacoFrame, GatewayConfig gwConfig) {
|
||||||
|
ArrayList<Byte> buf = buildVNetFrame(macacoFrame, gwConfig.gatewayLanAddress, (byte) gwConfig.userIndex,
|
||||||
|
(byte) gwConfig.nodeIndex);
|
||||||
|
byte[] merd = toByteArray(buf);
|
||||||
|
|
||||||
|
InetAddress serverAddr;
|
||||||
|
try {
|
||||||
|
serverAddr = gwConfig.gatewayWanAddress.isEmpty() ? InetAddress.getByName(gwConfig.gatewayLanAddress)
|
||||||
|
: InetAddress.getByName(gwConfig.gatewayWanAddress);
|
||||||
|
var packet = new DatagramPacket(merd, merd.length, serverAddr,
|
||||||
|
SoulissUDPConstants.SOULISS_GATEWAY_DEFAULT_PORT);
|
||||||
|
SendDispatcherRunnable.put(packet, logger);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.warn("Error: {} ", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* send broadcast UDP frame - unused in this version
|
||||||
|
*/
|
||||||
|
private final void sendBroadcastNow(ArrayList<Byte> macacoFrame) {
|
||||||
|
byte iUserIndex = (byte) 120;
|
||||||
|
byte iNodeIndex = (byte) 70;
|
||||||
|
|
||||||
|
// Broadcast the message over all the network interfaces
|
||||||
|
Enumeration<@Nullable NetworkInterface> interfaces;
|
||||||
|
DatagramSocket sender = null;
|
||||||
|
try {
|
||||||
|
interfaces = NetworkInterface.getNetworkInterfaces();
|
||||||
|
|
||||||
|
while (interfaces.hasMoreElements()) {
|
||||||
|
var networkInterface = interfaces.nextElement();
|
||||||
|
if (networkInterface != null) {
|
||||||
|
if (networkInterface.isLoopback() || !networkInterface.isUp()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
|
||||||
|
var broadcast = new InetAddress[3];
|
||||||
|
broadcast[0] = InetAddress.getByName("224.0.0.1");
|
||||||
|
broadcast[1] = InetAddress.getByName("255.255.255.255");
|
||||||
|
broadcast[2] = interfaceAddress.getBroadcast();
|
||||||
|
for (InetAddress bc : broadcast) {
|
||||||
|
// Send the broadcast package!
|
||||||
|
if (bc != null) {
|
||||||
|
try {
|
||||||
|
ArrayList<Byte> buf = buildVNetFrame(macacoFrame, "255.255.255.255", iUserIndex,
|
||||||
|
iNodeIndex);
|
||||||
|
byte[] merd = toByteArray(buf);
|
||||||
|
var packet = new DatagramPacket(merd, merd.length, bc,
|
||||||
|
SoulissUDPConstants.SOULISS_GATEWAY_DEFAULT_PORT);
|
||||||
|
// Datagramsocket creation
|
||||||
|
var channel = DatagramChannel.open();
|
||||||
|
sender = channel.socket();
|
||||||
|
sender.setReuseAddress(true);
|
||||||
|
sender.setBroadcast(true);
|
||||||
|
|
||||||
|
var sa = new InetSocketAddress(230);
|
||||||
|
sender.bind(sa);
|
||||||
|
|
||||||
|
sender.send(packet);
|
||||||
|
logger.debug("Request packet sent to: {} Interface: {}", bc.getHostAddress(),
|
||||||
|
networkInterface.getDisplayName());
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.debug("IO error: {}", e.getMessage());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.debug("{}", e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
if ((sender != null) && (!sender.isClosed())) {
|
||||||
|
sender.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SocketException | UnknownHostException e) {
|
||||||
|
logger.warn("{}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build VNet Frame
|
||||||
|
*/
|
||||||
|
private final ArrayList<Byte> buildVNetFrame(ArrayList<Byte> macacoFrame2, @Nullable String gatewayLanAddress,
|
||||||
|
byte iUserIndex, byte iNodeIndex) {
|
||||||
|
if (gatewayLanAddress != null) {
|
||||||
|
ArrayList<Byte> frame = new ArrayList<>();
|
||||||
|
InetAddress ip;
|
||||||
|
try {
|
||||||
|
ip = InetAddress.getByName(gatewayLanAddress);
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
logger.warn("{}", e.getMessage());
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
byte[] dude = ip.getAddress();
|
||||||
|
|
||||||
|
// Port
|
||||||
|
frame.add((byte) 23);
|
||||||
|
// es 192.168.1.XX BOARD
|
||||||
|
frame.add((byte) (dude[3] & 0xFF));
|
||||||
|
|
||||||
|
// n broadcast : communication by Ip
|
||||||
|
// 255.255.255.255 to associate vNet 0xFFFF address.
|
||||||
|
frame.add(gatewayLanAddress.compareTo(SoulissUDPConstants.BROADCASTADDR) == 0 ? dude[2] : 0);
|
||||||
|
// NODE INDEX - source vNet address User Interface
|
||||||
|
frame.add(iNodeIndex);
|
||||||
|
// USER INDEX - source vNet address User Interface
|
||||||
|
frame.add(iUserIndex);
|
||||||
|
|
||||||
|
// adds the calculation in the head
|
||||||
|
// Length
|
||||||
|
frame.add(0, (byte) (frame.size() + macacoFrame2.size() + 1));
|
||||||
|
// Length Check 2
|
||||||
|
frame.add(0, (byte) (frame.size() + macacoFrame2.size() + 1));
|
||||||
|
|
||||||
|
frame.addAll(macacoFrame2);
|
||||||
|
return frame;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Cannot build VNet Frame . Null Souliss IP address");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds old-school byte array
|
||||||
|
*
|
||||||
|
* @param buf
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private final byte[] toByteArray(ArrayList<Byte> buf) {
|
||||||
|
var merd = new byte[buf.size()];
|
||||||
|
for (var i = 0; i < buf.size(); i++) {
|
||||||
|
merd[i] = buf.get(i);
|
||||||
|
}
|
||||||
|
return merd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build MULTICAST FORCE Frame
|
||||||
|
*/
|
||||||
|
public final void sendMULTICASTFORCEFrame(GatewayConfig gwConfig, byte typical, byte shortCommand) {
|
||||||
|
ArrayList<Byte> macacoFrame = new ArrayList<>();
|
||||||
|
macacoFrame.add(SoulissUDPConstants.SOULISS_UDP_FUNCTION_FORCE_MASSIVE);
|
||||||
|
|
||||||
|
// PUTIN, STARTOFFEST, NUMBEROF
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x0);
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x0);
|
||||||
|
// Start Offset
|
||||||
|
macacoFrame.add(typical);
|
||||||
|
// Number Of
|
||||||
|
macacoFrame.add((byte) 1);
|
||||||
|
// PAYLOAD
|
||||||
|
macacoFrame.add(shortCommand);
|
||||||
|
logger.debug("sendMULTICASTFORCEFrame - {}, soulissNodeIPAddressOnLAN: {}", macacoToString(macacoFrame),
|
||||||
|
gwConfig);
|
||||||
|
queueToDispatcher(macacoFrame, gwConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build PING Frame
|
||||||
|
*/
|
||||||
|
public final void sendPing(@Nullable GatewayConfig gwConfig) {
|
||||||
|
if (gwConfig != null) {
|
||||||
|
ArrayList<Byte> macacoFrame = new ArrayList<>();
|
||||||
|
macacoFrame.add(SoulissUDPConstants.SOULISS_UDP_FUNCTION_PING_REQ);
|
||||||
|
|
||||||
|
// PUTIN, STARTOFFEST, NUMBEROF
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
// Start Offset
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
// Number Of
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
logger.debug("sendPing - {}, IP: {} ", macacoToString(macacoFrame), gwConfig);
|
||||||
|
queueToDispatcher(macacoFrame, gwConfig);
|
||||||
|
} else {
|
||||||
|
logger.warn("Cannot send Souliss Ping - Ip null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build BROADCAST PING Frame
|
||||||
|
*/
|
||||||
|
public final void sendBroadcastGatewayDiscover() {
|
||||||
|
ArrayList<Byte> macacoFrame = new ArrayList<>();
|
||||||
|
macacoFrame.add(SoulissUDPConstants.SOULISS_UDP_FUNCTION_DISCOVER_GW_NODE_BCAST_REQ);
|
||||||
|
|
||||||
|
// PUTIN, STARTOFFEST, NUMBEROF
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x05);
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
// Start Offset
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
// Number Of
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
logger.debug("sendBroadcastPing - {} ", macacoToString(macacoFrame));
|
||||||
|
sendBroadcastNow(macacoFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build SUBSCRIPTION Frame
|
||||||
|
*/
|
||||||
|
public final void sendSUBSCRIPTIONframe(GatewayConfig gwConfig, int iNodes) {
|
||||||
|
ArrayList<Byte> macacoFrame = new ArrayList<>();
|
||||||
|
macacoFrame.add(SoulissUDPConstants.SOULISS_UDP_FUNCTION_SUBSCRIBE_REQ);
|
||||||
|
|
||||||
|
// PUTIN, STARTOFFEST, NUMBEROF
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
|
||||||
|
macacoFrame.add((byte) iNodes);
|
||||||
|
logger.debug("sendSUBSCRIPTIONframe - {}, IP: {} ", macacoToString(macacoFrame), gwConfig);
|
||||||
|
queueToDispatcher(macacoFrame, gwConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build HEALTHY REQUEST Frame
|
||||||
|
*/
|
||||||
|
public final void sendHealthyRequestFrame(GatewayConfig gwConfig, int iNodes) {
|
||||||
|
ArrayList<Byte> macacoFrame = new ArrayList<>();
|
||||||
|
macacoFrame.add(SoulissUDPConstants.SOULISS_UDP_FUNCTION_HEALTHY_REQ);
|
||||||
|
|
||||||
|
// PUTIN, STARTOFFSET, NUMBEROF
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
macacoFrame.add((byte) iNodes);
|
||||||
|
logger.debug("sendHealthyRequestFrame - {}, IP: {} ", macacoToString(macacoFrame), gwConfig);
|
||||||
|
queueToDispatcher(macacoFrame, gwConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build TYPICAL REQUEST Frame
|
||||||
|
*/
|
||||||
|
public final void sendTypicalRequestFrame(GatewayConfig gwConfig, int nodes) {
|
||||||
|
ArrayList<Byte> macacoFrame = new ArrayList<>();
|
||||||
|
macacoFrame.add(SoulissUDPConstants.SOULISS_UDP_FUNCTION_TYP_REQ);
|
||||||
|
// PUTIN, STARTOFFEST, NUMBEROF
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
// startOffset
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
// iNodes
|
||||||
|
macacoFrame.add((byte) nodes);
|
||||||
|
logger.debug("sendTypicalRequestFrame - {}, IP: {} ", macacoToString(macacoFrame), gwConfig.gatewayLanAddress);
|
||||||
|
queueToDispatcher(macacoFrame, gwConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build TYPICAL REQUEST Frame with start offset
|
||||||
|
*/
|
||||||
|
public final void sendTypicalRequestFrame(GatewayConfig gwConfig, int start, int nodes) {
|
||||||
|
ArrayList<Byte> macacoFrame = new ArrayList<>();
|
||||||
|
macacoFrame.add(SoulissUDPConstants.SOULISS_UDP_FUNCTION_TYP_REQ);
|
||||||
|
// PUTIN, STARTOFFEST, NUMBEROF
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
// PUTIN
|
||||||
|
macacoFrame.add((byte) 0x00);
|
||||||
|
// startOffset
|
||||||
|
macacoFrame.add((byte) start);
|
||||||
|
// iNodes
|
||||||
|
macacoFrame.add((byte) nodes);
|
||||||
|
logger.debug("sendTypicalRequestFrame - {}, IP: {} ", macacoToString(macacoFrame), gwConfig.gatewayLanAddress);
|
||||||
|
queueToDispatcher(macacoFrame, gwConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean flag = true;
|
||||||
|
|
||||||
|
private final String macacoToString(ArrayList<Byte> mACACOframe) {
|
||||||
|
// I copy arrays to avoid concurrent changes
|
||||||
|
ArrayList<Byte> mACACOframe2 = new ArrayList<>();
|
||||||
|
mACACOframe2.addAll(mACACOframe);
|
||||||
|
flag = false;
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.append("HEX: [");
|
||||||
|
for (byte b : mACACOframe2) {
|
||||||
|
sb.append(String.format("%02X ", b));
|
||||||
|
}
|
||||||
|
sb.append("]");
|
||||||
|
flag = true;
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,115 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.protocol;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to conver half precision float to int int are used on analogue
|
||||||
|
* typicals (2 bytes) and should be reversed because of endianess
|
||||||
|
* http://stackoverflow.com/users/237321/x4u
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public final class HalfFloatUtils {
|
||||||
|
|
||||||
|
public static boolean isNaN(float x) {
|
||||||
|
return x != x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignores the higher 16 bits
|
||||||
|
public static float toFloat(int hbits) {
|
||||||
|
// 10 bits mantissa
|
||||||
|
int mant = hbits & 0x03ff;
|
||||||
|
// 5 bits exponent
|
||||||
|
int exp = hbits & 0x7c00;
|
||||||
|
if (exp == 0x7c00) {
|
||||||
|
// -> NaN/Inf
|
||||||
|
exp = 0x3fc00;
|
||||||
|
// normalized value
|
||||||
|
} else if (exp != 0) {
|
||||||
|
// exp - 15 + 127
|
||||||
|
exp += 0x1c000;
|
||||||
|
if (mant == 0 && exp > 0x1c400) {
|
||||||
|
return Float.intBitsToFloat((hbits & 0x8000) << 16 | exp << 13 | 0x3ff);
|
||||||
|
}
|
||||||
|
// && exp==0 -> subnormal
|
||||||
|
} else if (mant != 0) {
|
||||||
|
// make it normal
|
||||||
|
exp = 0x1c400;
|
||||||
|
do {
|
||||||
|
// mantissa * 2
|
||||||
|
mant <<= 1;
|
||||||
|
// decrease exp by 1
|
||||||
|
exp -= 0x400;
|
||||||
|
// while not normal
|
||||||
|
} while ((mant & 0x400) == 0);
|
||||||
|
// discard subnormal bit
|
||||||
|
mant &= 0x3ff;
|
||||||
|
// else +/-0 -> +/-0
|
||||||
|
}
|
||||||
|
// combine all parts
|
||||||
|
return Float.intBitsToFloat(
|
||||||
|
// sign << ( 31 - 15 )
|
||||||
|
(hbits & 0x8000) << 16
|
||||||
|
// value << ( 23 - 10 )
|
||||||
|
| (exp | mant) << 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns all higher 16 bits as 0 for all results
|
||||||
|
public static int fromFloat(float fval) {
|
||||||
|
var fbits = Float.floatToIntBits(fval);
|
||||||
|
// sign only
|
||||||
|
int sign = fbits >>> 16 & 0x8000;
|
||||||
|
// rounded value
|
||||||
|
int val = (fbits & 0x7fffffff) + 0x1000;
|
||||||
|
|
||||||
|
// might be or become NaN/Inf
|
||||||
|
if (val >= 0x47800000)
|
||||||
|
// avoid Inf due to rounding
|
||||||
|
{
|
||||||
|
// is or must become
|
||||||
|
// NaN/Inf
|
||||||
|
if ((fbits & 0x7fffffff) >= 0x47800000) {
|
||||||
|
if (val < 0x7f800000) {
|
||||||
|
// make it +/-Inf
|
||||||
|
return sign | 0x7c00;
|
||||||
|
}
|
||||||
|
// remains +/-Inf or NaN
|
||||||
|
return sign | 0x7c00 |
|
||||||
|
// keep NaN (and Inf) bits
|
||||||
|
(fbits & 0x007fffff) >>> 13;
|
||||||
|
}
|
||||||
|
// unrounded not quite Inf
|
||||||
|
return sign | 0x7bff;
|
||||||
|
}
|
||||||
|
if (val >= 0x38800000) {
|
||||||
|
// exp - 127 + 15
|
||||||
|
return sign | val - 0x38000000 >>> 13;
|
||||||
|
}
|
||||||
|
if (val < 0x33000000) {
|
||||||
|
// becomes +/-0
|
||||||
|
return sign;
|
||||||
|
}
|
||||||
|
// tmp exp for subnormal calc
|
||||||
|
val = (fbits & 0x7fffffff) >>> 23;
|
||||||
|
// add subnormal bit
|
||||||
|
return sign | ((fbits & 0x7fffff | 0x800000)
|
||||||
|
// round depending on cut off
|
||||||
|
+ (0x800000 >>> val - 102)
|
||||||
|
// div by 2^(1-(exp-127+15)) and >> 13 | exp=0
|
||||||
|
>>> 126 - val);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.protocol;
|
||||||
|
|
||||||
|
import java.net.DatagramPacket;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data Structure for class SendDispatcherThread
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class PacketStruct {
|
||||||
|
private DatagramPacket packet;
|
||||||
|
|
||||||
|
public DatagramPacket getPacket() {
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean sent = false;
|
||||||
|
private long time = 0;
|
||||||
|
|
||||||
|
public PacketStruct(DatagramPacket packetPar) {
|
||||||
|
packet = packetPar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getSent() {
|
||||||
|
return sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSent(boolean sent) {
|
||||||
|
this.sent = sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTime(long time) {
|
||||||
|
// set the time only if it has not already been set once
|
||||||
|
if (this.time == 0) {
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,442 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.protocol;
|
||||||
|
|
||||||
|
import java.net.DatagramPacket;
|
||||||
|
import java.net.DatagramSocket;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.nio.channels.DatagramChannel;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissUDPConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissGatewayHandler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissGenericHandler;
|
||||||
|
import org.openhab.core.thing.Bridge;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provide to take packet, and send it to regular interval to Souliss
|
||||||
|
* Network
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class SendDispatcherRunnable implements Runnable {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(SendDispatcherRunnable.class);
|
||||||
|
|
||||||
|
private @Nullable SoulissGatewayHandler gwHandler;
|
||||||
|
static boolean bPopSuspend = false;
|
||||||
|
protected static ArrayList<PacketStruct> packetsList = new ArrayList<>();
|
||||||
|
private long startTime = System.currentTimeMillis();
|
||||||
|
static int iDelay = 0; // equal to 0 if array is empty
|
||||||
|
static int sendMinDelay = 0;
|
||||||
|
|
||||||
|
public SendDispatcherRunnable(Bridge bridge) {
|
||||||
|
this.gwHandler = (SoulissGatewayHandler) bridge.getHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put packet to send in ArrayList PacketList
|
||||||
|
*/
|
||||||
|
public static synchronized void put(DatagramPacket packetToPUT, Logger logger) {
|
||||||
|
bPopSuspend = true;
|
||||||
|
var bPacchettoGestito = false;
|
||||||
|
// I extract the node addressed by the incoming packet. returns -1 if the package is not of the
|
||||||
|
// SOULISS_UDP_FUNCTION_FORCE type
|
||||||
|
int node = getNode(packetToPUT);
|
||||||
|
if (node >= 0) {
|
||||||
|
logger.debug("Push packet in queue - Node {}", node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packetsList.isEmpty() || node < 0) {
|
||||||
|
bPacchettoGestito = false;
|
||||||
|
} else {
|
||||||
|
// OPTIMIZER
|
||||||
|
// scan packets list to sent
|
||||||
|
for (var i = 0; i < packetsList.size(); i++) {
|
||||||
|
if (node >= 0 && getNode(packetsList.get(i).getPacket()) == node && !packetsList.get(i).getSent()) {
|
||||||
|
// frame for the same node already present in the list
|
||||||
|
logger.debug("Frame UPD per nodo {} già presente in coda. Esecuzione ottimizzazione.", node);
|
||||||
|
bPacchettoGestito = true;
|
||||||
|
// if the packet to be inserted is shorter (or equal) than the one in the queue
|
||||||
|
// then I overwrite the bytes of the packet present in the queue
|
||||||
|
if (packetToPUT.getData().length <= packetsList.get(i).getPacket().getData().length) {
|
||||||
|
// it scrolls the command bytes and if the byte is non-zero overwrites the byte present in the
|
||||||
|
// queued packet
|
||||||
|
logger.trace("Optimizer. Packet to push: {}", macacoToString(packetToPUT.getData()));
|
||||||
|
logger.trace("Optimizer. Previous frame: {}",
|
||||||
|
macacoToString(packetsList.get(i).getPacket().getData()));
|
||||||
|
// typical values start from byte 12 onwards
|
||||||
|
for (var j = 12; j < packetToPUT.getData().length; j++) {
|
||||||
|
// if the j-th byte is different from zero then
|
||||||
|
// I overwrite it with the byte of the packet already present
|
||||||
|
if (packetToPUT.getData()[j] != 0) {
|
||||||
|
packetsList.get(i).getPacket().getData()[j] = packetToPUT.getData()[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.debug("Optimizer. Previous frame modified to: {}",
|
||||||
|
macacoToString(packetsList.get(i).getPacket().getData()));
|
||||||
|
} else {
|
||||||
|
// if the packet to be inserted is longer than the one in the list then
|
||||||
|
// I overwrite the bytes of the packet to be inserted, then I delete the one in the list
|
||||||
|
// and insert the new one
|
||||||
|
if (packetToPUT.getData().length > packetsList.get(i).getPacket().getData().length) {
|
||||||
|
for (var j = 12; j < packetsList.get(i).getPacket().getData().length; j++) {
|
||||||
|
// if the j-th byte is different from zero then I overwrite it with the byte of the
|
||||||
|
// packet already present
|
||||||
|
if ((packetsList.get(i).getPacket().getData()[j] != 0)
|
||||||
|
&& (packetToPUT.getData()[j] == 0)) {
|
||||||
|
// overwrite the bytes of the last frame
|
||||||
|
// only if the byte equals zero.
|
||||||
|
// If the last frame is nonzero
|
||||||
|
// takes precedence and must override
|
||||||
|
packetToPUT.getData()[j] = packetsList.get(i).getPacket().getData()[j];
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// removes the packet
|
||||||
|
logger.debug("Optimizer. Remove frame: {}",
|
||||||
|
macacoToString(packetsList.get(i).getPacket().getData()));
|
||||||
|
packetsList.remove(i);
|
||||||
|
// inserts the new
|
||||||
|
logger.debug("Optimizer. Add frame: {}", macacoToString(packetToPUT.getData()));
|
||||||
|
packetsList.add(new PacketStruct(packetToPUT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bPacchettoGestito) {
|
||||||
|
logger.debug("Add packet: {}", macacoToString(packetToPUT.getData()));
|
||||||
|
packetsList.add(new PacketStruct(packetToPUT));
|
||||||
|
}
|
||||||
|
bPopSuspend = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
DatagramSocket sender = null;
|
||||||
|
|
||||||
|
try (var channel = DatagramChannel.open();) {
|
||||||
|
if (checkTime()) {
|
||||||
|
PacketStruct sp = pop();
|
||||||
|
if (sp != null) {
|
||||||
|
logger.debug(
|
||||||
|
"SendDispatcherJob - Functional Code 0x{} - Packet: {} - Elementi rimanenti in lista: {}",
|
||||||
|
Integer.toHexString(sp.getPacket().getData()[7]), macacoToString(sp.getPacket().getData()),
|
||||||
|
packetsList.size());
|
||||||
|
|
||||||
|
sender = channel.socket();
|
||||||
|
sender.setReuseAddress(true);
|
||||||
|
sender.setBroadcast(true);
|
||||||
|
|
||||||
|
var localGwHandler = this.gwHandler;
|
||||||
|
if (localGwHandler != null) {
|
||||||
|
var sa = new InetSocketAddress(localGwHandler.getGwConfig().preferredLocalPortNumber);
|
||||||
|
sender.bind(sa);
|
||||||
|
sender.send(sp.getPacket());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare the states in memory with the frames sent.
|
||||||
|
// If match deletes the frame from the sent list
|
||||||
|
safeSendCheck();
|
||||||
|
|
||||||
|
resetTime();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("{}", e.getMessage());
|
||||||
|
} finally {
|
||||||
|
if (sender != null && !sender.isClosed()) {
|
||||||
|
sender.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get node number from packet
|
||||||
|
*/
|
||||||
|
private static int getNode(DatagramPacket packet) {
|
||||||
|
// 7 is the byte of the VNet frame at which I find the command code
|
||||||
|
// 10 is the byte of the VNet frame at which I find the node ID
|
||||||
|
if (packet.getData()[7] == SoulissUDPConstants.SOULISS_UDP_FUNCTION_FORCE) {
|
||||||
|
return packet.getData()[10];
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String macacoToString(byte[] frame2) {
|
||||||
|
byte[] frame = frame2.clone();
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.append("HEX: [");
|
||||||
|
for (byte b : frame) {
|
||||||
|
sb.append(String.format("%02X ", b));
|
||||||
|
}
|
||||||
|
sb.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check frame updates with packetList, where flag "sent" is true. If all
|
||||||
|
* commands was executed there delete packet in list.
|
||||||
|
*/
|
||||||
|
public void safeSendCheck() {
|
||||||
|
int node;
|
||||||
|
int iSlot;
|
||||||
|
SoulissGenericHandler localTyp;
|
||||||
|
var sCmd = "";
|
||||||
|
byte bExpected;
|
||||||
|
|
||||||
|
var sExpected = "";
|
||||||
|
|
||||||
|
// scan of the sent packets list
|
||||||
|
for (var i = 0; i < packetsList.size(); i++) {
|
||||||
|
|
||||||
|
if (packetsList.get(i).getSent()) {
|
||||||
|
node = getNode(packetsList.get(i).getPacket());
|
||||||
|
iSlot = 0;
|
||||||
|
for (var j = 12; j < packetsList.get(i).getPacket().getData().length; j++) {
|
||||||
|
// I check the slot only if the command is different from ZERO
|
||||||
|
if ((packetsList.get(i).getPacket().getData()[j] != 0) && (this.gwHandler != null)) {
|
||||||
|
localTyp = getHandler(node, iSlot, this.logger);
|
||||||
|
|
||||||
|
if (localTyp != null) {
|
||||||
|
bExpected = localTyp.getExpectedRawState(packetsList.get(i).getPacket().getData()[j]);
|
||||||
|
|
||||||
|
// if the expected value of the typical is -1 then it means that the typical does not
|
||||||
|
// support the
|
||||||
|
// function
|
||||||
|
// secureSend
|
||||||
|
if (bExpected < 0) {
|
||||||
|
localTyp = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// translate the command sent with the expected state e
|
||||||
|
// then compare with the current state
|
||||||
|
if (logger.isDebugEnabled() && localTyp != null) {
|
||||||
|
sCmd = Integer.toHexString(packetsList.get(i).getPacket().getData()[j]);
|
||||||
|
// command sent
|
||||||
|
sCmd = sCmd.length() < 2 ? "0x0" + sCmd.toUpperCase() : "0x" + sCmd.toUpperCase();
|
||||||
|
sExpected = Integer.toHexString(bExpected);
|
||||||
|
sExpected = sExpected.length() < 2 ? "0x0" + sExpected.toUpperCase()
|
||||||
|
: "0x" + sExpected.toUpperCase();
|
||||||
|
logger.debug(
|
||||||
|
"Compare. Node: {} Slot: {} Node Name: {} Command: {} Expected Souliss State: {} - Actual OH item State: {}",
|
||||||
|
node, iSlot, localTyp.getLabel(), sCmd, sExpected, localTyp.getRawState());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localTyp != null && checkExpectedState(localTyp.getRawState(), bExpected)) {
|
||||||
|
// if the value of the typical matches the value
|
||||||
|
// transmitted then I set the byte to zero.
|
||||||
|
// when all bytes are equal to zero then
|
||||||
|
// delete the frame
|
||||||
|
packetsList.get(i).getPacket().getData()[j] = 0;
|
||||||
|
logger.debug("{} Node: {} Slot: {} - OK Expected State", localTyp.getLabel(), node,
|
||||||
|
iSlot);
|
||||||
|
} else if (localTyp == null) {
|
||||||
|
if (bExpected < 0) {
|
||||||
|
// if the typical is not managed then I set the byte of the relative slot to zero
|
||||||
|
packetsList.get(i).getPacket().getData()[j] = 0;
|
||||||
|
} else {
|
||||||
|
// if there is no typical at slot j then it means that it is one
|
||||||
|
// slot
|
||||||
|
// connected
|
||||||
|
// to the previous one (ex: RGB, T31, ...)
|
||||||
|
// then if slot j-1 = 0 then j can also be set to 0
|
||||||
|
if (packetsList.get(i).getPacket().getData()[j - 1] == 0) {
|
||||||
|
packetsList.get(i).getPacket().getData()[j] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iSlot++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the value of all bytes that make up the packet is 0 then I remove the packet from
|
||||||
|
// list
|
||||||
|
// also if the timout has elapsed then I set the packet to be resent
|
||||||
|
if (checkAllsSlotZero(packetsList.get(i).getPacket())) {
|
||||||
|
logger.debug("Command packet executed - Removed");
|
||||||
|
packetsList.remove(i);
|
||||||
|
} else {
|
||||||
|
// if the frame is not equal to zero I check the TIMEOUT and if
|
||||||
|
// it has expired so I set the SENT flag to false
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
|
||||||
|
SoulissGatewayHandler localGwHandler = this.gwHandler;
|
||||||
|
if (localGwHandler != null) {
|
||||||
|
if ((localGwHandler.getGwConfig().timeoutToRequeue < time - packetsList.get(i).getTime())
|
||||||
|
&& (localGwHandler.getGwConfig().timeoutToRemovePacket < time
|
||||||
|
- packetsList.get(i).getTime())) {
|
||||||
|
logger.debug("Packet Execution timeout - Removed");
|
||||||
|
packetsList.remove(i);
|
||||||
|
} else {
|
||||||
|
logger.debug("Packet Execution timeout - Requeued");
|
||||||
|
packetsList.get(i).setSent(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private @Nullable SoulissGenericHandler getHandler(int node, int slot, Logger logger) {
|
||||||
|
SoulissGatewayHandler localGwHandler = this.gwHandler;
|
||||||
|
|
||||||
|
Iterator<Thing> thingsIterator;
|
||||||
|
if (localGwHandler != null) {
|
||||||
|
thingsIterator = localGwHandler.getThing().getThings().iterator();
|
||||||
|
Thing typ = null;
|
||||||
|
while (thingsIterator.hasNext()) {
|
||||||
|
typ = thingsIterator.next();
|
||||||
|
if (typ.getThingTypeUID().equals(SoulissBindingConstants.TOPICS_THING_TYPE)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SoulissGenericHandler handler = (SoulissGenericHandler) typ.getHandler();
|
||||||
|
|
||||||
|
// execute it only if binding is Souliss and update is for my
|
||||||
|
// Gateway
|
||||||
|
if ((handler != null) && (handler.getNode() == node && handler.getSlot() == slot)) {
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean checkExpectedState(byte itemState, byte expectedState) {
|
||||||
|
// if expected state is null than return true. The frame will not requeued
|
||||||
|
if (expectedState <= -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return itemState == expectedState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean checkAllsSlotZero(DatagramPacket packet) {
|
||||||
|
var bflag = true;
|
||||||
|
for (var j = 12; j < packet.getData().length; j++) {
|
||||||
|
if ((packet.getData()[j] != 0)) {
|
||||||
|
bflag = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bflag;
|
||||||
|
}
|
||||||
|
|
||||||
|
long t = 0;
|
||||||
|
long tPrec = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pop SocketAndPacket from ArrayList PacketList
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private synchronized PacketStruct pop() {
|
||||||
|
synchronized (this) {
|
||||||
|
SoulissGatewayHandler localGwHandler = this.gwHandler;
|
||||||
|
|
||||||
|
// don't pop if bPopSuspend = true
|
||||||
|
// bPopSuspend is set by the put method
|
||||||
|
if ((localGwHandler != null) && (!bPopSuspend)) {
|
||||||
|
t = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// brings the interval to the minimum only if:
|
||||||
|
// the length of the tail less than or equal to 1;
|
||||||
|
// if the SEND_DELAY time has elapsed.
|
||||||
|
|
||||||
|
if (packetsList.size() <= 1) {
|
||||||
|
iDelay = sendMinDelay;
|
||||||
|
} else {
|
||||||
|
iDelay = localGwHandler.getGwConfig().sendInterval;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var iPacket = 0;
|
||||||
|
var bFlagWhile = true;
|
||||||
|
// discard packages already sent
|
||||||
|
while ((iPacket < packetsList.size()) && bFlagWhile) {
|
||||||
|
if (packetsList.get(iPacket).getSent()) {
|
||||||
|
iPacket++;
|
||||||
|
} else {
|
||||||
|
bFlagWhile = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean tFlag = (t - tPrec) >= localGwHandler.getGwConfig().sendInterval;
|
||||||
|
|
||||||
|
// if we have reached the end of the list and then all
|
||||||
|
// packets have already been sent so I also place the tFlag
|
||||||
|
// to false (as if the timeout hasn't elapsed yet)
|
||||||
|
if (iPacket >= packetsList.size()) {
|
||||||
|
tFlag = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!packetsList.isEmpty()) && tFlag) {
|
||||||
|
tPrec = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// extract the first element of the list
|
||||||
|
PacketStruct sp = packetsList.get(iPacket);
|
||||||
|
|
||||||
|
// PACKAGE MANAGEMENT: deleted from the list or
|
||||||
|
// marked as sent if it is a FORCE
|
||||||
|
if (packetsList.get(iPacket).getPacket()
|
||||||
|
.getData()[7] == SoulissUDPConstants.SOULISS_UDP_FUNCTION_FORCE) {
|
||||||
|
// flag sent set to true
|
||||||
|
packetsList.get(iPacket).setSent(true);
|
||||||
|
// set time
|
||||||
|
packetsList.get(iPacket).setTime(System.currentTimeMillis());
|
||||||
|
} else {
|
||||||
|
packetsList.remove(iPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("POP: {} packets in memory", packetsList.size());
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
var iPacketSentCounter = 0;
|
||||||
|
var i = 0;
|
||||||
|
while ((i < packetsList.size())) {
|
||||||
|
if (packetsList.get(i).getSent()) {
|
||||||
|
iPacketSentCounter++;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
logger.debug("POP: {} force frame sent", iPacketSentCounter);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("Pop frame {} - Delay for 'SendDispatcherThread' setted to {} mills.",
|
||||||
|
macacoToString(sp.getPacket().getData()), iDelay);
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetTime() {
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkTime() {
|
||||||
|
return startTime < (System.currentTimeMillis() - iDelay);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,586 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.protocol;
|
||||||
|
|
||||||
|
import java.net.DatagramPacket;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissBindingConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissProtocolConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.SoulissUDPConstants;
|
||||||
|
import org.openhab.binding.souliss.internal.discovery.DiscoverResult;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissGatewayHandler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissGenericHandler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT11Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT12Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT13Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT14Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT16Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT18Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT19Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT1AHandler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT22Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT31Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT41Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT42Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT5nHandler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT61Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT62Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT63Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT64Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT65Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT66Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT67Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissT68Handler;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissTopicsHandler;
|
||||||
|
import org.openhab.core.library.types.DecimalType;
|
||||||
|
import org.openhab.core.library.types.StringType;
|
||||||
|
import org.openhab.core.thing.Bridge;
|
||||||
|
import org.openhab.core.thing.Thing;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class decodes incoming Souliss packets, starting from decodevNet
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
* @author Alessandro Del Pex - Souliss App
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class UDPDecoder {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(UDPDecoder.class);
|
||||||
|
private @Nullable DiscoverResult discoverResult;
|
||||||
|
private @Nullable SoulissGatewayHandler gwHandler;
|
||||||
|
|
||||||
|
private @Nullable Byte lastByteGatewayIp = null;
|
||||||
|
|
||||||
|
public UDPDecoder(Bridge bridge, @Nullable DiscoverResult pDiscoverResult) {
|
||||||
|
this.gwHandler = (SoulissGatewayHandler) bridge.getHandler();
|
||||||
|
this.discoverResult = pDiscoverResult;
|
||||||
|
var localGwHandler = this.gwHandler;
|
||||||
|
if (localGwHandler != null) {
|
||||||
|
this.lastByteGatewayIp = (byte) Integer
|
||||||
|
.parseInt(localGwHandler.getGwConfig().gatewayLanAddress.split("\\.")[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get packet from VNET Frame
|
||||||
|
*
|
||||||
|
* @param packet
|
||||||
|
* incoming datagram
|
||||||
|
*/
|
||||||
|
public void decodeVNetDatagram(DatagramPacket packet) {
|
||||||
|
int checklen = packet.getLength();
|
||||||
|
ArrayList<Byte> mac = new ArrayList<>();
|
||||||
|
for (var ig = 7; ig < checklen; ig++) {
|
||||||
|
mac.add((byte) (packet.getData()[ig] & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if decoded Gw equal to ip of bridge handler or 1 (action messages)
|
||||||
|
Byte gwCheck = (byte) (packet.getData()[5] & 0xFF);
|
||||||
|
if ((gwCheck == 1) || (gwCheck.equals(this.lastByteGatewayIp))) {
|
||||||
|
decodeMacaco((byte) (packet.getData()[5] & 0xFF), mac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes lower level MaCaCo packet
|
||||||
|
*
|
||||||
|
* @param lastByteGatewayIP
|
||||||
|
*
|
||||||
|
* @param macacoPck
|
||||||
|
*/
|
||||||
|
private void decodeMacaco(byte lastByteGatewayIP, ArrayList<Byte> macacoPck) {
|
||||||
|
int functionalCode = macacoPck.get(0);
|
||||||
|
switch (functionalCode) {
|
||||||
|
case SoulissUDPConstants.SOULISS_UDP_FUNCTION_PING_RESP:
|
||||||
|
logger.debug("Received functional code: 0x{}- Ping answer", Integer.toHexString(functionalCode));
|
||||||
|
decodePing(macacoPck);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SoulissUDPConstants.SOULISS_UDP_FUNCTION_DISCOVER_GW_NODE_BCAST_RESP:
|
||||||
|
logger.debug("Received functional code: 0x{} - Discover a gateway node answer (broadcast)",
|
||||||
|
Integer.toHexString(functionalCode));
|
||||||
|
try {
|
||||||
|
decodePingBroadcast(macacoPck);
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
logger.warn("Error: {}", e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SoulissUDPConstants.SOULISS_UDP_FUNCTION_POLL_RESP:
|
||||||
|
logger.debug("Received functional code: 0x{} - subscribe response",
|
||||||
|
Integer.toHexString(functionalCode));
|
||||||
|
decodeStateRequest(macacoPck);
|
||||||
|
break;
|
||||||
|
case SoulissUDPConstants.SOULISS_UDP_FUNCTION_SUBSCRIBE_RESP:
|
||||||
|
logger.debug("Received functional code: 0x{} - Read state answer", Integer.toHexString(functionalCode));
|
||||||
|
decodeStateRequest(macacoPck);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Answer for assigned typical logic
|
||||||
|
case SoulissUDPConstants.SOULISS_UDP_FUNCTION_TYP_RESP:
|
||||||
|
logger.debug("Received functional code: 0x{}- Read typical logic answer",
|
||||||
|
Integer.toHexString(functionalCode));
|
||||||
|
decodeTypRequest(lastByteGatewayIP, macacoPck);
|
||||||
|
break;
|
||||||
|
// Answer
|
||||||
|
case SoulissUDPConstants.SOULISS_UDP_FUNCTION_HEALTHY_RESP:
|
||||||
|
// nodes healthy
|
||||||
|
logger.debug("Received functional code: 0x{} - Nodes Healthy", Integer.toHexString(functionalCode));
|
||||||
|
decodeHealthyRequest(macacoPck);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (byte) SoulissUDPConstants.SOULISS_UDP_FUNCTION_DBSTRUCT_RESP:
|
||||||
|
logger.debug("Received functional code: 0x{} - Database structure answer",
|
||||||
|
Integer.toHexString(functionalCode));
|
||||||
|
decodeDBStructRequest(macacoPck);
|
||||||
|
break;
|
||||||
|
case 0x83:
|
||||||
|
logger.debug("Functional code not supported");
|
||||||
|
break;
|
||||||
|
case 0x84:
|
||||||
|
logger.debug("Data out of range");
|
||||||
|
break;
|
||||||
|
case 0x85:
|
||||||
|
logger.debug("Subscription refused");
|
||||||
|
break;
|
||||||
|
case (byte) SoulissUDPConstants.SOULISS_UDP_FUNCTION_ACTION_MESSAGE:
|
||||||
|
logger.debug("Received functional code: 0x{} - Action Message (Topic)",
|
||||||
|
Integer.toHexString(functionalCode));
|
||||||
|
decodeActionMessages(macacoPck);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.debug("Received functional code: 0x{} - unused by OH Binding",
|
||||||
|
Integer.toHexString(functionalCode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mac
|
||||||
|
*/
|
||||||
|
private void decodePing(ArrayList<Byte> mac) {
|
||||||
|
// not used
|
||||||
|
int putIn1 = mac.get(1);
|
||||||
|
// not used
|
||||||
|
int putIn2 = mac.get(2);
|
||||||
|
logger.debug("decodePing: putIn code: {}, {}", putIn1, putIn2);
|
||||||
|
var localGwHandler = this.gwHandler;
|
||||||
|
if (localGwHandler != null) {
|
||||||
|
localGwHandler.gatewayDetected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void decodePingBroadcast(ArrayList<Byte> macaco) throws UnknownHostException {
|
||||||
|
String ip = macaco.get(5) + "." + macaco.get(6) + "." + macaco.get(7) + "." + macaco.get(8);
|
||||||
|
byte[] addr = { (macaco.get(5)).byteValue(), (macaco.get(6)).byteValue(), (macaco.get(7)).byteValue(),
|
||||||
|
(macaco.get(8)).byteValue() };
|
||||||
|
logger.debug("decodePingBroadcast. Gateway Discovery. IP: {}", ip);
|
||||||
|
|
||||||
|
var localDiscoverResult = this.discoverResult;
|
||||||
|
if (localDiscoverResult != null) {
|
||||||
|
localDiscoverResult.gatewayDetected(InetAddress.getByAddress(addr), macaco.get(8).toString());
|
||||||
|
} else {
|
||||||
|
logger.debug("decodePingBroadcast aborted. 'discoverResult' is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* decode Typicals Request Packet
|
||||||
|
* It read Souliss Network and create OH items
|
||||||
|
*
|
||||||
|
* @param lastByteGatewayIP
|
||||||
|
*
|
||||||
|
* @param mac
|
||||||
|
*/
|
||||||
|
private void decodeTypRequest(byte lastByteGatewayIP, ArrayList<Byte> mac) {
|
||||||
|
var localGwHandler = this.gwHandler;
|
||||||
|
if (localGwHandler != null) {
|
||||||
|
int typXnodo = localGwHandler.getMaxTypicalXnode();
|
||||||
|
|
||||||
|
byte tgtnode = mac.get(3);
|
||||||
|
int numberOf = mac.get(4);
|
||||||
|
|
||||||
|
// creates Souliss nodes
|
||||||
|
for (var j = 0; j < numberOf; j++) {
|
||||||
|
// create only not-empty typicals
|
||||||
|
if ((mac.get(5 + j) != 0) && (mac.get(5 + j) != SoulissProtocolConstants.SOULISS_T_RELATED)) {
|
||||||
|
byte typical = mac.get(5 + j);
|
||||||
|
byte slot = (byte) (j % typXnodo);
|
||||||
|
byte node = (byte) (j / typXnodo + tgtnode);
|
||||||
|
logger.debug("Thing Detected. IP (last byte): {}, Typical: 0x{}, Node: {}, Slot: {} ",
|
||||||
|
lastByteGatewayIP, Integer.toHexString(typical), node, slot);
|
||||||
|
|
||||||
|
var localDiscoverResult = this.discoverResult;
|
||||||
|
if (localDiscoverResult != null) {
|
||||||
|
localDiscoverResult.thingDetectedTypicals(lastByteGatewayIP, typical, node, slot);
|
||||||
|
} else {
|
||||||
|
logger.debug("decodeTypRequest aborted. 'discoverResult' is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* decode Typicals Request Packet
|
||||||
|
* It read Action Messages on Souliss Network and create items
|
||||||
|
*
|
||||||
|
* @param lastByteGatewayIP
|
||||||
|
*
|
||||||
|
* @param mac
|
||||||
|
*/
|
||||||
|
private void decodeActionMessages(ArrayList<Byte> mac) {
|
||||||
|
String sTopicNumber;
|
||||||
|
String sTopicVariant;
|
||||||
|
float fRet = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// A 16-bit Topic Number: Define the topic itself
|
||||||
|
// A 8-bit Topic Variant : Define a variant for the topic
|
||||||
|
|
||||||
|
String[] sTopicNumberArray = { Integer.toHexString(mac.get(2)).toUpperCase(),
|
||||||
|
Integer.toHexString(mac.get(1)).toUpperCase() };
|
||||||
|
if (sTopicNumberArray[0].length() == 1) {
|
||||||
|
sTopicNumberArray[0] = "0" + sTopicNumberArray[0];
|
||||||
|
}
|
||||||
|
if (sTopicNumberArray[1].length() == 1) {
|
||||||
|
sTopicNumberArray[1] = "0" + sTopicNumberArray[1];
|
||||||
|
}
|
||||||
|
sTopicNumber = sTopicNumberArray[0] + sTopicNumberArray[1];
|
||||||
|
logger.debug("Topic Number: 0x{}", sTopicNumber);
|
||||||
|
|
||||||
|
sTopicVariant = Integer.toHexString(mac.get(3)).toUpperCase();
|
||||||
|
if (sTopicVariant.length() == 1) {
|
||||||
|
sTopicVariant = "0" + sTopicVariant;
|
||||||
|
}
|
||||||
|
logger.debug("Topic Variant: 0x{}", sTopicVariant);
|
||||||
|
if (mac.get(4) == 1) {
|
||||||
|
fRet = mac.get(5);
|
||||||
|
logger.debug("Topic Value (Payload one byte): {} ", Integer.toHexString(mac.get(5)).toUpperCase());
|
||||||
|
} else if (mac.get(4) == 2) {
|
||||||
|
byte[] value = { mac.get(5), mac.get(6) };
|
||||||
|
|
||||||
|
int shifted = value[1] << 8;
|
||||||
|
fRet = HalfFloatUtils.toFloat(shifted + value[0]);
|
||||||
|
logger.debug("Topic Value (Payload 2 bytes): {}", fRet);
|
||||||
|
}
|
||||||
|
var localGwHandler = this.gwHandler;
|
||||||
|
if (localGwHandler != null) {
|
||||||
|
var listThings = localGwHandler.getThing().getThings();
|
||||||
|
|
||||||
|
Boolean bIsPresent = false;
|
||||||
|
|
||||||
|
for (Thing t : listThings) {
|
||||||
|
if (t.getUID().toString().split(":")[2]
|
||||||
|
.equals(sTopicNumber + SoulissBindingConstants.UUID_NODE_SLOT_SEPARATOR + sTopicVariant)) {
|
||||||
|
var topicHandler = (SoulissTopicsHandler) (t.getHandler());
|
||||||
|
if (topicHandler != null) {
|
||||||
|
topicHandler.setState(DecimalType.valueOf(Float.toString(fRet)));
|
||||||
|
bIsPresent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var localDiscoverResult = this.discoverResult;
|
||||||
|
if (localDiscoverResult != null && !bIsPresent) {
|
||||||
|
localDiscoverResult.thingDetectedActionMessages(sTopicNumber, sTopicVariant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception uy) {
|
||||||
|
logger.warn("decodeActionMessages ERROR");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* decode DB Struct Request Packet
|
||||||
|
* It return Souliss Network:
|
||||||
|
* node number
|
||||||
|
* max supported number of nodes
|
||||||
|
* max typical per node
|
||||||
|
* max requests
|
||||||
|
* See Souliss wiki for details
|
||||||
|
*
|
||||||
|
* @param lastByteGatewayIP
|
||||||
|
*
|
||||||
|
* @param mac
|
||||||
|
*/
|
||||||
|
private void decodeDBStructRequest(ArrayList<Byte> mac) {
|
||||||
|
int nodes = mac.get(5);
|
||||||
|
int maxTypicalXnode = mac.get(7);
|
||||||
|
|
||||||
|
SoulissGatewayHandler localGwHandler = this.gwHandler;
|
||||||
|
if (localGwHandler != null) {
|
||||||
|
localGwHandler.setNodes(nodes);
|
||||||
|
localGwHandler.setMaxTypicalXnode(maxTypicalXnode);
|
||||||
|
localGwHandler.dbStructAnswerReceived();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a souliss nodes health request
|
||||||
|
*
|
||||||
|
* @param macaco
|
||||||
|
* packet
|
||||||
|
*/
|
||||||
|
private void decodeHealthyRequest(ArrayList<Byte> mac) {
|
||||||
|
int numberOf = mac.get(4);
|
||||||
|
|
||||||
|
for (var i = 5; i < 5 + numberOf; i++) {
|
||||||
|
var localGwHandler = this.gwHandler;
|
||||||
|
if (localGwHandler != null) {
|
||||||
|
// build an array containing healths
|
||||||
|
List<Thing> listaThings = localGwHandler.getThing().getThings();
|
||||||
|
|
||||||
|
ThingHandler handler = null;
|
||||||
|
for (Thing thing : listaThings) {
|
||||||
|
if (thing.getThingTypeUID().equals(SoulissBindingConstants.TOPICS_THING_TYPE)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
handler = thing.getHandler();
|
||||||
|
if (handler != null) {
|
||||||
|
int tgtnode = i - 5;
|
||||||
|
if (((SoulissGenericHandler) handler).getNode() == tgtnode) {
|
||||||
|
((SoulissGenericHandler) handler).setHealthy((mac.get(i)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.debug("decode Healthy Request Warning. Thing handler is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void decodeStateRequest(ArrayList<Byte> mac) {
|
||||||
|
int tgtnode = mac.get(3);
|
||||||
|
|
||||||
|
Iterator<Thing> thingsIterator = null;
|
||||||
|
var localGwHandler = this.gwHandler;
|
||||||
|
if (localGwHandler != null) {
|
||||||
|
thingsIterator = localGwHandler.getThing().getThings().iterator();
|
||||||
|
|
||||||
|
var bFound = false;
|
||||||
|
Thing typ = null;
|
||||||
|
while (thingsIterator.hasNext() && !bFound) {
|
||||||
|
typ = thingsIterator.next();
|
||||||
|
// if a topic continue
|
||||||
|
// ignoring it
|
||||||
|
if (typ.getThingTypeUID().equals(SoulissBindingConstants.TOPICS_THING_TYPE)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String[] sUIDArray = typ.getUID().getAsString().split(":");
|
||||||
|
ThingHandler handler = typ.getHandler();
|
||||||
|
// execute it only if binding is Souliss and update is for my
|
||||||
|
// Gateway
|
||||||
|
if (handler != null) {
|
||||||
|
// execute it
|
||||||
|
// only
|
||||||
|
// if it is
|
||||||
|
// node
|
||||||
|
// to update
|
||||||
|
if (((SoulissGenericHandler) handler).getNode() == tgtnode) {
|
||||||
|
// ...now check slot
|
||||||
|
int slot = ((SoulissGenericHandler) handler).getSlot();
|
||||||
|
// get typical value
|
||||||
|
var sVal = getByteAtSlot(mac, slot);
|
||||||
|
var decodingLiteralLabel = "Decoding {}{}";
|
||||||
|
var packetLabel = " packet";
|
||||||
|
// update Txx
|
||||||
|
switch (sUIDArray[1]) {
|
||||||
|
case SoulissBindingConstants.T11:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T11, packetLabel);
|
||||||
|
((SoulissT11Handler) handler).setRawState(sVal);
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T12:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T12, packetLabel);
|
||||||
|
((SoulissT12Handler) handler).setRawState(sVal);
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T13:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T13, packetLabel);
|
||||||
|
((SoulissT13Handler) handler).setRawState(sVal);
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T14:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T14, packetLabel);
|
||||||
|
((SoulissT14Handler) handler).setRawState(sVal);
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T16:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T16, packetLabel);
|
||||||
|
((SoulissT16Handler) handler).setRawStateCommand(sVal);
|
||||||
|
((SoulissT16Handler) handler).setRawStateRgb(getByteAtSlot(mac, slot + 1),
|
||||||
|
getByteAtSlot(mac, slot + 2), getByteAtSlot(mac, slot + 3));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SoulissBindingConstants.T18:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T18, packetLabel);
|
||||||
|
((SoulissT18Handler) handler).setRawState(sVal);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SoulissBindingConstants.T19:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T19, packetLabel);
|
||||||
|
((SoulissT19Handler) handler).setRawState(sVal);
|
||||||
|
((SoulissT19Handler) handler).setRawStateDimmerValue(getByteAtSlot(mac, slot + 1));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SoulissBindingConstants.T1A:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T1A, packetLabel);
|
||||||
|
((SoulissT1AHandler) handler).setRawState(sVal);
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T21:
|
||||||
|
case SoulissBindingConstants.T22:
|
||||||
|
logger.debug(decodingLiteralLabel,
|
||||||
|
SoulissBindingConstants.T21 + "/" + SoulissBindingConstants.T22, packetLabel);
|
||||||
|
((SoulissT22Handler) handler).setRawState(sVal);
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T31:
|
||||||
|
logger.debug("Decoding {}/{}", SoulissBindingConstants.T31,
|
||||||
|
SoulissBindingConstants.T31);
|
||||||
|
logger.debug("packet: ");
|
||||||
|
logger.debug("- bit0 (system on-off): {}", getBitState(sVal, 0));
|
||||||
|
logger.debug("- bit1 (heating on-off): {}", getBitState(sVal, 1));
|
||||||
|
logger.debug("- bit2 (cooling on-off): {}", getBitState(sVal, 2));
|
||||||
|
logger.debug("- bit3 (fan1 on-off): {}", getBitState(sVal, 3));
|
||||||
|
logger.debug("- bit4 (fan2 on-off): {}", getBitState(sVal, 4));
|
||||||
|
logger.debug("- bit5 (fan3 on-off): {}", getBitState(sVal, 5));
|
||||||
|
logger.debug("- bit6 (Manual/automatic fan mode): {}", getBitState(sVal, 6));
|
||||||
|
logger.debug("- bit7 (heating/cooling mode): {}", getBitState(sVal, 7));
|
||||||
|
|
||||||
|
((SoulissT31Handler) handler).setRawStateValues(sVal, getFloatAtSlot(mac, slot + 1),
|
||||||
|
getFloatAtSlot(mac, slot + 3));
|
||||||
|
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T41:
|
||||||
|
((SoulissT41Handler) handler).setRawState(sVal);
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T42:
|
||||||
|
((SoulissT42Handler) handler).setRawState(sVal);
|
||||||
|
switch (sVal) {
|
||||||
|
case SoulissProtocolConstants.SOULISS_T4N_NO_ANTITHEFT:
|
||||||
|
((SoulissT42Handler) handler).setState(StringType
|
||||||
|
.valueOf(SoulissBindingConstants.T4N_ALARMOFF_MESSAGE_CHANNEL));
|
||||||
|
break;
|
||||||
|
case SoulissProtocolConstants.SOULISS_T4N_ALARM:
|
||||||
|
((SoulissT42Handler) handler).setState(StringType
|
||||||
|
.valueOf(SoulissBindingConstants.T4N_ALARMON_MESSAGE_CHANNEL));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T51:
|
||||||
|
case SoulissBindingConstants.T52:
|
||||||
|
case SoulissBindingConstants.T53:
|
||||||
|
case SoulissBindingConstants.T54:
|
||||||
|
case SoulissBindingConstants.T55:
|
||||||
|
case SoulissBindingConstants.T56:
|
||||||
|
case SoulissBindingConstants.T57:
|
||||||
|
case SoulissBindingConstants.T58:
|
||||||
|
logger.debug("Decoding T5n packet");
|
||||||
|
if (!Float.isNaN(getFloatAtSlot(mac, slot))) {
|
||||||
|
((SoulissT5nHandler) handler).setFloatValue(getFloatAtSlot(mac, slot));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T61:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T61, packetLabel);
|
||||||
|
if (!Float.isNaN(getFloatAtSlot(mac, slot))) {
|
||||||
|
((SoulissT61Handler) handler).setFloatValue(getFloatAtSlot(mac, slot));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T62:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T62, packetLabel);
|
||||||
|
if (!Float.isNaN(getFloatAtSlot(mac, slot))) {
|
||||||
|
((SoulissT62Handler) handler).setFloatValue(getFloatAtSlot(mac, slot));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T63:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T63, packetLabel);
|
||||||
|
if (!Float.isNaN(getFloatAtSlot(mac, slot))) {
|
||||||
|
((SoulissT63Handler) handler).setFloatValue(getFloatAtSlot(mac, slot));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T64:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T64, packetLabel);
|
||||||
|
if (!Float.isNaN(getFloatAtSlot(mac, slot))) {
|
||||||
|
((SoulissT64Handler) handler).setFloatValue(getFloatAtSlot(mac, slot));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T65:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T65, packetLabel);
|
||||||
|
if (!Float.isNaN(getFloatAtSlot(mac, slot))) {
|
||||||
|
((SoulissT65Handler) handler).setFloatValue(getFloatAtSlot(mac, slot));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T66:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T66, packetLabel);
|
||||||
|
if (!Float.isNaN(getFloatAtSlot(mac, slot))) {
|
||||||
|
((SoulissT66Handler) handler).setFloatValue(getFloatAtSlot(mac, slot));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T67:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T67, packetLabel);
|
||||||
|
if (!Float.isNaN(getFloatAtSlot(mac, slot))) {
|
||||||
|
((SoulissT67Handler) handler).setFloatValue(getFloatAtSlot(mac, slot));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SoulissBindingConstants.T68:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.T68, packetLabel);
|
||||||
|
if (!Float.isNaN(getFloatAtSlot(mac, slot))) {
|
||||||
|
((SoulissT68Handler) handler).setFloatValue(getFloatAtSlot(mac, slot));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SoulissBindingConstants.TOPICS:
|
||||||
|
logger.debug(decodingLiteralLabel, SoulissBindingConstants.TOPICS, packetLabel);
|
||||||
|
if (!Float.isNaN(getFloatAtSlot(mac, slot))) {
|
||||||
|
((SoulissTopicsHandler) handler).setFloatValue(getFloatAtSlot(mac, slot));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.debug("Unsupported typical");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte getByteAtSlot(ArrayList<Byte> mac, int slot) {
|
||||||
|
return mac.get(5 + slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float getFloatAtSlot(ArrayList<Byte> mac, int slot) {
|
||||||
|
int iOutput = mac.get(5 + slot) & 0xFF;
|
||||||
|
int iOutput2 = mac.get(5 + slot + 1) & 0xFF;
|
||||||
|
// we have two bytes, convert them...
|
||||||
|
int shifted = iOutput2 << 8;
|
||||||
|
return HalfFloatUtils.toFloat(shifted + iOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getBitState(byte vRaw, int iBit) {
|
||||||
|
final var maskBit1 = 0x1;
|
||||||
|
|
||||||
|
if (((vRaw >>> iBit) & maskBit1) == 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,116 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.souliss.internal.protocol;
|
||||||
|
|
||||||
|
import java.net.BindException;
|
||||||
|
import java.net.DatagramPacket;
|
||||||
|
import java.net.DatagramSocket;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketTimeoutException;
|
||||||
|
import java.nio.channels.DatagramChannel;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.souliss.internal.discovery.DiscoverResult;
|
||||||
|
import org.openhab.binding.souliss.internal.handler.SoulissGatewayHandler;
|
||||||
|
import org.openhab.core.thing.Bridge;
|
||||||
|
import org.openhab.core.util.HexUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provide receive packet from network
|
||||||
|
*
|
||||||
|
* @author Tonino Fazio - Initial contribution
|
||||||
|
* @author Luca Calcaterra - Refactor for OH3
|
||||||
|
* @author Alessandro Del Pex - Souliss App
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class UDPListenDiscoverRunnable implements Runnable {
|
||||||
|
|
||||||
|
protected boolean bExit = false;
|
||||||
|
private @Nullable UDPDecoder decoder = null;
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(UDPListenDiscoverRunnable.class);
|
||||||
|
|
||||||
|
private @Nullable SoulissGatewayHandler gwHandler;
|
||||||
|
|
||||||
|
public UDPListenDiscoverRunnable(Bridge bridge, @Nullable DiscoverResult pDiscoverResult) {
|
||||||
|
this.gwHandler = (SoulissGatewayHandler) bridge.getHandler();
|
||||||
|
decoder = new UDPDecoder(bridge, pDiscoverResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
DatagramSocket socket = null;
|
||||||
|
|
||||||
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
|
try {
|
||||||
|
// open socket for listening...
|
||||||
|
var channel = DatagramChannel.open();
|
||||||
|
socket = channel.socket();
|
||||||
|
|
||||||
|
socket.setReuseAddress(true);
|
||||||
|
socket.setBroadcast(true);
|
||||||
|
|
||||||
|
var localGwHandler = this.gwHandler;
|
||||||
|
if (localGwHandler != null) {
|
||||||
|
var sa = new InetSocketAddress(localGwHandler.getGwConfig().preferredLocalPortNumber);
|
||||||
|
socket.bind(sa);
|
||||||
|
|
||||||
|
var buf = new byte[200];
|
||||||
|
// receive request
|
||||||
|
final var packet = new DatagramPacket(buf, buf.length);
|
||||||
|
socket.setSoTimeout(60000);
|
||||||
|
socket.receive(packet);
|
||||||
|
buf = packet.getData();
|
||||||
|
|
||||||
|
// **************** DECODER ********************
|
||||||
|
logger.debug("Packet received (port {}) {}", socket.getLocalPort(), HexUtils.bytesToHex(buf));
|
||||||
|
|
||||||
|
var localDecoder = this.decoder;
|
||||||
|
if (localDecoder != null) {
|
||||||
|
localDecoder.decodeVNetDatagram(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (BindException e) {
|
||||||
|
logger.warn("UDP Port busy, Souliss already listening? {} ", e.getLocalizedMessage());
|
||||||
|
try {
|
||||||
|
if (socket != null && !socket.isClosed()) {
|
||||||
|
socket.close();
|
||||||
|
}
|
||||||
|
} catch (Exception e1) {
|
||||||
|
logger.warn("UDP socket close failed: {} ", e1.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
} catch (SocketTimeoutException e2) {
|
||||||
|
logger.warn("UDP SocketTimeoutException close: {}", e2.getLocalizedMessage());
|
||||||
|
if (socket != null && !socket.isClosed()) {
|
||||||
|
socket.close();
|
||||||
|
}
|
||||||
|
} catch (Exception ee) {
|
||||||
|
logger.warn("Exception receiving-decoding message: {} ", ee.getLocalizedMessage());
|
||||||
|
if (socket != null && !socket.isClosed()) {
|
||||||
|
socket.close();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
var localGwHandler = this.gwHandler;
|
||||||
|
if (socket != null && !socket.isClosed()) {
|
||||||
|
socket.close();
|
||||||
|
} else if ((socket == null) && (localGwHandler != null)) {
|
||||||
|
localGwHandler.setBridgeStatus(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<binding:binding id="souliss" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||||
|
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||||
|
|
||||||
|
<name>Souliss Binding</name>
|
||||||
|
<description>This is the binding for Souliss. The Arduino based SmartHome..</description>
|
||||||
|
|
||||||
|
</binding:binding>
|
File diff suppressed because it is too large
Load Diff
@ -317,6 +317,7 @@
|
|||||||
<module>org.openhab.binding.sonos</module>
|
<module>org.openhab.binding.sonos</module>
|
||||||
<module>org.openhab.binding.sonyaudio</module>
|
<module>org.openhab.binding.sonyaudio</module>
|
||||||
<module>org.openhab.binding.sonyprojector</module>
|
<module>org.openhab.binding.sonyprojector</module>
|
||||||
|
<module>org.openhab.binding.souliss</module>
|
||||||
<module>org.openhab.binding.spotify</module>
|
<module>org.openhab.binding.spotify</module>
|
||||||
<module>org.openhab.binding.squeezebox</module>
|
<module>org.openhab.binding.squeezebox</module>
|
||||||
<module>org.openhab.binding.surepetcare</module>
|
<module>org.openhab.binding.surepetcare</module>
|
||||||
|
Loading…
Reference in New Issue
Block a user