added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
32
bundles/org.openhab.binding.velbus/.classpath
Normal file
32
bundles/org.openhab.binding.velbus/.classpath
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
23
bundles/org.openhab.binding.velbus/.project
Normal file
23
bundles/org.openhab.binding.velbus/.project
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.openhab.binding.velbus</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
13
bundles/org.openhab.binding.velbus/NOTICE
Normal file
13
bundles/org.openhab.binding.velbus/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
|
||||
263
bundles/org.openhab.binding.velbus/README.md
Normal file
263
bundles/org.openhab.binding.velbus/README.md
Normal file
@@ -0,0 +1,263 @@
|
||||
# Velbus Binding
|
||||
|
||||
The Velbus binding integrates with a [Velbus](https://www.velbus.eu/) system through a Velbus configuration module (VMBRSUSB, VMB1USB or VMB1RS) or a network connection (TCP/IP).
|
||||
|
||||
The binding has been tested with a USB configuration module for universal mounting (VMB1USB).
|
||||
For optimal stability, the preferred configuration module is the VMBRSUSB module.
|
||||
|
||||
The binding exposes basic actions from the Velbus System that can be triggered from the smartphone/tablet interface, as defined by the [Velbus Protocol info sheets](https://github.com/velbus).
|
||||
|
||||
Supported item types are switches, dimmers and rollershutters.
|
||||
Pushbutton, temperature sensors and input module states are retrieved and made available in the binding.
|
||||
|
||||
## Supported Things
|
||||
|
||||
|
||||
A Velbus configuration module (e.g. VMBRSUSB) or a network server (e.g. [VelServer](https://github.com/StefCoene/velserver/wiki/TCP-server-for-Velbus)) is required as a "bridge" for accessing any other Velbus devices.
|
||||
|
||||
The supported Velbus devices are:
|
||||
|
||||
```
|
||||
vmb1bl, vmb1bls, vmb1dm, vmb1led, vmb1ry, vmb1ryno, vmb1rynos, vmb1rys, vmb1ts, vmb2bl, vmb2ble, vmb2pbn, vmb4an, vmb4dc, vmb4ry, vmb4ryld, vmb4ryno, vmb6in, vmb6pbn, vmb7in, vmb8ir, vmb8pb, vmb8pbu, vmbdme, vmbdmi, vmbdmir, vmbel1, vmbel2, vmbel4, vmbelo, vmbgp1, vmbgp2, vmbgp4, vmbgp4pir, vmbgpo, vmbgpod, vmbmeteo, vmbpirc, vmbpirm, vmbpiro
|
||||
```
|
||||
|
||||
The type of a specific device can be found in the configuration section for things in the Paper UI.
|
||||
It is part of the unique thing id which could look like:
|
||||
|
||||
```
|
||||
velbus:vmb4ryld:0424e5d2:01:CH1
|
||||
```
|
||||
|
||||
The thing type is the second string behind the first colon and in this example it is **vmb4ryld**.
|
||||
|
||||
## Discovery
|
||||
|
||||
The Velbus bridge cannot be discovered automatically.
|
||||
It has to be added manually by defining the serial port of the Velbus Configuration module for the Velbus Serial Bridge or by defining the IP Address and port for the Velbus Network Bridge.
|
||||
|
||||
Once the bridge has been added as a thing, a manual scan can be launched to discover all other supported Velbus devices on the bus.
|
||||
These devices will be available in the inbox.
|
||||
The discovery scan will also retrieve the channel names of the Velbus devices.
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
The Velbus bridge needs to be added first in the things file or through Paper UI.
|
||||
|
||||
For the Velbus Serial Bridge it is necessary to specify the serial port device used for communication.
|
||||
On Linux systems, this will usually be either `/dev/ttyS0`, `/dev/ttyUSB0` or `/dev/ttyACM0` (or a higher number than `0` if multiple devices are present).
|
||||
On Windows it will be `COM1`, `COM2`, etc.
|
||||
|
||||
In the things file, this might look e.g. like
|
||||
|
||||
```
|
||||
Bridge velbus:bridge:1 [ port="COM1" ]
|
||||
```
|
||||
|
||||
For the Velbus Network Bridge it is necessary to specify the IP Address or hostname and the port of the Velbus network server.
|
||||
This will usually be either the loopback address `127.0.0.1`, and port number.
|
||||
Or the specific IP of the machine `10.0.0.110` , and port number.
|
||||
|
||||
In the things file, this might look like
|
||||
|
||||
```
|
||||
Bridge velbus:networkbridge:1 "Velbus Network Bridge - Loopback" @ "Control" [ address="127.0.0.1", port=6000 ]
|
||||
```
|
||||
|
||||
Optionally, both the serial bridge and the network bridge can also update the realtime clock, date and daylight savings status of the Velbus modules.
|
||||
This is achieved by setting the Time Update Interval (in minutes) on the bridge, e.g.:
|
||||
|
||||
```
|
||||
Bridge velbus:bridge:1 [ port="COM1", timeUpdateInterval="360" ]
|
||||
```
|
||||
|
||||
The default time update interval is every 360 minutes.
|
||||
Setting the interval to 0 minutes or leaving it empty disables the update of the realtime clock, date and daylight savings status of the Velbus modules.
|
||||
|
||||
In case of a connection error, the bridges can also try to reconnect automatically.
|
||||
You can specify at which interval the bridge should try to reconnect by setting the Reconnection Interval (in seconds), e.g.:
|
||||
|
||||
```
|
||||
Bridge velbus:bridge:1 [ port="COM1", reconnectionInterval="15" ]
|
||||
```
|
||||
|
||||
The default reconnection interval is 15 seconds.
|
||||
|
||||
|
||||
For the other Velbus devices, the thing configuration has the following syntax:
|
||||
|
||||
```
|
||||
Thing velbus:<thing type>:<bridgeId>:<thingId> "Label" @ "Location" [CH1="Kitchen Light", CH2="Living Light"]
|
||||
```
|
||||
|
||||
or nested in the bridge configuration:
|
||||
|
||||
```
|
||||
<thing type> <thingId> "Label" @ "Location" [CH1="Kitchen Light", CH2="Living Light"]
|
||||
```
|
||||
|
||||
The following thing types are valid for configuration:
|
||||
|
||||
```
|
||||
vmb1bl, vmb1bls, vmb1dm, vmb1led, vmb1ry, vmb1ryno, vmb1rynos, vmb1rys, vmb1ts, vmb2bl, vmb2ble, vmb2pbn, vmb4an, vmb4dc, vmb4ry, vmb4ryld, vmb4ryno, vmb6in, vmb6pbn, vmb7in, vmb8ir, vmb8pb, vmb8pbu, vmbdme, vmbdmi, vmbdmir, vmbel1, vmbel2, vmbel4, vmbelo, vmbgp1, vmbgp2, vmbgp4, vmbgp4pir, vmbgpo, vmbgpod, vmbmeteo, vmbpirc, vmbpirm, vmbpiro
|
||||
```
|
||||
|
||||
`thingId` is the hexadecimal Velbus address of the thing.
|
||||
|
||||
`"Label"` is an optional label for the thing.
|
||||
|
||||
`@ "Location"` is optional, and represents the location of the thing.
|
||||
|
||||
`[CHx="..."]` is optional, and represents the name of channel x, e.g. CH1 specifies the name of channel 1.
|
||||
|
||||
For thing types with builtin sensors (e.g. temperature), the interval at which the sensors should be checked can be set by specifying the Refresh Interval, e.g.:
|
||||
|
||||
```
|
||||
Thing velbus:vmbelo:<bridgeId>:<thingId> [refresh="300"]
|
||||
```
|
||||
|
||||
The default refresh interval for the sensors is 300 seconds.
|
||||
Setting the refresh interval to 0 or leaving it empty will prevent the thing from periodically refreshing the sensor values.
|
||||
|
||||
The following thing types support a sensor refresh interval:
|
||||
|
||||
```
|
||||
vmb1ts, vmb4an, vmbel1, vmbel2, vmbel4, vmbelo, vmbgp1, vmbgp2, vmbgp4, vmbgp4pir, vmbgpo, vmbgpod, vmbmeteo, vmbpirc, vmbpirm, vmbpiro
|
||||
```
|
||||
|
||||
The `vmb7in` thing type also supports a refresh interval. For this thing type, the refresh interval is the interval at which the counter values should be refreshed.
|
||||
|
||||
For dimmers the speed (in seconds) at which the modules should dim from 0% to 100% can be set by specifying the Dimspeed, e.g.:
|
||||
|
||||
```
|
||||
Thing velbus:vmb4dc:<bridgeId>:<thingId> [dimspeed="5"]
|
||||
```
|
||||
|
||||
The following thing types support setting the dimspeed:
|
||||
|
||||
```
|
||||
vmb1dm, vmb1led, vmb4dc, vmbdme, vmbdmi, vmbdmir
|
||||
```
|
||||
|
||||
## Channels
|
||||
|
||||
For thing types `vmb1bl` and `vmb1bls` the supported channel is `CH1`.
|
||||
UpDown, StopMove and Percent command types are supported.
|
||||
|
||||
For thing types `vmb1dm`, `vmb1led`, `vmbdme`, `vmbdmi` and `vmbdmir` the supported channel is `CH1`.
|
||||
OnOff and Percent command types are supported.
|
||||
Sending an ON command will switch the dimmer to the value stored when last turning the dimmer off.
|
||||
|
||||
For thing type `vmb1ry` the supported channel is `CH1`.
|
||||
OnOff command types are supported.
|
||||
|
||||
For thing type `vmb4ry` 4 channels are available `CH1` ... `CH4`.
|
||||
OnOff command types are supported.
|
||||
|
||||
For thing types `vmb1ryno`, `vmb1rynos`, `vmb1rys`, `vmb4ryld` and `vmb4ryno` 5 channels are available `CH1` ... `CH5`.
|
||||
OnOff command types are supported.
|
||||
|
||||
The module `vmb1ts` has a number of channels to set the module's thermostat (`thermostat:currentTemperatureSetpoint`, `thermostat:heatingModeComfortTemperatureSetpoint`, `thermostat:heatingModeDayTemperatureSetpoint`, `thermostat:heatingModeNightTemperatureSetpoint`, `thermostat:heatingModeAntiFrostTemperatureSetpoint`, `thermostat:coolingModeComfortTemperatureSetpoint`, `thermostat:coolingModeDayTemperatureSetpoint`, `thermostat:coolingModeNightTemperatureSetpoint`, `thermostat:coolingModeSafeTemperatureSetpoint`, `operatingMode` and `thermostat:mode`) and thermostat trigger channels: `thermostat:heater`, `thermostat:boost`, `thermostat:pump`, `thermostat:cooler`, `thermostat:alarm1`, `thermostat:alarm2`, `thermostat:alarm3`, `thermostat:alarm4`.
|
||||
|
||||
For thing types `vmb2bl` and `vmb2ble` the supported channels are `CH1` and `CH2`. UpDown, StopMove and Percent command types are supported.
|
||||
|
||||
Thing type `vmb6in` has 6 trigger channels `input#CH1` ... `input#CH6`.
|
||||
|
||||
Thing type `vmb7in` has 8 trigger channels `input#CH1` ... `input#CH8`.
|
||||
|
||||
Thing types `vmb2pbn`, `vmb6pbn`, `vmb7in`, `vmb8ir`, `vmb8pb`, `vmb8pbu` and `vmbrfr8s` have 8 trigger channels (`input:CH1` ... `input:CH8`).
|
||||
Thing types `vmb2pbn`, `vmb6pbn`, `vmb7in`, `vmb8ir`, `vmb8pb`, `vmb8pbu` and `vmbrfr8s` have 8 trigger channels (`input:CH1` ... `input:CH8`).
|
||||
Thing types `vmb2pbn`, `vmb6pbn`, `vmb7in`, `vmb8pb`, `vmb8pbu` and `vmbrfr8s` also have and 2 channels to steer the button LED feedback (`feedback:CH1` and `feedback:CH2`).
|
||||
Additionally, the modules `vmb2pbn`, `vmb6pbn`, `vmb7in`, `vmb8pbu` and `vmbrfr8s` have a number of channels to set the module's alarms: `clockAlarm:clockAlarm1Enabled`, `clockAlarm:clockAlarm1Type`, `clockAlarm:clockAlarm1WakeupHour`, `clockAlarm:clockAlarm1WakeupMinute`, `clockAlarm:clockAlarm1BedtimeHour`, `clockAlarm:clockAlarm1BedtimeMinute`, `clockAlarm:clockAlarm2Enabled`, `clockAlarm:clockAlarm2Type`, `clockAlarm:clockAlarm2WakeupHour`, `clockAlarm:clockAlarm2WakeupMinute`, `clockAlarm:clockAlarm2BedtimeHour` and `clockAlarm:clockAlarm2BedtimeMinute`.
|
||||
|
||||
For thing type`vmb4an` 8 trigger channels are avaiable `input:CH1` ... `input:CH8`.
|
||||
These channels will be triggered by the module's alarms.
|
||||
Four pairs of channels are available to retrieve the module's analog inputs.
|
||||
Each pair has a channel to retrieve the raw analog value (`analogInput:CH9Raw` ... `analogInput:CH12Raw`) and a channel to retrieve the textual analog value (`analogInput:CH9` ... `analogInput:CH12`).
|
||||
Four channels are available to set the module's analog outputs `analogOutput:CH13` ... `analogOutput:CH16`.
|
||||
|
||||
For thing type `vmb4dc` 4 channels are available `CH1` ... `CH4`.
|
||||
OnOff and Percent command types are supported.
|
||||
Sending an ON command will switch the dimmer to the value stored when last turning the dimmer off.
|
||||
|
||||
For thing type `vmb4ry` 4 channels are available `CH1` ... `CH4`.
|
||||
OnOff command types are supported.
|
||||
|
||||
Thing types `vmbel1`, `vmbel2`, `vmbel4`, `vmbgp1`, `vmbgp2`, `vmbgp4`, `vmbgp4pir` and `vmbpiro` have 8 trigger channels `input:CH1` ... `input:CH8` and one temperature channel `input:CH9`.
|
||||
The thing types `vmbel1` and `vmbgp1` have one channel to steer the button LED feedback `feedback:CH1`.
|
||||
The thing types `vmbel2` and `vmbgp2` have two channels to steer the button LED feedback `feedback:CH1` and `feedback:CH2`.
|
||||
The thing types `vmbel4`, `vmbgp4` and `vmbgp4pir` have four channels to steer the button LED feedback `feedback:CH1` ... `feedback:CH4`.
|
||||
The thing type `vmbpiro` has a channel `input:LIGHT` indicating the illuminance.
|
||||
Thing types `vmbel1`, `vmbel2`, `vmbel4`, `vmbgp1`, `vmbgp2`, `vmbgp4` and `vmbgp4pir` have a number of channels to set the module's alarms: `clockAlarm:clockAlarm1Enabled`, `clockAlarm:clockAlarm1Type`, `clockAlarm:clockAlarm1WakeupHour`, `clockAlarm:clockAlarm1WakeupMinute`, `clockAlarm:clockAlarm1BedtimeHour`, `clockAlarm:clockAlarm1BedtimeMinute`, `clockAlarm:clockAlarm2Enabled`, `clockAlarm:clockAlarm2Type`, `clockAlarm:clockAlarm2WakeupHour`, `clockAlarm:clockAlarm2WakeupMinute`, `clockAlarm:clockAlarm2BedtimeHour` and `clockAlarm:clockAlarm2BedtimeMinute`.
|
||||
Thing types `vmbel1`, `vmbel2`, `vmbel4`, `vmbgp1`, `vmbgp2`, `vmbgp4` and `vmbgp4pir` also have a number of channels to set the module's thermostat (`thermostat:currentTemperatureSetpoint`, `thermostat:heatingModeComfortTemperatureSetpoint`, `thermostat:heatingModeDayTemperatureSetpoint`, `thermostat:heatingModeNightTemperatureSetpoint`, `thermostat:heatingModeAntiFrostTemperatureSetpoint`, `thermostat:coolingModeComfortTemperatureSetpoint`, `thermostat:coolingModeDayTemperatureSetpoint`, `thermostat:coolingModeNightTemperatureSetpoint`, `thermostat:coolingModeSafeTemperatureSetpoint`, `operatingMode` and `thermostat:mode`) and thermostat trigger channels: `thermostat:heater`, `thermostat:boost`, `thermostat:pump`, `thermostat:cooler`, `thermostat:alarm1`, `thermostat:alarm2`, `thermostat:alarm3`, `thermostat:alarm4`.
|
||||
|
||||
Thing types `vmbelo`, `vmbgpo` and `vmbgpod` have 32 trigger channels `input:CH1` ... `input:CH32` and one temperature channel `input:CH33`.
|
||||
They have have 32 channels to steer the button LED feedback `feedback:CH1` ... `feedback:CH32`.
|
||||
They have a number of channels to set the module's alarms: `clockAlarm:clockAlarm1Enabled`, `clockAlarm:clockAlarm1Type`, `clockAlarm:clockAlarm1WakeupHour`, `clockAlarm:clockAlarm1WakeupMinute`, `clockAlarm:clockAlarm1BedtimeHour`, `clockAlarm:clockAlarm1BedtimeMinute`, `clockAlarm:clockAlarm2Enabled`, `clockAlarm:clockAlarm2Type`, `clockAlarm:clockAlarm2WakeupHour`, `clockAlarm:clockAlarm2WakeupMinute`, `clockAlarm:clockAlarm2BedtimeHour` and `clockAlarm:clockAlarm2BedtimeMinute`.
|
||||
They have a number of channels to set the module's thermostat thermostat (`thermostat:currentTemperatureSetpoint`, `thermostat:heatingModeComfortTemperatureSetpoint`, `thermostat:heatingModeDayTemperatureSetpoint`, `thermostat:heatingModeNightTemperatureSetpoint`, `thermostat:heatingModeAntiFrostTemperatureSetpoint`, `thermostat:coolingModeComfortTemperatureSetpoint`, `thermostat:coolingModeDayTemperatureSetpoint`, `thermostat:coolingModeNightTemperatureSetpoint`, `thermostat:coolingModeSafeTemperatureSetpoint`, `operatingMode` and `thermostat:mode`) and thermostat trigger channels: `thermostat:heater`, `thermostat:boost`, `thermostat:pump`, `thermostat:cooler`, `thermostat:alarm1`, `thermostat:alarm2`, `thermostat:alarm3`, `thermostat:alarm4`.
|
||||
They also have two channels to control the module's display `oledDisplay:MEMO` and `oledDisplay:SCREENSAVER`.
|
||||
|
||||
Thing type `vmbmeteo`has 8 trigger channels (`input:CH1` ... `input:CH8`). These channels will be triggered by the module's alarms.
|
||||
It has a number of channels to set the module's alarms: `clockAlarm:clockAlarm1Enabled`, `clockAlarm:clockAlarm1Type`, `clockAlarm:clockAlarm1WakeupHour`, `clockAlarm:clockAlarm1WakeupMinute`, `clockAlarm:clockAlarm1BedtimeHour`, `clockAlarm:clockAlarm1BedtimeMinute`, `clockAlarm:clockAlarm2Enabled`, `clockAlarm:clockAlarm2Type`, `clockAlarm:clockAlarm2WakeupHour`, `clockAlarm:clockAlarm2WakeupMinute`, `clockAlarm:clockAlarm2BedtimeHour` and `clockAlarm:clockAlarm2BedtimeMinute`.
|
||||
It also has a number of channels to read out the weather station's sensors: `weatherStation:temperature`, `weatherStation:rainfall`, `weatherStation:illuminance` and `weatherStation:windspeed`.
|
||||
|
||||
Thing types `vmbpirc` and `vmbpirm` have 7 trigger channels `input:CH1` ... `input:CH7`.
|
||||
Additionally, these modules have a number of channels to set the module's alarms: `clockAlarm:clockAlarm1Enabled`, `clockAlarm:clockAlarm1Type`, `clockAlarm:clockAlarm1WakeupHour`, `clockAlarm:clockAlarm1WakeupMinute`, `clockAlarm:clockAlarm1BedtimeHour`, `clockAlarm:clockAlarm1BedtimeMinute`, `clockAlarm:clockAlarm2Enabled`, `clockAlarm:clockAlarm2Type`, `clockAlarm:clockAlarm2WakeupHour`, `clockAlarm:clockAlarm2WakeupMinute`, `clockAlarm:clockAlarm2BedtimeHour` and `clockAlarm:clockAlarm2BedtimeMinute`.
|
||||
|
||||
The trigger channels can be used as a trigger to rules. The event message can be `PRESSED`, `RELEASED`or `LONG_PRESSED`.
|
||||
|
||||
## Full Example
|
||||
|
||||
.things:
|
||||
|
||||
```
|
||||
Bridge velbus:bridge:1 [ port="COM1"] {
|
||||
vmb2ble 01
|
||||
vmb2pbn 02
|
||||
vmb6pbn 03
|
||||
vmb8pbu 04
|
||||
vmb7in 05
|
||||
vmb4ryld 06
|
||||
vmb4dc 07
|
||||
vmbgp1 08
|
||||
vmbgp2 09
|
||||
vmbgp4 0A
|
||||
vmbgp4pir 0B
|
||||
vmbgpo 0C
|
||||
vmbgpod 0D
|
||||
vmbpiro 0E
|
||||
}
|
||||
```
|
||||
|
||||
.items:
|
||||
|
||||
```
|
||||
Switch LivingRoom {channel="velbus:vmb4ryld:1:06:CH1"} # Switch for onOff type action
|
||||
Dimmer TVRoom {channel="velbus:vmb4dc:1:07:CH2"} # Changing brightness dimmer type action
|
||||
Rollershutter Kitchen {channel="velbus:vmb2ble:1:01"} # Controlling rollershutter or blind type action
|
||||
|
||||
Number Temperature_LivingRoom "Temperature [%.1f °C]" <temperature> channel="velbus:vmbgp1:1:08:CH09"}
|
||||
Number Temperature_Corridor "Temperature [%.1f °C]" <temperature> channel="velbus:vmbgpo:1:0C:CH33"}
|
||||
Number Temperature_Outside "Temperature [%.1f °C]" <temperature> channel="velbus:vmbpiro:1:0E:CH09"}
|
||||
```
|
||||
|
||||
.sitemap:
|
||||
|
||||
```
|
||||
Switch item=LivingRoom
|
||||
Slider item=TVRoom
|
||||
Switch item=TVRoom # allows switching dimmer item off or on
|
||||
Rollershutter item=Kitchen
|
||||
```
|
||||
|
||||
Example trigger rule:
|
||||
|
||||
```
|
||||
rule "example trigger rule"
|
||||
when
|
||||
Channel 'velbus:vmb7in:1:05:CH5' triggered PRESSED
|
||||
then
|
||||
var message = receivedEvent.getEvent()
|
||||
logInfo("velbusTriggerExample", "Message: {}", message)
|
||||
...
|
||||
end
|
||||
```
|
||||
17
bundles/org.openhab.binding.velbus/pom.xml
Normal file
17
bundles/org.openhab.binding.velbus/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.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.velbus</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: Velbus Binding</name>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.velbus-${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-velbus" description="Velbus Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<feature>openhab-transport-serial</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.velbus/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,224 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link VelbusBindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "velbus";
|
||||
|
||||
// bridges
|
||||
public static final ThingTypeUID BRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, "bridge");
|
||||
public static final ThingTypeUID NETWORK_BRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, "networkbridge");
|
||||
|
||||
// generic thing types
|
||||
public static final ThingTypeUID THING_TYPE_VMB1BL = new ThingTypeUID(BINDING_ID, "vmb1bl");
|
||||
public static final ThingTypeUID THING_TYPE_VMB1BLS = new ThingTypeUID(BINDING_ID, "vmb1bls");
|
||||
public static final ThingTypeUID THING_TYPE_VMB1DM = new ThingTypeUID(BINDING_ID, "vmb1dm");
|
||||
public static final ThingTypeUID THING_TYPE_VMB1LED = new ThingTypeUID(BINDING_ID, "vmb1led");
|
||||
public static final ThingTypeUID THING_TYPE_VMB1RY = new ThingTypeUID(BINDING_ID, "vmb1ry");
|
||||
public static final ThingTypeUID THING_TYPE_VMB1RYNO = new ThingTypeUID(BINDING_ID, "vmb1ryno");
|
||||
public static final ThingTypeUID THING_TYPE_VMB1RYNOS = new ThingTypeUID(BINDING_ID, "vmb1rynos");
|
||||
public static final ThingTypeUID THING_TYPE_VMB1RYS = new ThingTypeUID(BINDING_ID, "vmb1rys");
|
||||
public static final ThingTypeUID THING_TYPE_VMB1TS = new ThingTypeUID(BINDING_ID, "vmb1ts");
|
||||
public static final ThingTypeUID THING_TYPE_VMB2BL = new ThingTypeUID(BINDING_ID, "vmb2bl");
|
||||
public static final ThingTypeUID THING_TYPE_VMB2BLE = new ThingTypeUID(BINDING_ID, "vmb2ble");
|
||||
public static final ThingTypeUID THING_TYPE_VMB2PBN = new ThingTypeUID(BINDING_ID, "vmb2pbn");
|
||||
public static final ThingTypeUID THING_TYPE_VMB4AN = new ThingTypeUID(BINDING_ID, "vmb4an");
|
||||
public static final ThingTypeUID THING_TYPE_VMB4DC = new ThingTypeUID(BINDING_ID, "vmb4dc");
|
||||
public static final ThingTypeUID THING_TYPE_VMB4RY = new ThingTypeUID(BINDING_ID, "vmb4ry");
|
||||
public static final ThingTypeUID THING_TYPE_VMB4RYLD = new ThingTypeUID(BINDING_ID, "vmb4ryld");
|
||||
public static final ThingTypeUID THING_TYPE_VMB4RYNO = new ThingTypeUID(BINDING_ID, "vmb4ryno");
|
||||
public static final ThingTypeUID THING_TYPE_VMB6IN = new ThingTypeUID(BINDING_ID, "vmb6in");
|
||||
public static final ThingTypeUID THING_TYPE_VMB6PBN = new ThingTypeUID(BINDING_ID, "vmb6pbn");
|
||||
public static final ThingTypeUID THING_TYPE_VMB7IN = new ThingTypeUID(BINDING_ID, "vmb7in");
|
||||
public static final ThingTypeUID THING_TYPE_VMB8IR = new ThingTypeUID(BINDING_ID, "vmb8ir");
|
||||
public static final ThingTypeUID THING_TYPE_VMB8PB = new ThingTypeUID(BINDING_ID, "vmb8pb");
|
||||
public static final ThingTypeUID THING_TYPE_VMB8PBU = new ThingTypeUID(BINDING_ID, "vmb8pbu");
|
||||
public static final ThingTypeUID THING_TYPE_VMBDME = new ThingTypeUID(BINDING_ID, "vmbdme");
|
||||
public static final ThingTypeUID THING_TYPE_VMBDMI = new ThingTypeUID(BINDING_ID, "vmbdmi");
|
||||
public static final ThingTypeUID THING_TYPE_VMBDMIR = new ThingTypeUID(BINDING_ID, "vmbdmir");
|
||||
public static final ThingTypeUID THING_TYPE_VMBEL1 = new ThingTypeUID(BINDING_ID, "vmbel1");
|
||||
public static final ThingTypeUID THING_TYPE_VMBEL2 = new ThingTypeUID(BINDING_ID, "vmbel2");
|
||||
public static final ThingTypeUID THING_TYPE_VMBEL4 = new ThingTypeUID(BINDING_ID, "vmbel4");
|
||||
public static final ThingTypeUID THING_TYPE_VMBELO = new ThingTypeUID(BINDING_ID, "vmbelo");
|
||||
public static final ThingTypeUID THING_TYPE_VMBGP1 = new ThingTypeUID(BINDING_ID, "vmbgp1");
|
||||
public static final ThingTypeUID THING_TYPE_VMBGP1_2 = new ThingTypeUID(BINDING_ID, "vmbgp1-2");
|
||||
public static final ThingTypeUID THING_TYPE_VMBGP2 = new ThingTypeUID(BINDING_ID, "vmbgp2");
|
||||
public static final ThingTypeUID THING_TYPE_VMBGP2_2 = new ThingTypeUID(BINDING_ID, "vmbgp2-2");
|
||||
public static final ThingTypeUID THING_TYPE_VMBGP4 = new ThingTypeUID(BINDING_ID, "vmbgp4");
|
||||
public static final ThingTypeUID THING_TYPE_VMBGP4_2 = new ThingTypeUID(BINDING_ID, "vmbgp4-2");
|
||||
public static final ThingTypeUID THING_TYPE_VMBGP4PIR = new ThingTypeUID(BINDING_ID, "vmbgp4pir");
|
||||
public static final ThingTypeUID THING_TYPE_VMBGP4PIR_2 = new ThingTypeUID(BINDING_ID, "vmbgp4pir-2");
|
||||
public static final ThingTypeUID THING_TYPE_VMBGPO = new ThingTypeUID(BINDING_ID, "vmbgpo");
|
||||
public static final ThingTypeUID THING_TYPE_VMBGPOD = new ThingTypeUID(BINDING_ID, "vmbgpod");
|
||||
public static final ThingTypeUID THING_TYPE_VMBGPOD_2 = new ThingTypeUID(BINDING_ID, "vmbgpod-2");
|
||||
public static final ThingTypeUID THING_TYPE_VMBMETEO = new ThingTypeUID(BINDING_ID, "vmbmeteo");
|
||||
public static final ThingTypeUID THING_TYPE_VMBPIRC = new ThingTypeUID(BINDING_ID, "vmbpirc");
|
||||
public static final ThingTypeUID THING_TYPE_VMBPIRM = new ThingTypeUID(BINDING_ID, "vmbpirm");
|
||||
public static final ThingTypeUID THING_TYPE_VMBPIRO = new ThingTypeUID(BINDING_ID, "vmbpiro");
|
||||
public static final ThingTypeUID THING_TYPE_VMBRFR8S = new ThingTypeUID(BINDING_ID, "vmbrfr8s");
|
||||
|
||||
// thing type sets
|
||||
public static final Set<ThingTypeUID> BRIDGE_THING_TYPES_UIDS = Collections
|
||||
.unmodifiableSet(new HashSet<>(Arrays.asList(BRIDGE_THING_TYPE, NETWORK_BRIDGE_THING_TYPE)));
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(
|
||||
new HashSet<>(Arrays.asList(THING_TYPE_VMB1BL, THING_TYPE_VMB1BLS, THING_TYPE_VMB1DM, THING_TYPE_VMB1LED,
|
||||
THING_TYPE_VMB1RY, THING_TYPE_VMB1RYNO, THING_TYPE_VMB1RYNOS, THING_TYPE_VMB1RYS, THING_TYPE_VMB1TS,
|
||||
THING_TYPE_VMB2BL, THING_TYPE_VMB2BLE, THING_TYPE_VMB2PBN, THING_TYPE_VMB4AN, THING_TYPE_VMB4DC,
|
||||
THING_TYPE_VMB4RY, THING_TYPE_VMB4RYLD, THING_TYPE_VMB4RYNO, THING_TYPE_VMB6IN, THING_TYPE_VMB6PBN,
|
||||
THING_TYPE_VMB7IN, THING_TYPE_VMB8IR, THING_TYPE_VMB8PB, THING_TYPE_VMB8PBU, THING_TYPE_VMBDME,
|
||||
THING_TYPE_VMBDMI, THING_TYPE_VMBDMIR, THING_TYPE_VMBEL1, THING_TYPE_VMBEL2, THING_TYPE_VMBEL4,
|
||||
THING_TYPE_VMBELO, THING_TYPE_VMBGP1, THING_TYPE_VMBGP1_2, THING_TYPE_VMBGP2, THING_TYPE_VMBGP2_2,
|
||||
THING_TYPE_VMBGP4, THING_TYPE_VMBGP4_2, THING_TYPE_VMBGP4PIR, THING_TYPE_VMBGP4PIR_2,
|
||||
THING_TYPE_VMBGPO, THING_TYPE_VMBGPOD, THING_TYPE_VMBGPOD_2, THING_TYPE_VMBMETEO,
|
||||
THING_TYPE_VMBPIRC, THING_TYPE_VMBPIRM, THING_TYPE_VMBPIRO, THING_TYPE_VMBRFR8S)));
|
||||
|
||||
// Velbus module types
|
||||
public static final byte MODULE_TYPE_VMB8PB = 0x01;
|
||||
public static final byte MODULE_TYPE_VMB1RY = 0x02;
|
||||
public static final byte MODULE_TYPE_VMB1BL = 0x03;
|
||||
public static final byte MODULE_TYPE_VMB6IN = 0x05;
|
||||
public static final byte MODULE_TYPE_VMB1DM = 0x07;
|
||||
public static final byte MODULE_TYPE_VMB4RY = 0x08;
|
||||
public static final byte MODULE_TYPE_VMB2BL = 0x09;
|
||||
public static final byte MODULE_TYPE_VMB8IR = 0x0A;
|
||||
public static final byte MODULE_TYPE_VMB1TS = 0x0C;
|
||||
public static final byte MODULE_TYPE_VMB1LED = 0x0F;
|
||||
public static final byte MODULE_TYPE_VMB4RYLD = 0x10;
|
||||
public static final byte MODULE_TYPE_VMB4RYNO = 0x11;
|
||||
public static final byte MODULE_TYPE_VMB4DC = 0x12;
|
||||
public static final byte MODULE_TYPE_VMBDME = 0x14;
|
||||
public static final byte MODULE_TYPE_VMBDMI = 0x15;
|
||||
public static final byte MODULE_TYPE_VMB8PBU = 0x16;
|
||||
public static final byte MODULE_TYPE_VMB6PBN = 0x17;
|
||||
public static final byte MODULE_TYPE_VMB2PBN = 0x18;
|
||||
public static final byte MODULE_TYPE_VMB1RYNO = 0x1B;
|
||||
public static final byte MODULE_TYPE_VMB2BLE = 0x1D;
|
||||
public static final byte MODULE_TYPE_VMBGP1 = 0x1E;
|
||||
public static final byte MODULE_TYPE_VMBGP2 = 0x1F;
|
||||
public static final byte MODULE_TYPE_VMBGP4 = 0x20;
|
||||
public static final byte MODULE_TYPE_VMBGPO = 0x21;
|
||||
public static final byte MODULE_TYPE_VMB7IN = 0x22;
|
||||
public static final byte MODULE_TYPE_VMBGPOD = 0x28;
|
||||
public static final byte MODULE_TYPE_VMB1RYNOS = 0x29;
|
||||
public static final byte MODULE_TYPE_VMBPIRM = 0x2A;
|
||||
public static final byte MODULE_TYPE_VMBPIRC = 0x2B;
|
||||
public static final byte MODULE_TYPE_VMBPIRO = 0x2C;
|
||||
public static final byte MODULE_TYPE_VMBGP4PIR = 0x2D;
|
||||
public static final byte MODULE_TYPE_VMB1BLS = 0x2E;
|
||||
public static final byte MODULE_TYPE_VMBDMIR = 0x2F;
|
||||
public static final byte MODULE_TYPE_VMBRFR8S = 0x30;
|
||||
public static final byte MODULE_TYPE_VMBMETEO = 0x31;
|
||||
public static final byte MODULE_TYPE_VMB4AN = 0x32;
|
||||
public static final byte MODULE_TYPE_VMBEL1 = 0x34;
|
||||
public static final byte MODULE_TYPE_VMBEL2 = 0x35;
|
||||
public static final byte MODULE_TYPE_VMBEL4 = 0x36;
|
||||
public static final byte MODULE_TYPE_VMBELO = 0x37;
|
||||
public static final byte MODULE_TYPE_VMBGP1_2 = 0x3A;
|
||||
public static final byte MODULE_TYPE_VMBGP2_2 = 0x3B;
|
||||
public static final byte MODULE_TYPE_VMBGP4_2 = 0x3C;
|
||||
public static final byte MODULE_TYPE_VMBGPOD_2 = 0x3D;
|
||||
public static final byte MODULE_TYPE_VMBGP4PIR_2 = 0x3E;
|
||||
public static final byte MODULE_TYPE_VMB1RYS = 0x41;
|
||||
|
||||
// Velbus commands
|
||||
public static final byte COMMAND_PUSH_BUTTON_STATUS = 0x00;
|
||||
public static final byte COMMAND_SWITCH_RELAY_OFF = 0x01;
|
||||
public static final byte COMMAND_SWITCH_RELAY_ON = 0x02;
|
||||
public static final byte COMMAND_SWITCH_BLIND_OFF = 0x04;
|
||||
public static final byte COMMAND_BLIND_UP = 0x05;
|
||||
public static final byte COMMAND_BLIND_DOWN = 0x06;
|
||||
public static final byte COMMAND_SET_VALUE = 0x07;
|
||||
public static final byte COMMAND_SLIDER_STATUS = 0x0F;
|
||||
public static final byte COMMAND_RESTORE_LAST_DIMVALUE = 0x11;
|
||||
public static final byte COMMAND_BLIND_POS = 0x1C;
|
||||
public static final byte COMMAND_SENSOR_RAW_DATA = (byte) 0xA9;
|
||||
public static final byte COMMAND_LIGHT_VALUE_REQUEST = (byte) 0xAA;
|
||||
public static final byte COMMAND_TEXT = (byte) 0xAC;
|
||||
public static final byte COMMAND_DAYLIGHT_SAVING_STATUS = (byte) 0xAF;
|
||||
public static final byte COMMAND_SUBTYPE = (byte) 0xB0;
|
||||
public static final byte COMMAND_SET_REALTIME_DATE = (byte) 0xB7;
|
||||
public static final byte COMMAND_DIMMERCONTROLLER_STATUS = (byte) 0xB8;
|
||||
public static final byte COMMAND_TEMP_SENSOR_SETTINGS_PART4 = (byte) 0xB9;
|
||||
public static final byte COMMAND_COUNTER_STATUS_REQUEST = (byte) 0xBD;
|
||||
public static final byte COMMAND_COUNTER_STATUS = (byte) 0xBE;
|
||||
public static final byte COMMAND_SET_ALARM_CLOCK = (byte) 0xC3;
|
||||
public static final byte COMMAND_TEMP_SENSOR_SETTINGS_PART3 = (byte) 0xC6;
|
||||
public static final byte COMMAND_READ_MEMORY_BLOCK = (byte) 0xC9;
|
||||
public static final byte COMMAND_MEMORY_DATA_BLOCK = (byte) 0xCC;
|
||||
public static final byte COMMAND_SET_REALTIME_CLOCK = (byte) 0xD8;
|
||||
public static final byte COMMAND_SWITCH_TO_COMFORT_MODE = (byte) 0xDB;
|
||||
public static final byte COMMAND_SWITCH_TO_DAY_MODE = (byte) 0xDC;
|
||||
public static final byte COMMAND_SWITCH_TO_NIGHT_MODE = (byte) 0xDD;
|
||||
public static final byte COMMAND_SWITCH_TO_SAFE_MODE = (byte) 0xDE;
|
||||
public static final byte COMMAND_SET_COOLING_MODE = (byte) 0xDF;
|
||||
public static final byte COMMAND_SET_HEATING_MODE = (byte) 0xE0;
|
||||
public static final byte COMMAND_SET_TEMP = (byte) 0xE4;
|
||||
public static final byte COMMAND_SENSOR_READOUT_REQUEST = (byte) 0xE5;
|
||||
public static final byte COMMAND_SENSOR_TEMPERATURE = (byte) 0xE6;
|
||||
public static final byte COMMAND_TEMP_SENSOR_SETTINGS_REQUEST = (byte) 0xE7;
|
||||
public static final byte COMMAND_TEMP_SENSOR_SETTINGS_PART1 = (byte) 0xE8;
|
||||
public static final byte COMMAND_TEMP_SENSOR_SETTINGS_PART2 = (byte) 0xE9;
|
||||
public static final byte COMMAND_TEMP_SENSOR_STATUS = (byte) 0xEA;
|
||||
public static final byte COMMAND_BLIND_STATUS = (byte) 0xEC;
|
||||
public static final byte COMMAND_MODULE_STATUS = (byte) 0xED;
|
||||
public static final byte COMMAND_DIMMER_STATUS = (byte) 0xEE;
|
||||
public static final byte COMMAND_MODULE_NAME_REQUEST = (byte) 0xEF;
|
||||
public static final byte COMMAND_MODULE_NAME_PART1 = (byte) 0xF0;
|
||||
public static final byte COMMAND_MODULE_NAME_PART2 = (byte) 0xF1;
|
||||
public static final byte COMMAND_MODULE_NAME_PART3 = (byte) 0xF2;
|
||||
public static final byte COMMAND_CLEAR_LED = (byte) 0xF5;
|
||||
public static final byte COMMAND_SET_LED = (byte) 0xF6;
|
||||
public static final byte COMMAND_SLOW_BLINK_LED = (byte) 0xF7;
|
||||
public static final byte COMMAND_FAST_BLINK_LED = (byte) 0xF8;
|
||||
public static final byte COMMAND_VERY_FAST_BLINK_LED = (byte) 0xF9;
|
||||
public static final byte COMMAND_STATUS_REQUEST = (byte) 0xFA;
|
||||
public static final byte COMMAND_RELAY_STATUS = (byte) 0xFB;
|
||||
public static final byte COMMAND_WRITE_DATA_TO_MEMORY = (byte) 0xFC;
|
||||
public static final byte COMMAND_READ_DATA_FROM_MEMORY = (byte) 0xFD;
|
||||
public static final byte COMMAND_MEMORY_DATA = (byte) 0xFE;
|
||||
public static final byte COMMAND_MODULE_TYPE = (byte) 0xFF;
|
||||
public static final byte ALL_CHANNELS = (byte) 0xFF;
|
||||
|
||||
// Module properties
|
||||
public static final String PORT = "port";
|
||||
public static final String ADDRESS = "address";
|
||||
public static final String REFRESH_INTERVAL = "refresh";
|
||||
public static final String COUNTER1_PULSE_MULTIPLIER = "COUNTER1_PULSE_MULTIPLIER";
|
||||
public static final String COUNTER2_PULSE_MULTIPLIER = "COUNTER2_PULSE_MULTIPLIER";
|
||||
public static final String COUNTER3_PULSE_MULTIPLIER = "COUNTER3_PULSE_MULTIPLIER";
|
||||
public static final String COUNTER4_PULSE_MULTIPLIER = "COUNTER4_PULSE_MULTIPLIER";
|
||||
public static final String RECONNECTION_INTERVAL = "reconnectionInterval";
|
||||
public static final String TIME_UPDATE_INTERVAL = "timeUpdateInterval";
|
||||
public static final String MODULE_SERIAL_NUMBER = "serial number";
|
||||
public static final String MODULE_MEMORY_MAP_VERSION = "memory map version";
|
||||
public static final String MODULE_BUILD = "build";
|
||||
public static final String CHANNEL = "CH";
|
||||
public static final String SUB_ADDRESS = "subaddress";
|
||||
public static final String DIMSPEED = "dimspeed";
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusChannelIdentifier} represents a class with properties that uniquely identify a channel.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusChannelIdentifier {
|
||||
|
||||
private byte address;
|
||||
private byte channel;
|
||||
|
||||
public VelbusChannelIdentifier(byte address, byte channel) {
|
||||
this.address = address;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public byte getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public byte getChannelByte() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public int getChannelNumberFromBitNumber() {
|
||||
int position = 0;
|
||||
byte remainingChannelBits = channel;
|
||||
while (remainingChannelBits != 0) {
|
||||
position++;
|
||||
if ((remainingChannelBits & ((byte) 1)) != 0) {
|
||||
return position;
|
||||
}
|
||||
remainingChannelBits = (byte) (remainingChannelBits >>> 1);
|
||||
}
|
||||
return position;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusClockAlarm} represents a class that contains the state representation of a velbus clock alarm.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusClockAlarm {
|
||||
private boolean enabled;
|
||||
private boolean isLocal;
|
||||
private byte wakeupHour;
|
||||
private byte wakeupMinute;
|
||||
private byte bedtimeHour;
|
||||
private byte bedtimeMinute;
|
||||
|
||||
public VelbusClockAlarm() {
|
||||
this.enabled = true;
|
||||
this.isLocal = true;
|
||||
this.wakeupHour = 7;
|
||||
this.wakeupMinute = 0;
|
||||
this.bedtimeHour = 23;
|
||||
this.bedtimeMinute = 0;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public boolean isLocal() {
|
||||
return this.isLocal;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean value) {
|
||||
this.enabled = value;
|
||||
}
|
||||
|
||||
public void setLocal(boolean value) {
|
||||
this.isLocal = value;
|
||||
}
|
||||
|
||||
public byte getWakeupHour() {
|
||||
return this.wakeupHour;
|
||||
}
|
||||
|
||||
public void setWakeupHour(byte value) {
|
||||
this.wakeupHour = value;
|
||||
}
|
||||
|
||||
public byte getWakeupMinute() {
|
||||
return this.wakeupMinute;
|
||||
}
|
||||
|
||||
public void setWakeupMinute(byte value) {
|
||||
this.wakeupMinute = value;
|
||||
}
|
||||
|
||||
public byte getBedtimeHour() {
|
||||
return this.bedtimeHour;
|
||||
}
|
||||
|
||||
public void setBedtimeHour(byte value) {
|
||||
this.bedtimeHour = value;
|
||||
}
|
||||
|
||||
public byte getBedtimeMinute() {
|
||||
return this.bedtimeMinute;
|
||||
}
|
||||
|
||||
public void setBedtimeMinute(byte value) {
|
||||
this.bedtimeMinute = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusClockAlarmConfiguration} represents a class that contains the configuration of a velbus clock alarm.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusClockAlarmConfiguration {
|
||||
private VelbusClockAlarm alarmClock1;
|
||||
private VelbusClockAlarm alarmClock2;
|
||||
|
||||
public VelbusClockAlarmConfiguration() {
|
||||
this.alarmClock1 = new VelbusClockAlarm();
|
||||
this.alarmClock2 = new VelbusClockAlarm();
|
||||
}
|
||||
|
||||
public VelbusClockAlarm getAlarmClock1() {
|
||||
return alarmClock1;
|
||||
}
|
||||
|
||||
public VelbusClockAlarm getAlarmClock2() {
|
||||
return alarmClock2;
|
||||
}
|
||||
|
||||
public VelbusClockAlarm getAlarmClock(int alarmNumber) {
|
||||
if (alarmNumber == 1) {
|
||||
return getAlarmClock1();
|
||||
} else if (alarmNumber == 2) {
|
||||
return getAlarmClock2();
|
||||
} else {
|
||||
throw new IllegalArgumentException("The alarm clock '" + alarmNumber + "' does not exist.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusFirstGenerationDeviceModuleAddress} represents the address Velbus
|
||||
* module of the 1st generation.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusFirstGenerationDeviceModuleAddress extends VelbusModuleAddress {
|
||||
|
||||
public VelbusFirstGenerationDeviceModuleAddress(byte address) {
|
||||
super(address, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChannelNumber(VelbusChannelIdentifier velbusChannelIdentifier) {
|
||||
byte channelByte = velbusChannelIdentifier.getChannelByte();
|
||||
if (channelByte == (byte) 0x03) {
|
||||
return 1;
|
||||
} else if (channelByte == (byte) 0x0C) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("The byte '" + channelByte
|
||||
+ "' does not represent a valid channel on the first generation device with address '"
|
||||
+ velbusChannelIdentifier.getAddress() + "'.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public VelbusChannelIdentifier getChannelIdentifier(int channelIndex) {
|
||||
if (channelIndex == 0) {
|
||||
return new VelbusChannelIdentifier(getAddress(), (byte) 0x03);
|
||||
} else if (channelIndex == 1) {
|
||||
return new VelbusChannelIdentifier(getAddress(), (byte) 0x0C);
|
||||
} else {
|
||||
throw new IllegalArgumentException("The channel index '" + channelIndex
|
||||
+ "' is not valid for the first generation device on the address '" + getAddress() + "'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusBlindsHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusBridgeHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusDimmerHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusNetworkBridgeHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusRelayHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusSensorHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusSensorWithAlarmClockHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusSerialBridgeHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusVMB1TSHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusVMB4ANHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusVMB7INHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusVMBELHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusVMBELOHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusVMBGPHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusVMBGPOHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusVMBMeteoHandler;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusVMBPIROHandler;
|
||||
import org.openhab.core.io.transport.serial.SerialPortManager;
|
||||
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.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* The {@link VelbusHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.velbus")
|
||||
public class VelbusHandlerFactory extends BaseThingHandlerFactory {
|
||||
private final SerialPortManager serialPortManager;
|
||||
|
||||
@Activate
|
||||
public VelbusHandlerFactory(final @Reference SerialPortManager serialPortManager) {
|
||||
this.serialPortManager = serialPortManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return BRIDGE_THING_TYPES_UIDS.contains(thingTypeUID) || SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
ThingHandler thingHandler = null;
|
||||
|
||||
if (BRIDGE_THING_TYPES_UIDS.contains(thingTypeUID)) {
|
||||
VelbusBridgeHandler velbusBridgeHandler = thingTypeUID.equals(NETWORK_BRIDGE_THING_TYPE)
|
||||
? new VelbusNetworkBridgeHandler((Bridge) thing)
|
||||
: new VelbusSerialBridgeHandler((Bridge) thing, serialPortManager);
|
||||
thingHandler = velbusBridgeHandler;
|
||||
} else if (VelbusRelayHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
thingHandler = new VelbusRelayHandler(thing);
|
||||
} else if (VelbusDimmerHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
thingHandler = new VelbusDimmerHandler(thing);
|
||||
} else if (VelbusBlindsHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
thingHandler = new VelbusBlindsHandler(thing);
|
||||
} else if (VelbusSensorHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
thingHandler = new VelbusSensorHandler(thing);
|
||||
} else if (VelbusSensorWithAlarmClockHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
thingHandler = new VelbusSensorWithAlarmClockHandler(thing);
|
||||
} else if (VelbusVMBMeteoHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
thingHandler = new VelbusVMBMeteoHandler(thing);
|
||||
} else if (VelbusVMBGPHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
thingHandler = new VelbusVMBGPHandler(thing);
|
||||
} else if (VelbusVMBGPOHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
thingHandler = new VelbusVMBGPOHandler(thing);
|
||||
} else if (VelbusVMBPIROHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
thingHandler = new VelbusVMBPIROHandler(thing);
|
||||
} else if (VelbusVMB7INHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
thingHandler = new VelbusVMB7INHandler(thing);
|
||||
} else if (VelbusVMBELHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
thingHandler = new VelbusVMBELHandler(thing);
|
||||
} else if (VelbusVMBELOHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
thingHandler = new VelbusVMBELOHandler(thing);
|
||||
} else if (VelbusVMB4ANHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
thingHandler = new VelbusVMB4ANHandler(thing);
|
||||
} else if (VelbusVMB1TSHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
|
||||
thingHandler = new VelbusVMB1TSHandler(thing);
|
||||
}
|
||||
|
||||
return thingHandler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusBridgeHandler;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusChannelNameRequestPacket;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
|
||||
/**
|
||||
* The {@link VelbusModule} represents a generic module and its basic properties
|
||||
* in the Velbus system.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusModule {
|
||||
private final HashMap<Integer, String[]> channelNames = new HashMap<>();
|
||||
|
||||
private VelbusModuleAddress velbusModuleAddress;
|
||||
private byte highByteOfSerialNumber;
|
||||
private byte lowByteOfSerialNumber;
|
||||
private byte memoryMapVersion;
|
||||
private byte buildYear;
|
||||
private byte buildWeek;
|
||||
private int numberOfChannels;
|
||||
|
||||
private ThingTypeUID thingTypeUID;
|
||||
|
||||
public VelbusModule(VelbusModuleAddress velbusModuleAddress, byte moduleType, byte highByteOfSerialNumber,
|
||||
byte lowByteOfSerialNumber, byte memoryMapVersion, byte buildYear, byte buildWeek,
|
||||
ThingTypeUID thingTypeUID, int numberOfChannels) {
|
||||
this.velbusModuleAddress = velbusModuleAddress;
|
||||
this.highByteOfSerialNumber = highByteOfSerialNumber;
|
||||
this.lowByteOfSerialNumber = lowByteOfSerialNumber;
|
||||
this.memoryMapVersion = memoryMapVersion;
|
||||
this.buildYear = buildYear;
|
||||
this.buildWeek = buildWeek;
|
||||
this.thingTypeUID = thingTypeUID;
|
||||
this.numberOfChannels = numberOfChannels;
|
||||
}
|
||||
|
||||
public VelbusModuleAddress getModuleAddress() {
|
||||
return velbusModuleAddress;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return String.format("%02X", velbusModuleAddress.getAddress());
|
||||
}
|
||||
|
||||
public String getModuleSerialNumber() {
|
||||
return String.format("%02X", highByteOfSerialNumber) + String.format("%02X", lowByteOfSerialNumber);
|
||||
}
|
||||
|
||||
public String getMemoryMapVersion() {
|
||||
return String.format("%02X", memoryMapVersion);
|
||||
}
|
||||
|
||||
public String getModuleBuild() {
|
||||
return String.format("%02X", buildYear) + String.format("%02X", buildWeek);
|
||||
}
|
||||
|
||||
public ThingTypeUID getThingTypeUID() {
|
||||
return this.thingTypeUID;
|
||||
}
|
||||
|
||||
public ThingUID getThingUID(ThingUID bridgeUID) {
|
||||
return new ThingUID(getThingTypeUID(), bridgeUID, getAddress());
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return getThingTypeUID() + " (Address " + getAddress() + ")";
|
||||
}
|
||||
|
||||
protected String getChannelName(int channelIndex) {
|
||||
String channelName = "";
|
||||
|
||||
Integer key = channelIndex - 1;
|
||||
if (channelNames.containsKey(key)) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
String channelNamePart = channelNames.get(key)[i];
|
||||
if (channelNamePart != null) {
|
||||
channelName = channelName + channelNamePart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return channelName;
|
||||
}
|
||||
|
||||
public void sendChannelNameRequests(@Nullable VelbusBridgeHandler bridgeHandler) {
|
||||
if (bridgeHandler != null) {
|
||||
VelbusChannelNameRequestPacket channelNameRequest = new VelbusChannelNameRequestPacket(
|
||||
velbusModuleAddress.getAddress());
|
||||
bridgeHandler.sendPacket(channelNameRequest.getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
public void setChannelName(VelbusChannelIdentifier channelIdentifier, int namePartNumber, byte[] namePart) {
|
||||
StringBuilder contents = new StringBuilder();
|
||||
for (int i = 0; i < namePart.length; i++) {
|
||||
byte currentChar = namePart[i];
|
||||
if (currentChar != (byte) 0xFF) {
|
||||
contents.append((char) currentChar);
|
||||
}
|
||||
}
|
||||
|
||||
Integer key = numberOfChannels <= 8 ? velbusModuleAddress.getChannelIndex(channelIdentifier)
|
||||
: channelIdentifier.getChannelByte() - 1;
|
||||
if (!channelNames.containsKey(key)) {
|
||||
channelNames.put(key, new String[3]);
|
||||
}
|
||||
|
||||
channelNames.get(key)[namePartNumber - 1] = contents.toString();
|
||||
}
|
||||
|
||||
public Map<String, Object> getProperties() {
|
||||
Map<String, Object> properties = new TreeMap<>();
|
||||
|
||||
properties.put(ADDRESS, getAddress());
|
||||
properties.put(MODULE_SERIAL_NUMBER, getModuleSerialNumber());
|
||||
properties.put(MODULE_MEMORY_MAP_VERSION, getMemoryMapVersion());
|
||||
properties.put(MODULE_BUILD, getModuleBuild());
|
||||
|
||||
Integer[] keys = channelNames.keySet().toArray(new Integer[0]);
|
||||
Arrays.sort(keys);
|
||||
|
||||
for (Integer key : keys) {
|
||||
String channelName = getChannelName(key);
|
||||
if (channelName.length() > 0) {
|
||||
properties.put(CHANNEL + key, channelName);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] subAddresses = velbusModuleAddress.getSubAddresses();
|
||||
for (int i = 1; i <= subAddresses.length; i++) {
|
||||
properties.put(SUB_ADDRESS + i, String.format("%02X", subAddresses[i - 1]));
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
|
||||
/**
|
||||
* The {@link VelbusModuleAddress} represents the address and possible subaddresses of a Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusModuleAddress {
|
||||
private byte address;
|
||||
private byte[] subAddresses;
|
||||
|
||||
public VelbusModuleAddress(byte address, int numberOfSubAddresses) {
|
||||
this(address, getInitialSubAddresses(numberOfSubAddresses));
|
||||
}
|
||||
|
||||
public VelbusModuleAddress(byte address, byte[] subAddresses) {
|
||||
this.address = address;
|
||||
this.subAddresses = subAddresses;
|
||||
}
|
||||
|
||||
public byte getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setSubAddresses(byte[] subAddresses) {
|
||||
this.subAddresses = subAddresses;
|
||||
}
|
||||
|
||||
public byte[] getSubAddresses() {
|
||||
return subAddresses;
|
||||
}
|
||||
|
||||
public byte[] getActiveAddresses() {
|
||||
List<Byte> activeAddresses = new ArrayList<>();
|
||||
activeAddresses.add(address);
|
||||
|
||||
for (int i = 0; i < subAddresses.length; i++) {
|
||||
if (subAddresses[i] != (byte) 0xFF) {
|
||||
activeAddresses.add(subAddresses[i]);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] result = new byte[activeAddresses.size()];
|
||||
|
||||
for (int i = 0; i < activeAddresses.size(); i++) {
|
||||
result[i] = activeAddresses.get(i);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public VelbusChannelIdentifier getChannelIdentifier(ChannelUID channelUID) {
|
||||
int channelIndex = getChannelIndex(channelUID);
|
||||
|
||||
return getChannelIdentifier(channelIndex);
|
||||
}
|
||||
|
||||
public int getChannelNumber(ChannelUID channelUID) {
|
||||
return Integer.parseInt(channelUID.getIdWithoutGroup().substring(2));
|
||||
}
|
||||
|
||||
public int getChannelIndex(ChannelUID channelUID) {
|
||||
return getChannelNumber(channelUID) - 1;
|
||||
}
|
||||
|
||||
public String getChannelId(VelbusChannelIdentifier velbusChannelIdentifier) {
|
||||
return "CH" + getChannelNumber(velbusChannelIdentifier);
|
||||
}
|
||||
|
||||
public int getChannelIndex(VelbusChannelIdentifier velbusChannelIdentifier) {
|
||||
return this.getChannelNumber(velbusChannelIdentifier) - 1;
|
||||
}
|
||||
|
||||
public int getChannelNumber(VelbusChannelIdentifier velbusChannelIdentifier) {
|
||||
byte[] activeAddresses = getActiveAddresses();
|
||||
|
||||
for (int i = 0; i < activeAddresses.length; i++) {
|
||||
if (velbusChannelIdentifier.getAddress() == activeAddresses[i]) {
|
||||
return (i * 8) + velbusChannelIdentifier.getChannelNumberFromBitNumber();
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("The byte '" + velbusChannelIdentifier.getChannelByte()
|
||||
+ "' does not represent a valid channel on the address '" + velbusChannelIdentifier.getAddress()
|
||||
+ "'.");
|
||||
}
|
||||
|
||||
public VelbusChannelIdentifier getChannelIdentifier(int channelIndex) {
|
||||
int addressIndex = channelIndex / 8;
|
||||
int addressChannelIndex = channelIndex % 8;
|
||||
|
||||
byte address = addressIndex == 0 ? this.address : subAddresses[addressIndex - 1];
|
||||
byte channel = (byte) Math.pow(2, addressChannelIndex);
|
||||
|
||||
return new VelbusChannelIdentifier(address, channel);
|
||||
}
|
||||
|
||||
private static byte[] getInitialSubAddresses(int numberOfSubAddresses) {
|
||||
byte[] subAddresses = new byte[numberOfSubAddresses];
|
||||
|
||||
for (int i = 0; i < numberOfSubAddresses; i++) {
|
||||
subAddresses[i] = (byte) 0xFF;
|
||||
}
|
||||
|
||||
return subAddresses;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusPacket;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link VelbusPacketInputStream} is a wrapper around an InputStream that
|
||||
* aggregates bytes from the input stream to meaningfull packets in the Velbus system.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusPacketInputStream {
|
||||
private final Logger logger = LoggerFactory.getLogger(VelbusPacketInputStream.class);
|
||||
|
||||
public InputStream inputStream;
|
||||
|
||||
private ArrayList<Byte> currentData = new ArrayList<Byte>();
|
||||
private @Nullable Byte currentSTX = null;
|
||||
private @Nullable Byte currentPriority = null;
|
||||
private @Nullable Byte currentAddress = null;
|
||||
private @Nullable Byte currentDataLength = null;
|
||||
private @Nullable Byte currentChecksum = null;
|
||||
|
||||
public VelbusPacketInputStream(InputStream inputStream) {
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
|
||||
public byte[] readPacket() throws IOException {
|
||||
int currentDataByte;
|
||||
|
||||
while ((currentDataByte = inputStream.read()) > -1) {
|
||||
if (currentSTX == null) {
|
||||
if (((byte) currentDataByte) == VelbusPacket.STX) {
|
||||
currentSTX = (byte) currentDataByte;
|
||||
} else {
|
||||
resetCurrentState();
|
||||
logger.debug("Packet with invalid start byte: {}", currentDataByte);
|
||||
}
|
||||
} else if (currentPriority == null) {
|
||||
if (((byte) currentDataByte) == VelbusPacket.PRIO_HI
|
||||
|| ((byte) currentDataByte) == VelbusPacket.PRIO_LOW) {
|
||||
currentPriority = (byte) currentDataByte;
|
||||
} else {
|
||||
resetCurrentState();
|
||||
logger.debug("Packet with invalid priority received: {}", currentDataByte);
|
||||
}
|
||||
} else if (currentAddress == null) {
|
||||
currentAddress = (byte) currentDataByte;
|
||||
} else if (currentDataLength == null && currentDataByte <= 8) {
|
||||
currentDataLength = (byte) currentDataByte;
|
||||
} else if (currentDataLength == null) {
|
||||
currentDataLength = 1;
|
||||
currentData.add((byte) currentDataByte);
|
||||
} else if (currentDataLength != null && (currentData.size() < currentDataLength)) {
|
||||
currentData.add((byte) currentDataByte);
|
||||
} else if (currentChecksum == null) {
|
||||
currentChecksum = (byte) currentDataByte;
|
||||
byte[] packet = getCurrentPacket();
|
||||
byte expectedChecksum = VelbusPacket.computeCRCByte(packet);
|
||||
|
||||
if (currentChecksum != expectedChecksum) {
|
||||
resetCurrentState();
|
||||
logger.debug("Packet with invalid checksum received: {} instead of {}", currentChecksum,
|
||||
expectedChecksum);
|
||||
}
|
||||
} else if (((byte) currentDataByte) == VelbusPacket.ETX) {
|
||||
byte[] packet = getCurrentPacket();
|
||||
|
||||
resetCurrentState();
|
||||
|
||||
return packet;
|
||||
} else {
|
||||
resetCurrentState();
|
||||
logger.debug("Packet with invalid ETX received: {}", currentDataByte);
|
||||
}
|
||||
}
|
||||
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
inputStream.close();
|
||||
}
|
||||
|
||||
protected byte[] getCurrentPacket() {
|
||||
if (currentDataLength != null && currentSTX != null && currentPriority != null && currentAddress != null
|
||||
&& currentChecksum != null) {
|
||||
byte[] packet = new byte[6 + currentDataLength];
|
||||
packet[0] = currentSTX;
|
||||
packet[1] = currentPriority;
|
||||
packet[2] = currentAddress;
|
||||
packet[3] = currentDataLength;
|
||||
|
||||
for (int i = 0; i < currentDataLength; i++) {
|
||||
packet[4 + i] = currentData.get(i);
|
||||
}
|
||||
|
||||
packet[4 + currentDataLength] = currentChecksum;
|
||||
packet[5 + currentDataLength] = VelbusPacket.ETX;
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
protected void resetCurrentState() {
|
||||
currentSTX = null;
|
||||
currentPriority = null;
|
||||
currentAddress = null;
|
||||
currentDataLength = null;
|
||||
currentData = new ArrayList<>();
|
||||
currentChecksum = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusPacketListener} is notified when a Velbus packet for
|
||||
* the listener's address is sent on the bus.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface VelbusPacketListener {
|
||||
/**
|
||||
* This method is called whenever the state of the given relay has changed.
|
||||
*
|
||||
* @param packet The bytes of the received packet.
|
||||
*/
|
||||
void onPacketReceived(byte[] packet);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusBridgeConfig} class represents the configuration of a Velbus Bridge.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusBridgeConfig {
|
||||
public int timeUpdateInterval;
|
||||
public int reconnectionInterval;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusDimmerConfig} class represents the configuration of a Velbus dimmer.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusDimmerConfig {
|
||||
public int dimspeed;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusNetworkBridgeConfig} class represents the configuration of a Velbus Network Bridge.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusNetworkBridgeConfig {
|
||||
public String address = "";
|
||||
public int port;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusSensorConfig} class represents the configuration of a Velbus Temperature Sensor.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusSensorConfig {
|
||||
public int refresh;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusSerialBridgeConfig} class represents the configuration of a Velbus Serial Bridge.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusSerialBridgeConfig {
|
||||
public String port = "";
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusThingConfig} class represents the configuration of a Velbus thing.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusThingConfig {
|
||||
public String address = "";
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusVMB7INConfig} class represents the configuration of a Velbus VMB7IN module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusVMB7INConfig extends VelbusSensorConfig {
|
||||
public double counter1PulseMultiplier;
|
||||
public double counter2PulseMultiplier;
|
||||
public double counter3PulseMultiplier;
|
||||
public double counter4PulseMultiplier;
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
|
||||
import org.openhab.binding.velbus.internal.VelbusFirstGenerationDeviceModuleAddress;
|
||||
import org.openhab.binding.velbus.internal.VelbusModule;
|
||||
import org.openhab.binding.velbus.internal.VelbusModuleAddress;
|
||||
import org.openhab.binding.velbus.internal.VelbusPacketListener;
|
||||
import org.openhab.binding.velbus.internal.handler.VelbusBridgeHandler;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusScanPacket;
|
||||
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;
|
||||
|
||||
/**
|
||||
* If the user scans manually for things this
|
||||
* {@link VelbusThingDiscoveryService}
|
||||
* is used to return Velbus Modules as things to the framework.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusThingDiscoveryService extends AbstractDiscoveryService
|
||||
implements DiscoveryService, ThingHandlerService, VelbusPacketListener {
|
||||
private static final int SEARCH_TIME = 60;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(VelbusThingDiscoveryService.class);
|
||||
|
||||
private Map<Byte, VelbusModule> velbusModules = new HashMap<>();
|
||||
|
||||
private @Nullable VelbusBridgeHandler velbusBridgeHandler;
|
||||
|
||||
public VelbusThingDiscoveryService() {
|
||||
super(SUPPORTED_THING_TYPES_UIDS, SEARCH_TIME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
removeOlderResults(new Date().getTime());
|
||||
|
||||
final VelbusBridgeHandler velbusBridgeHandler = this.velbusBridgeHandler;
|
||||
if (velbusBridgeHandler != null) {
|
||||
velbusBridgeHandler.clearDefaultPacketListener();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
for (int i = 0x00; i <= 0xFF; i++) {
|
||||
VelbusScanPacket packet = new VelbusScanPacket((byte) i);
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
|
||||
final VelbusBridgeHandler velbusBridgeHandler = this.velbusBridgeHandler;
|
||||
if (velbusBridgeHandler != null) {
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceived(byte[] packet) {
|
||||
if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
|
||||
byte address = packet[2];
|
||||
byte length = packet[3];
|
||||
byte command = packet[4];
|
||||
|
||||
if (command == COMMAND_MODULE_TYPE && packet.length >= 10) {
|
||||
handleModuleTypeCommand(packet, address);
|
||||
} else if (command == COMMAND_MODULE_NAME_PART1 & packet.length >= 4 + length) {
|
||||
handleChannelNameCommand(packet, address, length, 1);
|
||||
} else if (command == COMMAND_MODULE_NAME_PART2 && packet.length >= 4 + length) {
|
||||
handleChannelNameCommand(packet, address, length, 2);
|
||||
} else if (command == COMMAND_MODULE_NAME_PART3 && packet.length >= 4 + length) {
|
||||
handleChannelNameCommand(packet, address, length, 3);
|
||||
} else if (command == COMMAND_SUBTYPE && packet.length >= 4 + length) {
|
||||
handleModuleSubtypeCommand(packet, address);
|
||||
} else {
|
||||
logger.debug("Unknown command '{}' to address '{}'.", String.format("%02X", command),
|
||||
String.format("%02X", address));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleModuleTypeCommand(byte[] packet, byte address) {
|
||||
byte moduleType = packet[5];
|
||||
byte highByteOfSerialNumber = packet[6];
|
||||
byte lowByteOfSerialNumber = packet[7];
|
||||
byte memoryMapVersion = packet[8];
|
||||
byte buildYear = packet[9];
|
||||
byte buildWeek = packet[10];
|
||||
|
||||
VelbusModule velbusModule = null;
|
||||
switch (moduleType) {
|
||||
case MODULE_TYPE_VMB1BL:
|
||||
velbusModule = new VelbusModule(new VelbusFirstGenerationDeviceModuleAddress(address), moduleType,
|
||||
highByteOfSerialNumber, lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek,
|
||||
THING_TYPE_VMB1BL, 1);
|
||||
break;
|
||||
case MODULE_TYPE_VMB1BLS:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1BLS, 1);
|
||||
break;
|
||||
case MODULE_TYPE_VMB1DM:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1DM, 1);
|
||||
break;
|
||||
case MODULE_TYPE_VMB1LED:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1LED, 1);
|
||||
break;
|
||||
case MODULE_TYPE_VMB1RY:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1RY, 1);
|
||||
break;
|
||||
case MODULE_TYPE_VMB1RYNO:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1RYNO, 5);
|
||||
break;
|
||||
case MODULE_TYPE_VMB1RYNOS:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1RYNOS, 5);
|
||||
break;
|
||||
case MODULE_TYPE_VMB1RYS:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1RYS, 5);
|
||||
break;
|
||||
case MODULE_TYPE_VMB1TS:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB1TS, 1);
|
||||
break;
|
||||
case MODULE_TYPE_VMB2BL:
|
||||
velbusModule = new VelbusModule(new VelbusFirstGenerationDeviceModuleAddress(address), moduleType,
|
||||
highByteOfSerialNumber, lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek,
|
||||
THING_TYPE_VMB2BL, 2);
|
||||
break;
|
||||
case MODULE_TYPE_VMB2BLE:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB2BLE, 2);
|
||||
break;
|
||||
case MODULE_TYPE_VMB2PBN:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB2PBN, 8);
|
||||
break;
|
||||
case MODULE_TYPE_VMB4AN:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB4AN, 4);
|
||||
break;
|
||||
case MODULE_TYPE_VMB4DC:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB4DC, 4);
|
||||
break;
|
||||
case MODULE_TYPE_VMB4RY:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB4RY, 4);
|
||||
break;
|
||||
case MODULE_TYPE_VMB4RYLD:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB4RYLD, 5);
|
||||
break;
|
||||
case MODULE_TYPE_VMB4RYNO:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB4RYNO, 5);
|
||||
break;
|
||||
case MODULE_TYPE_VMB6IN:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB6IN, 6);
|
||||
break;
|
||||
case MODULE_TYPE_VMB6PBN:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB6PBN, 8);
|
||||
break;
|
||||
case MODULE_TYPE_VMB7IN:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB7IN, 8);
|
||||
break;
|
||||
case MODULE_TYPE_VMB8IR:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB8IR, 8);
|
||||
break;
|
||||
case MODULE_TYPE_VMB8PB:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB8PB, 8);
|
||||
break;
|
||||
case MODULE_TYPE_VMB8PBU:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMB8PBU, 8);
|
||||
break;
|
||||
case MODULE_TYPE_VMBDME:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBDME, 1);
|
||||
break;
|
||||
case MODULE_TYPE_VMBDMI:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBDMI, 1);
|
||||
break;
|
||||
case MODULE_TYPE_VMBDMIR:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBDMIR, 1);
|
||||
break;
|
||||
case MODULE_TYPE_VMBEL1:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBEL1, 9);
|
||||
break;
|
||||
case MODULE_TYPE_VMBEL2:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBEL2, 9);
|
||||
break;
|
||||
case MODULE_TYPE_VMBEL4:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBEL4, 9);
|
||||
break;
|
||||
case MODULE_TYPE_VMBELO:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBELO, 33);
|
||||
break;
|
||||
case MODULE_TYPE_VMBGP1:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP1, 9);
|
||||
break;
|
||||
case MODULE_TYPE_VMBGP1_2:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP1_2, 9);
|
||||
break;
|
||||
case MODULE_TYPE_VMBGP2:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP2, 9);
|
||||
break;
|
||||
case MODULE_TYPE_VMBGP2_2:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP2_2, 9);
|
||||
break;
|
||||
case MODULE_TYPE_VMBGP4:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP4, 9);
|
||||
break;
|
||||
case MODULE_TYPE_VMBGP4_2:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP4_2, 9);
|
||||
break;
|
||||
case MODULE_TYPE_VMBGP4PIR:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP4PIR, 9);
|
||||
break;
|
||||
case MODULE_TYPE_VMBGP4PIR_2:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP4PIR_2, 9);
|
||||
break;
|
||||
case MODULE_TYPE_VMBGPO:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGPO, 33);
|
||||
break;
|
||||
case MODULE_TYPE_VMBGPOD:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGPOD, 33);
|
||||
break;
|
||||
case MODULE_TYPE_VMBGPOD_2:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGPOD_2, 33);
|
||||
break;
|
||||
case MODULE_TYPE_VMBMETEO:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBMETEO, 13);
|
||||
break;
|
||||
case MODULE_TYPE_VMBPIRC:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBPIRC, 7);
|
||||
break;
|
||||
case MODULE_TYPE_VMBPIRM:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBPIRM, 7);
|
||||
break;
|
||||
case MODULE_TYPE_VMBPIRO:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBPIRO, 9);
|
||||
break;
|
||||
case MODULE_TYPE_VMBRFR8S:
|
||||
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 0), moduleType, highByteOfSerialNumber,
|
||||
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBRFR8S, 8);
|
||||
break;
|
||||
}
|
||||
|
||||
if (velbusModule != null) {
|
||||
registerVelbusModule(address, velbusModule);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleModuleSubtypeCommand(byte[] packet, byte address) {
|
||||
if (velbusModules.containsKey(address)) {
|
||||
VelbusModule velbusModule = velbusModules.get(address);
|
||||
|
||||
byte[] subAddresses = new byte[4];
|
||||
System.arraycopy(packet, 8, subAddresses, 0, 4);
|
||||
|
||||
velbusModule.getModuleAddress().setSubAddresses(subAddresses);
|
||||
|
||||
for (int i = 0; i < subAddresses.length; i++) {
|
||||
if (subAddresses[i] != (byte) 0xFF) {
|
||||
velbusModules.put(subAddresses[i], velbusModule);
|
||||
}
|
||||
}
|
||||
|
||||
notifyDiscoveredVelbusModule(velbusModule);
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerVelbusModule(byte address, VelbusModule velbusModule) {
|
||||
velbusModules.put(address, velbusModule);
|
||||
notifyDiscoveredVelbusModule(velbusModule);
|
||||
velbusModule.sendChannelNameRequests(velbusBridgeHandler);
|
||||
}
|
||||
|
||||
private void handleChannelNameCommand(byte[] packet, byte address, byte length, int namePartNumber) {
|
||||
if (velbusModules.containsKey(address)) {
|
||||
VelbusModule velbusModule = velbusModules.get(address);
|
||||
|
||||
byte channel = packet[5];
|
||||
byte[] namePart = Arrays.copyOfRange(packet, 6, 6 + length - 2);
|
||||
|
||||
VelbusChannelIdentifier velbusChannelIdentifier = new VelbusChannelIdentifier(address, channel);
|
||||
velbusModule.setChannelName(velbusChannelIdentifier, namePartNumber, namePart);
|
||||
notifyDiscoveredVelbusModule(velbusModule);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyDiscoveredVelbusModule(VelbusModule velbusModule) {
|
||||
final VelbusBridgeHandler velbusBridgeHandler = this.velbusBridgeHandler;
|
||||
if (velbusBridgeHandler != null) {
|
||||
ThingUID bridgeUID = velbusBridgeHandler.getThing().getUID();
|
||||
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(velbusModule.getThingUID(bridgeUID))
|
||||
.withThingType(velbusModule.getThingTypeUID()).withProperties(velbusModule.getProperties())
|
||||
.withRepresentationProperty(ADDRESS).withBridge(bridgeUID).withLabel(velbusModule.getLabel())
|
||||
.build();
|
||||
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThingHandler(@Nullable ThingHandler handler) {
|
||||
if (handler instanceof VelbusBridgeHandler) {
|
||||
final VelbusBridgeHandler velbusBridgeHandler = (VelbusBridgeHandler) handler;
|
||||
this.velbusBridgeHandler = velbusBridgeHandler;
|
||||
velbusBridgeHandler.setDefaultPacketListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingHandler getThingHandler() {
|
||||
return this.velbusBridgeHandler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
|
||||
import org.openhab.binding.velbus.internal.VelbusFirstGenerationDeviceModuleAddress;
|
||||
import org.openhab.binding.velbus.internal.VelbusModuleAddress;
|
||||
import org.openhab.binding.velbus.internal.config.VelbusThingConfig;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusBlindOffPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusBlindPositionPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusBlindUpDownPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusStatusRequestPacket;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.StopMoveType;
|
||||
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.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
/**
|
||||
* The {@link VelbusBlindsHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusBlindsHandler extends VelbusThingHandler {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(
|
||||
Arrays.asList(THING_TYPE_VMB1BL, THING_TYPE_VMB1BLS, THING_TYPE_VMB2BL, THING_TYPE_VMB2BLE));
|
||||
|
||||
public VelbusBlindsHandler(Thing thing) {
|
||||
super(thing, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
VelbusStatusRequestPacket packet = new VelbusStatusRequestPacket(
|
||||
getModuleAddress().getChannelIdentifier(channelUID));
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
} else if (command instanceof UpDownType) {
|
||||
UpDownType s = (UpDownType) command;
|
||||
if (s == UpDownType.UP) {
|
||||
byte commandByte = COMMAND_BLIND_UP;
|
||||
|
||||
VelbusBlindUpDownPacket packet = new VelbusBlindUpDownPacket(
|
||||
getModuleAddress().getChannelIdentifier(channelUID), commandByte);
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
} else {
|
||||
byte commandByte = COMMAND_BLIND_DOWN;
|
||||
|
||||
VelbusBlindUpDownPacket packet = new VelbusBlindUpDownPacket(
|
||||
getModuleAddress().getChannelIdentifier(channelUID), commandByte);
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
} else if (command instanceof StopMoveType) {
|
||||
StopMoveType s = (StopMoveType) command;
|
||||
if (s == StopMoveType.STOP) {
|
||||
VelbusBlindOffPacket packet = new VelbusBlindOffPacket(
|
||||
getModuleAddress().getChannelIdentifier(channelUID));
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
} else if (command instanceof PercentType) {
|
||||
VelbusBlindPositionPacket packet = new VelbusBlindPositionPacket(
|
||||
getModuleAddress().getChannelIdentifier(channelUID), ((PercentType) command).byteValue());
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
} else {
|
||||
logger.debug("The command '{}' is not supported by this handler.", command.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable VelbusModuleAddress createVelbusModuleAddress(int numberOfSubAddresses) {
|
||||
final VelbusThingConfig velbusThingConfig = this.velbusThingConfig;
|
||||
if (velbusThingConfig != null) {
|
||||
byte address = hexToByte(velbusThingConfig.address);
|
||||
|
||||
if (isFirstGenerationDevice()) {
|
||||
return new VelbusFirstGenerationDeviceModuleAddress(address);
|
||||
}
|
||||
|
||||
return new VelbusModuleAddress(address, numberOfSubAddresses);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Boolean isFirstGenerationDevice() {
|
||||
ThingTypeUID thingTypeUID = this.getThing().getThingTypeUID();
|
||||
return thingTypeUID.equals(THING_TYPE_VMB1BL) || thingTypeUID.equals(THING_TYPE_VMB2BL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceived(byte[] packet) {
|
||||
logger.trace("onPacketReceived() was called");
|
||||
|
||||
if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
|
||||
byte command = packet[4];
|
||||
|
||||
if (command == COMMAND_BLIND_STATUS && packet.length >= 9) {
|
||||
byte address = packet[2];
|
||||
byte channel = packet[5];
|
||||
byte blindPosition = packet[9];
|
||||
|
||||
VelbusChannelIdentifier velbusChannelIdentifier = new VelbusChannelIdentifier(address, channel);
|
||||
PercentType state = new PercentType(blindPosition);
|
||||
updateState(getModuleAddress().getChannelId(velbusChannelIdentifier), state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.time.Instant;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
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.velbus.internal.VelbusPacketInputStream;
|
||||
import org.openhab.binding.velbus.internal.VelbusPacketListener;
|
||||
import org.openhab.binding.velbus.internal.config.VelbusBridgeConfig;
|
||||
import org.openhab.binding.velbus.internal.discovery.VelbusThingDiscoveryService;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusSetDatePacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusSetDaylightSavingsStatusPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusSetRealtimeClockPacket;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
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;
|
||||
|
||||
/**
|
||||
* {@link VelbusBridgeHandler} is an abstract handler for a Velbus interface and connects it to
|
||||
* the framework.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class VelbusBridgeHandler extends BaseBridgeHandler {
|
||||
private final Logger logger = LoggerFactory.getLogger(VelbusBridgeHandler.class);
|
||||
|
||||
private long lastPacketTimeMillis;
|
||||
|
||||
protected @Nullable VelbusPacketListener defaultPacketListener;
|
||||
protected Map<Byte, VelbusPacketListener> packetListeners = new HashMap<>();
|
||||
|
||||
private @NonNullByDefault({}) VelbusBridgeConfig bridgeConfig;
|
||||
private @Nullable ScheduledFuture<?> timeUpdateJob;
|
||||
private @Nullable ScheduledFuture<?> reconnectionHandler;
|
||||
|
||||
private @NonNullByDefault({}) OutputStream outputStream;
|
||||
private @NonNullByDefault({}) VelbusPacketInputStream inputStream;
|
||||
|
||||
private boolean listenerStopped;
|
||||
|
||||
public VelbusBridgeHandler(Bridge velbusBridge) {
|
||||
super(velbusBridge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing velbus bridge handler.");
|
||||
|
||||
bridgeConfig = getConfigAs(VelbusBridgeConfig.class);
|
||||
|
||||
connect();
|
||||
initializeTimeUpdate();
|
||||
}
|
||||
|
||||
private void initializeTimeUpdate() {
|
||||
int timeUpdateInterval = bridgeConfig.timeUpdateInterval;
|
||||
|
||||
if (timeUpdateInterval > 0) {
|
||||
startTimeUpdates(timeUpdateInterval);
|
||||
}
|
||||
}
|
||||
|
||||
private void startTimeUpdates(int timeUpdatesInterval) {
|
||||
timeUpdateJob = scheduler.scheduleWithFixedDelay(this::updateDateTime, 0, timeUpdatesInterval,
|
||||
TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
private void updateDateTime() {
|
||||
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(Instant.now(), TimeZone.getDefault().toZoneId());
|
||||
|
||||
updateDate(zonedDateTime);
|
||||
updateTime(zonedDateTime);
|
||||
updateDaylightSavingsStatus(zonedDateTime);
|
||||
}
|
||||
|
||||
private void updateTime(ZonedDateTime zonedDateTime) {
|
||||
VelbusSetRealtimeClockPacket packet = new VelbusSetRealtimeClockPacket((byte) 0x00, zonedDateTime);
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
this.sendPacket(packetBytes);
|
||||
}
|
||||
|
||||
private void updateDate(ZonedDateTime zonedDateTime) {
|
||||
VelbusSetDatePacket packet = new VelbusSetDatePacket((byte) 0x00, zonedDateTime);
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
this.sendPacket(packetBytes);
|
||||
}
|
||||
|
||||
private void updateDaylightSavingsStatus(ZonedDateTime zonedDateTime) {
|
||||
VelbusSetDaylightSavingsStatusPacket packet = new VelbusSetDaylightSavingsStatusPacket((byte) 0x00,
|
||||
zonedDateTime);
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
this.sendPacket(packetBytes);
|
||||
}
|
||||
|
||||
protected void initializeStreams(OutputStream outputStream, InputStream inputStream) {
|
||||
this.outputStream = outputStream;
|
||||
this.inputStream = new VelbusPacketInputStream(inputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
final ScheduledFuture<?> timeUpdateJob = this.timeUpdateJob;
|
||||
if (timeUpdateJob != null) {
|
||||
timeUpdateJob.cancel(true);
|
||||
}
|
||||
disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
// There is nothing to handle in the bridge handler
|
||||
}
|
||||
|
||||
public synchronized void sendPacket(byte[] packet) {
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
long timeSinceLastPacket = currentTimeMillis - lastPacketTimeMillis;
|
||||
|
||||
if (timeSinceLastPacket < 60) {
|
||||
// When sending you need a delay of 60ms between each packet (to prevent flooding the VMB1USB).
|
||||
long timeToDelay = 60 - timeSinceLastPacket;
|
||||
|
||||
scheduler.schedule(() -> {
|
||||
sendPacket(packet);
|
||||
}, timeToDelay, TimeUnit.MILLISECONDS);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
writePacket(packet);
|
||||
|
||||
lastPacketTimeMillis = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private void readPacket(byte[] packet) {
|
||||
byte address = packet[2];
|
||||
|
||||
if (packetListeners.containsKey(address)) {
|
||||
VelbusPacketListener packetListener = packetListeners.get(address);
|
||||
packetListener.onPacketReceived(packet);
|
||||
} else {
|
||||
final VelbusPacketListener defaultPacketListener = this.defaultPacketListener;
|
||||
if (defaultPacketListener != null) {
|
||||
defaultPacketListener.onPacketReceived(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void readPackets() {
|
||||
if (inputStream == null) {
|
||||
onConnectionLost();
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] packet;
|
||||
|
||||
listenerStopped = false;
|
||||
|
||||
try {
|
||||
while (!listenerStopped & ((packet = inputStream.readPacket()).length > 0)) {
|
||||
readPacket(packet);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (!listenerStopped) {
|
||||
onConnectionLost();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writePacket(byte[] packet) {
|
||||
if (outputStream == null) {
|
||||
onConnectionLost();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
outputStream.write(packet);
|
||||
outputStream.flush();
|
||||
} catch (IOException e) {
|
||||
onConnectionLost();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onConnectionLost() {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"A network communication error occurred.");
|
||||
disconnect();
|
||||
startReconnectionHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a connection to the Velbus system.
|
||||
*
|
||||
* @return True if the connection succeeded, false if the connection did not succeed.
|
||||
*/
|
||||
protected abstract boolean connect();
|
||||
|
||||
protected void disconnect() {
|
||||
listenerStopped = true;
|
||||
|
||||
try {
|
||||
if (outputStream != null) {
|
||||
outputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.debug("Error while closing output stream", e);
|
||||
}
|
||||
|
||||
try {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.debug("Error while closing input stream", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void startReconnectionHandler() {
|
||||
final ScheduledFuture<?> reconnectionHandler = this.reconnectionHandler;
|
||||
if (reconnectionHandler == null || reconnectionHandler.isCancelled()) {
|
||||
int reconnectionInterval = bridgeConfig.reconnectionInterval;
|
||||
if (reconnectionInterval > 0) {
|
||||
this.reconnectionHandler = scheduler.scheduleWithFixedDelay(() -> {
|
||||
if (connect() && reconnectionHandler != null) {
|
||||
reconnectionHandler.cancel(false);
|
||||
}
|
||||
}, reconnectionInterval, reconnectionInterval, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return Collections.singleton(VelbusThingDiscoveryService.class);
|
||||
}
|
||||
|
||||
public void setDefaultPacketListener(VelbusPacketListener velbusPacketListener) {
|
||||
defaultPacketListener = velbusPacketListener;
|
||||
}
|
||||
|
||||
public void clearDefaultPacketListener() {
|
||||
defaultPacketListener = null;
|
||||
}
|
||||
|
||||
public void registerPacketListener(byte address, VelbusPacketListener packetListener) {
|
||||
packetListeners.put(Byte.valueOf(address), packetListener);
|
||||
}
|
||||
|
||||
public void unregisterRelayStatusListener(byte address) {
|
||||
packetListeners.remove(Byte.valueOf(address));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
|
||||
import org.openhab.binding.velbus.internal.config.VelbusDimmerConfig;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusDimmerPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusStatusRequestPacket;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
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.ThingTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
/**
|
||||
* The {@link VelbusDimmerHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusDimmerHandler extends VelbusThingHandler {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(Arrays.asList(THING_TYPE_VMB1DM,
|
||||
THING_TYPE_VMB1LED, THING_TYPE_VMB4DC, THING_TYPE_VMBDME, THING_TYPE_VMBDMI, THING_TYPE_VMBDMIR));
|
||||
|
||||
private @NonNullByDefault({}) VelbusDimmerConfig dimmerConfig;
|
||||
|
||||
public VelbusDimmerHandler(Thing thing) {
|
||||
super(thing, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
this.dimmerConfig = getConfigAs(VelbusDimmerConfig.class);
|
||||
|
||||
super.initialize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
VelbusStatusRequestPacket packet = new VelbusStatusRequestPacket(
|
||||
getModuleAddress().getChannelIdentifier(channelUID));
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
} else if (command instanceof PercentType) {
|
||||
byte commandByte = COMMAND_SET_VALUE;
|
||||
|
||||
VelbusDimmerPacket packet = new VelbusDimmerPacket(getModuleAddress().getChannelIdentifier(channelUID),
|
||||
commandByte, ((PercentType) command).byteValue(), this.dimmerConfig.dimspeed,
|
||||
isFirstGenerationDevice());
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
} else if (command instanceof OnOffType) {
|
||||
byte commandByte = determineCommandByte((OnOffType) command);
|
||||
|
||||
VelbusDimmerPacket packet = new VelbusDimmerPacket(getModuleAddress().getChannelIdentifier(channelUID),
|
||||
commandByte, (byte) 0x00, this.dimmerConfig.dimspeed, isFirstGenerationDevice());
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
} else {
|
||||
logger.debug("The command '{}' is not supported by this handler.", command.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private byte determineCommandByte(OnOffType command) {
|
||||
return (command == OnOffType.ON) ? COMMAND_RESTORE_LAST_DIMVALUE : COMMAND_SET_VALUE;
|
||||
}
|
||||
|
||||
private Boolean isFirstGenerationDevice() {
|
||||
ThingTypeUID thingTypeUID = this.getThing().getThingTypeUID();
|
||||
return thingTypeUID.equals(THING_TYPE_VMB1DM) || thingTypeUID.equals(THING_TYPE_VMB1LED)
|
||||
|| thingTypeUID.equals(THING_TYPE_VMBDME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceived(byte[] packet) {
|
||||
logger.trace("onPacketReceived() was called");
|
||||
|
||||
if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
|
||||
byte address = packet[2];
|
||||
byte command = packet[4];
|
||||
|
||||
if ((command == COMMAND_DIMMERCONTROLLER_STATUS) && packet.length >= 8) {
|
||||
byte channel = packet[5];
|
||||
byte dimValue = packet[7];
|
||||
|
||||
VelbusChannelIdentifier velbusChannelIdentifier = new VelbusChannelIdentifier(address, channel);
|
||||
PercentType state = new PercentType(dimValue);
|
||||
updateState(getModuleAddress().getChannelId(velbusChannelIdentifier), state);
|
||||
} else if ((command == COMMAND_DIMMER_STATUS) && packet.length >= 7) {
|
||||
byte dimValue = packet[6];
|
||||
|
||||
VelbusChannelIdentifier velbusChannelIdentifier = new VelbusChannelIdentifier(address, (byte) 0x01);
|
||||
PercentType state = new PercentType(dimValue);
|
||||
updateState(getModuleAddress().getChannelId(velbusChannelIdentifier), state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusMemoTextPacket;
|
||||
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.thing.ThingStatusDetail;
|
||||
import org.openhab.core.types.Command;
|
||||
|
||||
/**
|
||||
* The {@link VelbusMemoHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class VelbusMemoHandler extends VelbusThermostatHandler {
|
||||
public static final int MEMO_TEXT_MAX_LENGTH = 63;
|
||||
|
||||
private final ChannelUID memoChannel = new ChannelUID(thing.getUID(), "oledDisplay", "MEMO");
|
||||
|
||||
public VelbusMemoHandler(Thing thing) {
|
||||
super(thing, 4, new ChannelUID(thing.getUID(), "input", "CH33"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
super.handleCommand(channelUID, command);
|
||||
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (channelUID.equals(memoChannel) && command instanceof StringType) {
|
||||
String memoText = ((StringType) command).toFullString();
|
||||
String trucatedMemoText = memoText.substring(0, Math.min(memoText.length(), MEMO_TEXT_MAX_LENGTH));
|
||||
String[] splittedMemoText = trucatedMemoText.split("(?<=\\G.....)");
|
||||
|
||||
for (int i = 0; i < splittedMemoText.length; i++) {
|
||||
VelbusMemoTextPacket packet = new VelbusMemoTextPacket(getModuleAddress().getAddress(), (byte) (i * 5),
|
||||
splittedMemoText[i].toCharArray());
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
|
||||
// The last character must be zero
|
||||
if ((((i * 5) + 5) >= trucatedMemoText.length()) && (splittedMemoText[i].length() == 5)) {
|
||||
packet = new VelbusMemoTextPacket(getModuleAddress().getAddress(), (byte) ((i + 1) * 5),
|
||||
new char[0]);
|
||||
|
||||
packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.velbus.internal.config.VelbusNetworkBridgeConfig;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* {@link VelbusNetworkBridgeHandler} is the handler for a Velbus network interface and connects it to
|
||||
* the framework.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusNetworkBridgeHandler extends VelbusBridgeHandler {
|
||||
private final Logger logger = LoggerFactory.getLogger(VelbusNetworkBridgeHandler.class);
|
||||
|
||||
private @Nullable Socket socket;
|
||||
private @NonNullByDefault({}) VelbusNetworkBridgeConfig networkBridgeConfig;
|
||||
|
||||
public VelbusNetworkBridgeHandler(Bridge velbusBridge) {
|
||||
super(velbusBridge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
this.networkBridgeConfig = getConfigAs(VelbusNetworkBridgeConfig.class);
|
||||
|
||||
super.initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a connection to the Velbus system.
|
||||
*
|
||||
* @return True if the connection succeeded, false if the connection did not succeed.
|
||||
*/
|
||||
@Override
|
||||
protected boolean connect() {
|
||||
try {
|
||||
Socket socket = new Socket(networkBridgeConfig.address, networkBridgeConfig.port);
|
||||
this.socket = socket;
|
||||
|
||||
initializeStreams(socket.getOutputStream(), socket.getInputStream());
|
||||
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
logger.debug("Bridge online on network address {}:{}", networkBridgeConfig.address,
|
||||
networkBridgeConfig.port);
|
||||
return true;
|
||||
} catch (IOException ex) {
|
||||
onConnectionLost();
|
||||
logger.debug("Failed to connect to network address {}:{}", networkBridgeConfig.address,
|
||||
networkBridgeConfig.port);
|
||||
}
|
||||
|
||||
// Start Velbus packet listener. This listener will act on all packets coming from
|
||||
// IP-interface.
|
||||
Thread thread = new Thread(this::readPackets, "OH-binding-" + this.thing.getUID());
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void disconnect() {
|
||||
final Socket socket = this.socket;
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
logger.debug("Error while closing socket", e);
|
||||
}
|
||||
this.socket = null;
|
||||
}
|
||||
|
||||
super.disconnect();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusRelayPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusStatusRequestPacket;
|
||||
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.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
/**
|
||||
* The {@link VelbusRelayHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusRelayHandler extends VelbusThingHandler {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(
|
||||
Arrays.asList(THING_TYPE_VMB1RY, THING_TYPE_VMB1RYNO, THING_TYPE_VMB1RYNOS, THING_TYPE_VMB1RYS,
|
||||
THING_TYPE_VMB4RY, THING_TYPE_VMB4RYLD, THING_TYPE_VMB4RYNO));
|
||||
|
||||
public VelbusRelayHandler(Thing thing) {
|
||||
super(thing, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
VelbusStatusRequestPacket packet = new VelbusStatusRequestPacket(
|
||||
getModuleAddress().getChannelIdentifier(channelUID));
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
} else if (command instanceof OnOffType) {
|
||||
byte commandByte = determineCommandByte((OnOffType) command);
|
||||
|
||||
VelbusRelayPacket packet = new VelbusRelayPacket(getModuleAddress().getChannelIdentifier(channelUID),
|
||||
commandByte);
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
} else {
|
||||
logger.debug("The command '{}' is not supported by this handler.", command.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
private byte determineCommandByte(OnOffType command) {
|
||||
return (command == OnOffType.ON) ? COMMAND_SWITCH_RELAY_ON : COMMAND_SWITCH_RELAY_OFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceived(byte[] packet) {
|
||||
logger.trace("onPacketReceived() was called");
|
||||
|
||||
if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
|
||||
byte command = packet[4];
|
||||
|
||||
if (command == COMMAND_RELAY_STATUS && packet.length >= 7) {
|
||||
byte address = packet[2];
|
||||
byte channel = packet[5];
|
||||
boolean on = packet[7] != 0x00;
|
||||
|
||||
VelbusChannelIdentifier velbusChannelIdentifier = new VelbusChannelIdentifier(address, channel);
|
||||
OnOffType state = on ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(getModuleAddress().getChannelId(velbusChannelIdentifier), state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusFeedbackLEDPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusPacket;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.CommonTriggerEvents;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
|
||||
/**
|
||||
* The {@link VelbusSensorHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusSensorHandler extends VelbusThingHandler {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(
|
||||
Arrays.asList(THING_TYPE_VMB6IN, THING_TYPE_VMB8IR, THING_TYPE_VMB8PB));
|
||||
|
||||
private static final StringType SET_LED = new StringType("SET_LED");
|
||||
private static final StringType SLOW_BLINK_LED = new StringType("SLOW_BLINK_LED");
|
||||
private static final StringType FAST_BLINK_LED = new StringType("FAST_BLINK_LED");
|
||||
private static final StringType VERY_FAST_BLINK_LED = new StringType("VERY_FAST_BLINK_LED");
|
||||
private static final StringType CLEAR_LED = new StringType("CLEAR_LED");
|
||||
|
||||
public VelbusSensorHandler(Thing thing) {
|
||||
this(thing, 0);
|
||||
}
|
||||
|
||||
public VelbusSensorHandler(Thing thing, int numberOfSubAddresses) {
|
||||
super(thing, numberOfSubAddresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isFeedbackChannel(channelUID) && command instanceof StringType) {
|
||||
byte commandByte;
|
||||
|
||||
StringType stringTypeCommand = (StringType) command;
|
||||
if (stringTypeCommand.equals(SET_LED)) {
|
||||
commandByte = COMMAND_SET_LED;
|
||||
} else if (stringTypeCommand.equals(SLOW_BLINK_LED)) {
|
||||
commandByte = COMMAND_SLOW_BLINK_LED;
|
||||
} else if (stringTypeCommand.equals(FAST_BLINK_LED)) {
|
||||
commandByte = COMMAND_FAST_BLINK_LED;
|
||||
} else if (stringTypeCommand.equals(VERY_FAST_BLINK_LED)) {
|
||||
commandByte = COMMAND_VERY_FAST_BLINK_LED;
|
||||
} else if (stringTypeCommand.equals(CLEAR_LED)) {
|
||||
commandByte = COMMAND_CLEAR_LED;
|
||||
} else {
|
||||
throw new UnsupportedOperationException(
|
||||
"The command '" + command + "' is not supported on channel '" + channelUID + "'.");
|
||||
}
|
||||
|
||||
VelbusFeedbackLEDPacket packet = new VelbusFeedbackLEDPacket(
|
||||
getModuleAddress().getChannelIdentifier(channelUID), commandByte);
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFeedbackChannel(ChannelUID channelUID) {
|
||||
return "feedback".equals(channelUID.getGroupId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceived(byte[] packet) {
|
||||
logger.trace("onPacketReceived() was called");
|
||||
|
||||
if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
|
||||
byte address = packet[2];
|
||||
byte command = packet[4];
|
||||
|
||||
if (command == COMMAND_PUSH_BUTTON_STATUS && packet.length >= 6) {
|
||||
byte channelJustPressed = packet[5];
|
||||
if (channelJustPressed != 0) {
|
||||
VelbusChannelIdentifier velbusChannelIdentifier = new VelbusChannelIdentifier(address,
|
||||
channelJustPressed);
|
||||
triggerChannel("input#" + getModuleAddress().getChannelId(velbusChannelIdentifier),
|
||||
CommonTriggerEvents.PRESSED);
|
||||
}
|
||||
|
||||
byte channelJustReleased = packet[6];
|
||||
if (channelJustReleased != 0) {
|
||||
VelbusChannelIdentifier velbusChannelIdentifier = new VelbusChannelIdentifier(address,
|
||||
channelJustReleased);
|
||||
triggerChannel("input#" + getModuleAddress().getChannelId(velbusChannelIdentifier),
|
||||
CommonTriggerEvents.RELEASED);
|
||||
}
|
||||
|
||||
byte channelLongPressed = packet[7];
|
||||
if (channelLongPressed != 0) {
|
||||
VelbusChannelIdentifier velbusChannelIdentifier = new VelbusChannelIdentifier(address,
|
||||
channelLongPressed);
|
||||
triggerChannel("input#" + getModuleAddress().getChannelId(velbusChannelIdentifier),
|
||||
CommonTriggerEvents.LONG_PRESSED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.VelbusClockAlarm;
|
||||
import org.openhab.binding.velbus.internal.VelbusClockAlarmConfiguration;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusSetLocalClockAlarmPacket;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
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.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
/**
|
||||
* The {@link VelbusSensorWithAlarmClockHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusSensorWithAlarmClockHandler extends VelbusSensorHandler {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(Arrays.asList(THING_TYPE_VMB2PBN,
|
||||
THING_TYPE_VMB6PBN, THING_TYPE_VMB8PBU, THING_TYPE_VMBPIRC, THING_TYPE_VMBPIRM, THING_TYPE_VMBRFR8S));
|
||||
private static final HashMap<ThingTypeUID, Integer> ALARM_CONFIGURATION_MEMORY_ADDRESSES = new HashMap<ThingTypeUID, Integer>();
|
||||
|
||||
static {
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMB2PBN, 0x0093);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMB4AN, 0x0046);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMB6PBN, 0x0093);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMB7IN, 0x0093);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMB8PBU, 0x0093);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBEL1, 0x0357);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBEL2, 0x0357);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBEL4, 0x0357);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBELO, 0x0593);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBPIRC, 0x0031);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBPIRM, 0x0031);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBPIRO, 0x0031);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBMETEO, 0x0083);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBGP1, 0x00A4);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBGP1_2, 0x00A4);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBGP2, 0x00A4);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBGP2_2, 0x00A4);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBGP4, 0x00A4);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBGP4_2, 0x00A4);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBGP4PIR, 0x00A4);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBGP4PIR_2, 0x00A4);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBGPO, 0x0284);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBGPOD, 0x0284);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBGPOD_2, 0x0284);
|
||||
ALARM_CONFIGURATION_MEMORY_ADDRESSES.put(THING_TYPE_VMBRFR8S, 0x0093);
|
||||
}
|
||||
|
||||
private static final byte ALARM_CONFIGURATION_MEMORY_SIZE = 0x09;
|
||||
private static final byte ALARM_1_ENABLED_MASK = 0x01;
|
||||
private static final byte ALARM_1_TYPE_MASK = 0x02;
|
||||
private static final byte ALARM_2_ENABLED_MASK = 0x04;
|
||||
private static final byte ALARM_2_TYPE_MASK = 0x08;
|
||||
|
||||
private static final StringType ALARM_TYPE_LOCAL = new StringType("LOCAL");
|
||||
private static final StringType ALARM_TYPE_GLOBAL = new StringType("GLOBAL");
|
||||
|
||||
private final ChannelUID clockAlarm1Enabled = new ChannelUID(thing.getUID(), "clockAlarm", "clockAlarm1Enabled");
|
||||
private final ChannelUID clockAlarm1Type = new ChannelUID(thing.getUID(), "clockAlarm", "clockAlarm1Type");
|
||||
private final ChannelUID clockAlarm1WakeupHour = new ChannelUID(thing.getUID(), "clockAlarm",
|
||||
"clockAlarm1WakeupHour");
|
||||
private final ChannelUID clockAlarm1WakeupMinute = new ChannelUID(thing.getUID(), "clockAlarm",
|
||||
"clockAlarm1WakeupMinute");
|
||||
private final ChannelUID clockAlarm1BedtimeHour = new ChannelUID(thing.getUID(), "clockAlarm",
|
||||
"clockAlarm1BedtimeHour");
|
||||
private final ChannelUID clockAlarm1BedtimeMinute = new ChannelUID(thing.getUID(), "clockAlarm",
|
||||
"clockAlarm1BedtimeMinute");
|
||||
private final ChannelUID clockAlarm2Enabled = new ChannelUID(thing.getUID(), "clockAlarm", "clockAlarm2Enabled");
|
||||
private final ChannelUID clockAlarm2Type = new ChannelUID(thing.getUID(), "clockAlarm", "clockAlarm2Type");
|
||||
private final ChannelUID clockAlarm2WakeupHour = new ChannelUID(thing.getUID(), "clockAlarm",
|
||||
"clockAlarm2WakeupHour");
|
||||
private final ChannelUID clockAlarm2WakeupMinute = new ChannelUID(thing.getUID(), "clockAlarm",
|
||||
"clockAlarm2WakeupMinute");
|
||||
private final ChannelUID clockAlarm2BedtimeHour = new ChannelUID(thing.getUID(), "clockAlarm",
|
||||
"clockAlarm2BedtimeHour");
|
||||
private final ChannelUID clockAlarm2BedtimeMinute = new ChannelUID(thing.getUID(), "clockAlarm",
|
||||
"clockAlarm2BedtimeMinute");
|
||||
|
||||
private int clockAlarmConfigurationMemoryAddress;
|
||||
private VelbusClockAlarmConfiguration alarmClockConfiguration = new VelbusClockAlarmConfiguration();
|
||||
|
||||
public VelbusSensorWithAlarmClockHandler(Thing thing) {
|
||||
this(thing, 0);
|
||||
}
|
||||
|
||||
public VelbusSensorWithAlarmClockHandler(Thing thing, int numberOfSubAddresses) {
|
||||
super(thing, numberOfSubAddresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
|
||||
if (ALARM_CONFIGURATION_MEMORY_ADDRESSES.containsKey(thing.getThingTypeUID())) {
|
||||
this.clockAlarmConfigurationMemoryAddress = ALARM_CONFIGURATION_MEMORY_ADDRESSES
|
||||
.get(thing.getThingTypeUID());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
super.handleCommand(channelUID, command);
|
||||
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAlarmClockChannel(channelUID) && command instanceof RefreshType) {
|
||||
sendReadMemoryBlockPacket(velbusBridgeHandler, this.clockAlarmConfigurationMemoryAddress + 0);
|
||||
sendReadMemoryBlockPacket(velbusBridgeHandler, this.clockAlarmConfigurationMemoryAddress + 4);
|
||||
sendReadMemoryPacket(velbusBridgeHandler, this.clockAlarmConfigurationMemoryAddress + 8);
|
||||
} else if (isAlarmClockChannel(channelUID)) {
|
||||
byte alarmNumber = determineAlarmNumber(channelUID);
|
||||
VelbusClockAlarm alarmClock = alarmClockConfiguration.getAlarmClock(alarmNumber);
|
||||
|
||||
if ((channelUID.equals(clockAlarm1Enabled) || channelUID.equals(clockAlarm2Enabled))
|
||||
&& command instanceof OnOffType) {
|
||||
boolean enabled = command == OnOffType.ON;
|
||||
alarmClock.setEnabled(enabled);
|
||||
} else if ((channelUID.equals(clockAlarm1Type) || channelUID.equals(clockAlarm2Type))
|
||||
&& command instanceof StringType) {
|
||||
boolean isLocal = ((StringType) command).equals(ALARM_TYPE_LOCAL);
|
||||
alarmClock.setLocal(isLocal);
|
||||
} else if (channelUID.equals(clockAlarm1WakeupHour)
|
||||
|| channelUID.equals(clockAlarm2WakeupHour) && command instanceof DecimalType) {
|
||||
byte wakeupHour = ((DecimalType) command).byteValue();
|
||||
alarmClock.setWakeupHour(wakeupHour);
|
||||
} else if (channelUID.equals(clockAlarm1WakeupMinute)
|
||||
|| channelUID.equals(clockAlarm2WakeupMinute) && command instanceof DecimalType) {
|
||||
byte wakeupMinute = ((DecimalType) command).byteValue();
|
||||
alarmClock.setWakeupMinute(wakeupMinute);
|
||||
} else if (channelUID.equals(clockAlarm1BedtimeHour)
|
||||
|| channelUID.equals(clockAlarm2BedtimeHour) && command instanceof DecimalType) {
|
||||
byte bedTimeHour = ((DecimalType) command).byteValue();
|
||||
alarmClock.setBedtimeHour(bedTimeHour);
|
||||
} else if (channelUID.equals(clockAlarm1BedtimeMinute)
|
||||
|| channelUID.equals(clockAlarm2BedtimeMinute) && command instanceof DecimalType) {
|
||||
byte bedTimeMinute = ((DecimalType) command).byteValue();
|
||||
alarmClock.setBedtimeMinute(bedTimeMinute);
|
||||
}
|
||||
|
||||
byte address = alarmClock.isLocal() ? getModuleAddress().getAddress() : 0x00;
|
||||
VelbusSetLocalClockAlarmPacket packet = new VelbusSetLocalClockAlarmPacket(address, alarmNumber,
|
||||
alarmClock);
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
} else {
|
||||
logger.debug("The command '{}' is not supported by this handler.", command.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceived(byte[] packet) {
|
||||
super.onPacketReceived(packet);
|
||||
|
||||
logger.trace("onPacketReceived() was called");
|
||||
|
||||
if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
|
||||
byte command = packet[4];
|
||||
|
||||
if ((command == COMMAND_MEMORY_DATA_BLOCK && packet.length >= 11)
|
||||
|| (command == COMMAND_MEMORY_DATA && packet.length >= 8)) {
|
||||
byte highMemoryAddress = packet[5];
|
||||
byte lowMemoryAddress = packet[6];
|
||||
int memoryAddress = ((highMemoryAddress & 0xff) << 8) | (lowMemoryAddress & 0xff);
|
||||
byte[] data = (command == COMMAND_MEMORY_DATA_BLOCK)
|
||||
? new byte[] { packet[7], packet[8], packet[9], packet[10] }
|
||||
: new byte[] { packet[7] };
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
|
||||
if (isClockAlarmConfigurationByte(memoryAddress + i)) {
|
||||
setClockAlarmConfigurationByte(memoryAddress + i, data[i]);
|
||||
}
|
||||
}
|
||||
} else if (command == COMMAND_MODULE_STATUS) {
|
||||
int clockAlarmAndProgramSelectionIndexInModuleStatus = this
|
||||
.getClockAlarmAndProgramSelectionIndexInModuleStatus();
|
||||
if (packet.length >= clockAlarmAndProgramSelectionIndexInModuleStatus + 1) {
|
||||
byte alarmAndProgramSelection = packet[clockAlarmAndProgramSelectionIndexInModuleStatus];
|
||||
|
||||
boolean alarmClock1Enabled = (alarmAndProgramSelection & 0x04) > 0;
|
||||
boolean alarmClock1IsLocal = (alarmAndProgramSelection & 0x08) == 0;
|
||||
VelbusClockAlarm alarmClock1 = this.alarmClockConfiguration.getAlarmClock1();
|
||||
alarmClock1.setEnabled(alarmClock1Enabled);
|
||||
alarmClock1.setLocal(alarmClock1IsLocal);
|
||||
updateState(clockAlarm1Enabled, alarmClock1.isEnabled() ? OnOffType.ON : OnOffType.OFF);
|
||||
updateState(clockAlarm1Type, alarmClock1.isLocal() ? ALARM_TYPE_LOCAL : ALARM_TYPE_GLOBAL);
|
||||
|
||||
boolean alarmClock2Enabled = (alarmAndProgramSelection & 0x10) > 0;
|
||||
boolean alarmClock2IsLocal = (alarmAndProgramSelection & 0x20) == 0;
|
||||
VelbusClockAlarm alarmClock2 = this.alarmClockConfiguration.getAlarmClock2();
|
||||
alarmClock2.setEnabled(alarmClock2Enabled);
|
||||
alarmClock2.setLocal(alarmClock2IsLocal);
|
||||
updateState(clockAlarm2Enabled, alarmClock2.isEnabled() ? OnOffType.ON : OnOffType.OFF);
|
||||
updateState(clockAlarm2Type, alarmClock2.isLocal() ? ALARM_TYPE_LOCAL : ALARM_TYPE_GLOBAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean isClockAlarmConfigurationByte(int memoryAddress) {
|
||||
return memoryAddress >= this.clockAlarmConfigurationMemoryAddress
|
||||
&& memoryAddress < (this.clockAlarmConfigurationMemoryAddress + ALARM_CONFIGURATION_MEMORY_SIZE);
|
||||
}
|
||||
|
||||
public void setClockAlarmConfigurationByte(int memoryAddress, byte data) {
|
||||
VelbusClockAlarm alarmClock1 = this.alarmClockConfiguration.getAlarmClock1();
|
||||
VelbusClockAlarm alarmClock2 = this.alarmClockConfiguration.getAlarmClock2();
|
||||
|
||||
switch (memoryAddress - this.clockAlarmConfigurationMemoryAddress) {
|
||||
case 0:
|
||||
alarmClock1.setEnabled((data & ALARM_1_ENABLED_MASK) > 0);
|
||||
alarmClock1.setLocal((data & ALARM_1_TYPE_MASK) > 0);
|
||||
|
||||
updateState(clockAlarm1Enabled, alarmClock1.isEnabled() ? OnOffType.ON : OnOffType.OFF);
|
||||
updateState(clockAlarm1Type, alarmClock1.isLocal() ? ALARM_TYPE_LOCAL : ALARM_TYPE_GLOBAL);
|
||||
|
||||
alarmClock2.setEnabled((data & ALARM_2_ENABLED_MASK) > 0);
|
||||
alarmClock2.setLocal((data & ALARM_2_TYPE_MASK) > 0);
|
||||
|
||||
updateState(clockAlarm2Enabled, alarmClock2.isEnabled() ? OnOffType.ON : OnOffType.OFF);
|
||||
updateState(clockAlarm2Type, alarmClock2.isLocal() ? ALARM_TYPE_LOCAL : ALARM_TYPE_GLOBAL);
|
||||
break;
|
||||
case 1:
|
||||
alarmClock1.setWakeupHour(data);
|
||||
updateState(clockAlarm1WakeupHour, new DecimalType(alarmClock1.getWakeupHour()));
|
||||
break;
|
||||
case 2:
|
||||
alarmClock1.setWakeupMinute(data);
|
||||
updateState(clockAlarm1WakeupMinute, new DecimalType(alarmClock1.getWakeupMinute()));
|
||||
break;
|
||||
case 3:
|
||||
alarmClock1.setBedtimeHour(data);
|
||||
updateState(clockAlarm1BedtimeHour, new DecimalType(alarmClock1.getBedtimeHour()));
|
||||
break;
|
||||
case 4:
|
||||
alarmClock1.setBedtimeMinute(data);
|
||||
updateState(clockAlarm1BedtimeMinute, new DecimalType(alarmClock1.getBedtimeMinute()));
|
||||
break;
|
||||
case 5:
|
||||
alarmClock2.setWakeupHour(data);
|
||||
updateState(clockAlarm2WakeupHour, new DecimalType(alarmClock2.getWakeupHour()));
|
||||
break;
|
||||
case 6:
|
||||
alarmClock2.setWakeupMinute(data);
|
||||
updateState(clockAlarm2WakeupMinute, new DecimalType(alarmClock2.getWakeupMinute()));
|
||||
break;
|
||||
case 7:
|
||||
alarmClock2.setBedtimeHour(data);
|
||||
updateState(clockAlarm2BedtimeHour, new DecimalType(alarmClock2.getBedtimeHour()));
|
||||
break;
|
||||
case 8:
|
||||
alarmClock2.setBedtimeMinute(data);
|
||||
updateState(clockAlarm2BedtimeMinute, new DecimalType(alarmClock2.getBedtimeMinute()));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("The memory address '" + memoryAddress
|
||||
+ "' does not represent a clock alarm configuration for the thing '" + this.thing.getUID()
|
||||
+ "'.");
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isAlarmClockChannel(ChannelUID channelUID) {
|
||||
return channelUID.equals(clockAlarm1Enabled) || channelUID.equals(clockAlarm1Type)
|
||||
|| channelUID.equals(clockAlarm1WakeupHour) || channelUID.equals(clockAlarm1WakeupMinute)
|
||||
|| channelUID.equals(clockAlarm1BedtimeHour) || channelUID.equals(clockAlarm1BedtimeMinute)
|
||||
|| channelUID.equals(clockAlarm2Enabled) || channelUID.equals(clockAlarm2Type)
|
||||
|| channelUID.equals(clockAlarm2WakeupHour) || channelUID.equals(clockAlarm2WakeupMinute)
|
||||
|| channelUID.equals(clockAlarm2BedtimeHour) || channelUID.equals(clockAlarm2BedtimeMinute);
|
||||
}
|
||||
|
||||
protected byte determineAlarmNumber(ChannelUID channelUID) {
|
||||
if (channelUID.equals(clockAlarm1Enabled) || channelUID.equals(clockAlarm1Type)
|
||||
|| channelUID.equals(clockAlarm1WakeupHour) || channelUID.equals(clockAlarm1WakeupMinute)
|
||||
|| channelUID.equals(clockAlarm1BedtimeHour) || channelUID.equals(clockAlarm1BedtimeMinute)) {
|
||||
return 1;
|
||||
} else if (channelUID.equals(clockAlarm2Enabled) || channelUID.equals(clockAlarm2Type)
|
||||
|| channelUID.equals(clockAlarm2WakeupHour) || channelUID.equals(clockAlarm2WakeupMinute)
|
||||
|| channelUID.equals(clockAlarm2BedtimeHour) || channelUID.equals(clockAlarm2BedtimeMinute)) {
|
||||
return 2;
|
||||
} else {
|
||||
throw new IllegalArgumentException("The given channelUID is not an alarm clock channel: " + channelUID);
|
||||
}
|
||||
}
|
||||
|
||||
protected int getClockAlarmAndProgramSelectionIndexInModuleStatus() {
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.TooManyListenersException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.velbus.internal.config.VelbusSerialBridgeConfig;
|
||||
import org.openhab.core.io.transport.serial.PortInUseException;
|
||||
import org.openhab.core.io.transport.serial.SerialPort;
|
||||
import org.openhab.core.io.transport.serial.SerialPortEvent;
|
||||
import org.openhab.core.io.transport.serial.SerialPortEventListener;
|
||||
import org.openhab.core.io.transport.serial.SerialPortIdentifier;
|
||||
import org.openhab.core.io.transport.serial.SerialPortManager;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* {@link VelbusSerialBridgeHandler} is the handler for a Velbus Serial-interface and connects it to
|
||||
* the framework.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusSerialBridgeHandler extends VelbusBridgeHandler implements SerialPortEventListener {
|
||||
private final Logger logger = LoggerFactory.getLogger(VelbusSerialBridgeHandler.class);
|
||||
|
||||
private SerialPortManager serialPortManager;
|
||||
|
||||
private @Nullable SerialPort serialPort;
|
||||
private @NonNullByDefault({}) VelbusSerialBridgeConfig serialBridgeConfig;
|
||||
|
||||
public VelbusSerialBridgeHandler(Bridge velbusBridge, SerialPortManager serialPortManager) {
|
||||
super(velbusBridge);
|
||||
this.serialPortManager = serialPortManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
this.serialBridgeConfig = getConfigAs(VelbusSerialBridgeConfig.class);
|
||||
|
||||
super.initialize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialEvent(SerialPortEvent event) {
|
||||
logger.debug("Serial port event triggered");
|
||||
|
||||
if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
|
||||
readPackets();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a connection to the Velbus system.
|
||||
*
|
||||
* @return True if the connection succeeded, false if the connection did not succeed.
|
||||
*/
|
||||
@Override
|
||||
protected boolean connect() {
|
||||
// parse ports and if the port is found, initialize the reader
|
||||
SerialPortIdentifier portId = serialPortManager.getIdentifier(serialBridgeConfig.port);
|
||||
if (portId == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, "Port is not known!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// initialize serial port
|
||||
try {
|
||||
SerialPort serialPort = portId.open(getThing().getUID().toString(), 2000);
|
||||
this.serialPort = serialPort;
|
||||
|
||||
OutputStream outputStream = serialPort.getOutputStream();
|
||||
InputStream inputStream = serialPort.getInputStream();
|
||||
|
||||
if (outputStream != null && inputStream != null) {
|
||||
initializeStreams(outputStream, inputStream);
|
||||
|
||||
serialPort.addEventListener(this);
|
||||
serialPort.notifyOnDataAvailable(true);
|
||||
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
logger.debug("Bridge online on serial port {}", serialBridgeConfig.port);
|
||||
return true;
|
||||
}
|
||||
} catch (final IOException ex) {
|
||||
onConnectionLost();
|
||||
logger.debug("I/O error on serial port {}", serialBridgeConfig.port);
|
||||
} catch (PortInUseException e) {
|
||||
onConnectionLost();
|
||||
logger.debug("Port {} is in use", serialBridgeConfig.port);
|
||||
} catch (TooManyListenersException e) {
|
||||
onConnectionLost();
|
||||
logger.debug("Cannot attach listener to port {}", serialBridgeConfig.port);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void disconnect() {
|
||||
final SerialPort serialPort = this.serialPort;
|
||||
if (serialPort != null) {
|
||||
serialPort.removeEventListener();
|
||||
serialPort.close();
|
||||
this.serialPort = null;
|
||||
}
|
||||
|
||||
super.disconnect();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_SENSOR_TEMPERATURE;
|
||||
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.measure.quantity.Temperature;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.velbus.internal.config.VelbusSensorConfig;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusSensorTemperatureRequestPacket;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
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.thing.ThingStatusDetail;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
/**
|
||||
* The {@link VelbusTemperatureSensorHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class VelbusTemperatureSensorHandler extends VelbusSensorWithAlarmClockHandler {
|
||||
private @Nullable ScheduledFuture<?> refreshJob;
|
||||
private @NonNullByDefault({}) VelbusSensorConfig sensorConfig;
|
||||
private ChannelUID temperatureChannel;
|
||||
|
||||
public VelbusTemperatureSensorHandler(Thing thing, int numberOfSubAddresses, ChannelUID temperatureChannel) {
|
||||
super(thing, numberOfSubAddresses);
|
||||
|
||||
this.temperatureChannel = temperatureChannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
this.sensorConfig = getConfigAs(VelbusSensorConfig.class);
|
||||
|
||||
super.initialize();
|
||||
|
||||
initializeAutomaticRefresh();
|
||||
}
|
||||
|
||||
private void initializeAutomaticRefresh() {
|
||||
int refreshInterval = this.sensorConfig.refresh;
|
||||
|
||||
if (refreshInterval > 0) {
|
||||
startAutomaticRefresh(refreshInterval);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
final ScheduledFuture<?> refreshJob = this.refreshJob;
|
||||
if (refreshJob != null) {
|
||||
refreshJob.cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void startAutomaticRefresh(int refreshInterval) {
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
refreshJob = scheduler.scheduleWithFixedDelay(() -> {
|
||||
sendSensorReadoutRequest(velbusBridgeHandler);
|
||||
}, 0, refreshInterval, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
super.handleCommand(channelUID, command);
|
||||
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
if (channelUID.equals(temperatureChannel)) {
|
||||
sendSensorReadoutRequest(velbusBridgeHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void sendSensorReadoutRequest(VelbusBridgeHandler velbusBridgeHandler) {
|
||||
VelbusSensorTemperatureRequestPacket packet = new VelbusSensorTemperatureRequestPacket(
|
||||
getModuleAddress().getAddress());
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceived(byte[] packet) {
|
||||
super.onPacketReceived(packet);
|
||||
|
||||
logger.trace("onPacketReceived() was called");
|
||||
|
||||
if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
|
||||
byte command = packet[4];
|
||||
|
||||
if (command == COMMAND_SENSOR_TEMPERATURE && packet.length >= 6) {
|
||||
byte highByteCurrentSensorTemperature = packet[5];
|
||||
byte lowByteCurrentSensorTemperature = packet[6];
|
||||
|
||||
boolean negative = (highByteCurrentSensorTemperature & 0x80) == 0x80;
|
||||
double temperature = ((((highByteCurrentSensorTemperature & 0x7f) << 3)
|
||||
+ ((lowByteCurrentSensorTemperature & 0xff) >> 5)) - (negative ? 0x400 : 0)) * 0.0625;
|
||||
QuantityType<Temperature> state = new QuantityType<>(temperature, SIUnits.CELSIUS);
|
||||
updateState(temperatureChannel, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusSensorSettingsRequestPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusSetTemperaturePacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusThermostatModePacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusThermostatOperatingModePacket;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
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.CommonTriggerEvents;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
/**
|
||||
* The {@link VelbusThermostatHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class VelbusThermostatHandler extends VelbusTemperatureSensorHandler {
|
||||
private static final double THERMOSTAT_TEMPERATURE_SETPOINT_RESOLUTION = 0.5;
|
||||
|
||||
private static final StringType OPERATING_MODE_HEATING = new StringType("HEATING");
|
||||
private static final StringType OPERATING_MODE_COOLING = new StringType("COOLING");
|
||||
|
||||
private static final byte OPERATING_MODE_MASK = (byte) 0x80;
|
||||
private static final byte COOLING_MODE_MASK = (byte) 0x80;
|
||||
|
||||
private static final StringType MODE_COMFORT = new StringType("COMFORT");
|
||||
private static final StringType MODE_DAY = new StringType("DAY");
|
||||
private static final StringType MODE_NIGHT = new StringType("NIGHT");
|
||||
private static final StringType MODE_SAFE = new StringType("SAFE");
|
||||
|
||||
private static final byte MODE_MASK = (byte) 0x70;
|
||||
private static final byte COMFORT_MODE_MASK = (byte) 0x40;
|
||||
private static final byte DAY_MODE_MASK = (byte) 0x20;
|
||||
private static final byte NIGHT_MODE_MASK = (byte) 0x10;
|
||||
|
||||
private final ChannelUID currentTemperatureSetpointChannel = new ChannelUID(thing.getUID(), "thermostat",
|
||||
"currentTemperatureSetpoint");
|
||||
private final ChannelUID heatingModeComfortTemperatureSetpointChannel = new ChannelUID(thing.getUID(), "thermostat",
|
||||
"heatingModeComfortTemperatureSetpoint");
|
||||
private final ChannelUID heatingModeDayTemperatureSetpointChannel = new ChannelUID(thing.getUID(), "thermostat",
|
||||
"heatingModeDayTemperatureSetpoint");
|
||||
private final ChannelUID heatingModeNightTemperatureSetpointChannel = new ChannelUID(thing.getUID(), "thermostat",
|
||||
"heatingModeNightTemperatureSetpoint");
|
||||
private final ChannelUID heatingModeAntifrostTemperatureSetpointChannel = new ChannelUID(thing.getUID(),
|
||||
"thermostat", "heatingModeAntiFrostTemperatureSetpoint");
|
||||
private final ChannelUID coolingModeComfortTemperatureSetpointChannel = new ChannelUID(thing.getUID(), "thermostat",
|
||||
"coolingModeComfortTemperatureSetpoint");
|
||||
private final ChannelUID coolingModeDayTemperatureSetpointChannel = new ChannelUID(thing.getUID(), "thermostat",
|
||||
"coolingModeDayTemperatureSetpoint");
|
||||
private final ChannelUID coolingModeNightTemperatureSetpointChannel = new ChannelUID(thing.getUID(), "thermostat",
|
||||
"coolingModeNightTemperatureSetpoint");
|
||||
private final ChannelUID coolingModeSafeTemperatureSetpointChannel = new ChannelUID(thing.getUID(), "thermostat",
|
||||
"coolingModeSafeTemperatureSetpoint");
|
||||
private final ChannelUID operatingModeChannel = new ChannelUID(thing.getUID(), "thermostat", "operatingMode");
|
||||
private final ChannelUID modeChannel = new ChannelUID(thing.getUID(), "thermostat", "mode");
|
||||
private final ChannelUID heaterChannel = new ChannelUID(thing.getUID(), "thermostat", "heater");
|
||||
private final ChannelUID boostChannel = new ChannelUID(thing.getUID(), "thermostat", "boost");
|
||||
private final ChannelUID pumpChannel = new ChannelUID(thing.getUID(), "thermostat", "pump");
|
||||
private final ChannelUID coolerChannel = new ChannelUID(thing.getUID(), "thermostat", "cooler");
|
||||
private final ChannelUID alarm1Channel = new ChannelUID(thing.getUID(), "thermostat", "alarm1");
|
||||
private final ChannelUID alarm2Channel = new ChannelUID(thing.getUID(), "thermostat", "alarm2");
|
||||
private final ChannelUID alarm3Channel = new ChannelUID(thing.getUID(), "thermostat", "alarm3");
|
||||
private final ChannelUID alarm4Channel = new ChannelUID(thing.getUID(), "thermostat", "alarm4");
|
||||
|
||||
public VelbusThermostatHandler(Thing thing, int numberOfSubAddresses, ChannelUID temperatureChannel) {
|
||||
super(thing, numberOfSubAddresses, temperatureChannel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
super.handleCommand(channelUID, command);
|
||||
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isThermostatChannel(channelUID) && command instanceof RefreshType) {
|
||||
VelbusSensorSettingsRequestPacket packet = new VelbusSensorSettingsRequestPacket(
|
||||
getModuleAddress().getAddress());
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
} else if (isThermostatChannel(channelUID)
|
||||
&& (command instanceof QuantityType<?> || command instanceof DecimalType)) {
|
||||
byte temperatureVariable = determineTemperatureVariable(channelUID);
|
||||
QuantityType<?> temperatureInDegreesCelcius = (command instanceof QuantityType<?>)
|
||||
? ((QuantityType<?>) command).toUnit(SIUnits.CELSIUS)
|
||||
: new QuantityType<>(((DecimalType) command), SIUnits.CELSIUS);
|
||||
|
||||
if (temperatureInDegreesCelcius != null) {
|
||||
byte temperature = convertToTwoComplementByte(temperatureInDegreesCelcius.doubleValue(),
|
||||
THERMOSTAT_TEMPERATURE_SETPOINT_RESOLUTION);
|
||||
|
||||
VelbusSetTemperaturePacket packet = new VelbusSetTemperaturePacket(getModuleAddress().getAddress(),
|
||||
temperatureVariable, temperature);
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
} else if (channelUID.equals(operatingModeChannel) && command instanceof StringType) {
|
||||
byte commandByte = ((StringType) command).equals(OPERATING_MODE_HEATING) ? COMMAND_SET_HEATING_MODE
|
||||
: COMMAND_SET_COOLING_MODE;
|
||||
|
||||
VelbusThermostatOperatingModePacket packet = new VelbusThermostatOperatingModePacket(
|
||||
getModuleAddress().getAddress(), commandByte);
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
} else if (channelUID.equals(modeChannel) && command instanceof StringType) {
|
||||
byte commandByte = COMMAND_SWITCH_TO_SAFE_MODE;
|
||||
|
||||
StringType stringTypeCommand = (StringType) command;
|
||||
if (stringTypeCommand.equals(MODE_COMFORT)) {
|
||||
commandByte = COMMAND_SWITCH_TO_COMFORT_MODE;
|
||||
} else if (stringTypeCommand.equals(MODE_DAY)) {
|
||||
commandByte = COMMAND_SWITCH_TO_DAY_MODE;
|
||||
} else if (stringTypeCommand.equals(MODE_NIGHT)) {
|
||||
commandByte = COMMAND_SWITCH_TO_NIGHT_MODE;
|
||||
}
|
||||
|
||||
VelbusThermostatModePacket packet = new VelbusThermostatModePacket(getModuleAddress().getAddress(),
|
||||
commandByte);
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
} else {
|
||||
logger.debug("The command '{}' is not supported by this handler.", command.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceived(byte[] packet) {
|
||||
super.onPacketReceived(packet);
|
||||
|
||||
logger.trace("onPacketReceived() was called");
|
||||
|
||||
if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
|
||||
byte address = packet[2];
|
||||
byte command = packet[4];
|
||||
|
||||
if (command == COMMAND_TEMP_SENSOR_SETTINGS_PART1 && packet.length >= 9) {
|
||||
byte currentTemperatureSetByte = packet[5];
|
||||
byte heatingModeComfortTemperatureSetByte = packet[6];
|
||||
byte heatingModeDayTemperatureSetByte = packet[7];
|
||||
byte heatingModeNightTemperatureSetByte = packet[8];
|
||||
byte heatingModeAntiFrostTemperatureSetByte = packet[9];
|
||||
|
||||
double currentTemperatureSet = convertFromTwoComplementByte(currentTemperatureSetByte,
|
||||
THERMOSTAT_TEMPERATURE_SETPOINT_RESOLUTION);
|
||||
double heatingModeComfortTemperatureSet = convertFromTwoComplementByte(
|
||||
heatingModeComfortTemperatureSetByte, THERMOSTAT_TEMPERATURE_SETPOINT_RESOLUTION);
|
||||
double heatingModeDayTemperatureSet = convertFromTwoComplementByte(heatingModeDayTemperatureSetByte,
|
||||
THERMOSTAT_TEMPERATURE_SETPOINT_RESOLUTION);
|
||||
double heatingModeNightTemperatureSet = convertFromTwoComplementByte(heatingModeNightTemperatureSetByte,
|
||||
THERMOSTAT_TEMPERATURE_SETPOINT_RESOLUTION);
|
||||
double heatingModeAntiFrostTemperatureSet = convertFromTwoComplementByte(
|
||||
heatingModeAntiFrostTemperatureSetByte, THERMOSTAT_TEMPERATURE_SETPOINT_RESOLUTION);
|
||||
|
||||
updateState(currentTemperatureSetpointChannel,
|
||||
new QuantityType<>(currentTemperatureSet, SIUnits.CELSIUS));
|
||||
updateState(heatingModeComfortTemperatureSetpointChannel,
|
||||
new QuantityType<>(heatingModeComfortTemperatureSet, SIUnits.CELSIUS));
|
||||
updateState(heatingModeDayTemperatureSetpointChannel,
|
||||
new QuantityType<>(heatingModeDayTemperatureSet, SIUnits.CELSIUS));
|
||||
updateState(heatingModeNightTemperatureSetpointChannel,
|
||||
new QuantityType<>(heatingModeNightTemperatureSet, SIUnits.CELSIUS));
|
||||
updateState(heatingModeAntifrostTemperatureSetpointChannel,
|
||||
new QuantityType<>(heatingModeAntiFrostTemperatureSet, SIUnits.CELSIUS));
|
||||
} else if (command == COMMAND_TEMP_SENSOR_SETTINGS_PART2 && packet.length >= 8) {
|
||||
byte coolingModeComfortTemperatureSetByte = packet[5];
|
||||
byte coolingModeDayTemperatureSetByte = packet[6];
|
||||
byte coolingModeNightTemperatureSetByte = packet[7];
|
||||
byte coolingModeSafeTemperatureSetByte = packet[8];
|
||||
|
||||
double coolingModeComfortTemperatureSet = convertFromTwoComplementByte(
|
||||
coolingModeComfortTemperatureSetByte, THERMOSTAT_TEMPERATURE_SETPOINT_RESOLUTION);
|
||||
double coolingModeDayTemperatureSet = convertFromTwoComplementByte(coolingModeDayTemperatureSetByte,
|
||||
THERMOSTAT_TEMPERATURE_SETPOINT_RESOLUTION);
|
||||
double coolingModeNightTemperatureSet = convertFromTwoComplementByte(coolingModeNightTemperatureSetByte,
|
||||
THERMOSTAT_TEMPERATURE_SETPOINT_RESOLUTION);
|
||||
double coolingModeSafeTemperatureSet = convertFromTwoComplementByte(coolingModeSafeTemperatureSetByte,
|
||||
THERMOSTAT_TEMPERATURE_SETPOINT_RESOLUTION);
|
||||
|
||||
updateState(coolingModeComfortTemperatureSetpointChannel,
|
||||
new QuantityType<>(coolingModeComfortTemperatureSet, SIUnits.CELSIUS));
|
||||
updateState(coolingModeDayTemperatureSetpointChannel,
|
||||
new QuantityType<>(coolingModeDayTemperatureSet, SIUnits.CELSIUS));
|
||||
updateState(coolingModeNightTemperatureSetpointChannel,
|
||||
new QuantityType<>(coolingModeNightTemperatureSet, SIUnits.CELSIUS));
|
||||
updateState(coolingModeSafeTemperatureSetpointChannel,
|
||||
new QuantityType<>(coolingModeSafeTemperatureSet, SIUnits.CELSIUS));
|
||||
} else if (command == COMMAND_TEMP_SENSOR_STATUS && packet.length >= 9) {
|
||||
byte operatingMode = packet[5];
|
||||
byte targetTemperature = packet[9];
|
||||
|
||||
if ((operatingMode & OPERATING_MODE_MASK) == COOLING_MODE_MASK) {
|
||||
updateState(operatingModeChannel, OPERATING_MODE_COOLING);
|
||||
} else {
|
||||
updateState(operatingModeChannel, OPERATING_MODE_HEATING);
|
||||
}
|
||||
|
||||
if ((operatingMode & MODE_MASK) == COMFORT_MODE_MASK) {
|
||||
updateState(modeChannel, MODE_COMFORT);
|
||||
} else if ((operatingMode & MODE_MASK) == DAY_MODE_MASK) {
|
||||
updateState(modeChannel, MODE_DAY);
|
||||
} else if ((operatingMode & MODE_MASK) == NIGHT_MODE_MASK) {
|
||||
updateState(modeChannel, MODE_NIGHT);
|
||||
} else {
|
||||
updateState(modeChannel, MODE_SAFE);
|
||||
}
|
||||
|
||||
double targetTemperatureValue = convertFromTwoComplementByte(targetTemperature,
|
||||
THERMOSTAT_TEMPERATURE_SETPOINT_RESOLUTION);
|
||||
updateState(currentTemperatureSetpointChannel,
|
||||
new QuantityType<>(targetTemperatureValue, SIUnits.CELSIUS));
|
||||
} else if (address != this.getModuleAddress().getAddress() && command == COMMAND_PUSH_BUTTON_STATUS) {
|
||||
byte outputChannelsJustActivated = packet[5];
|
||||
byte outputChannelsJustDeactivated = packet[6];
|
||||
|
||||
triggerThermostatChannels(outputChannelsJustActivated, CommonTriggerEvents.PRESSED);
|
||||
triggerThermostatChannels(outputChannelsJustDeactivated, CommonTriggerEvents.RELEASED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void triggerThermostatChannels(byte outputChannels, String event) {
|
||||
if ((outputChannels & 0x01) == 0x01) {
|
||||
triggerChannel(heaterChannel, event);
|
||||
}
|
||||
if ((outputChannels & 0x02) == 0x02) {
|
||||
triggerChannel(boostChannel, event);
|
||||
}
|
||||
if ((outputChannels & 0x04) == 0x04) {
|
||||
triggerChannel(pumpChannel, event);
|
||||
}
|
||||
if ((outputChannels & 0x08) == 0x08) {
|
||||
triggerChannel(coolerChannel, event);
|
||||
}
|
||||
if ((outputChannels & 0x10) == 0x10) {
|
||||
triggerChannel(alarm1Channel, event);
|
||||
}
|
||||
if ((outputChannels & 0x20) == 0x20) {
|
||||
triggerChannel(alarm2Channel, event);
|
||||
}
|
||||
if ((outputChannels & 0x40) == 0x40) {
|
||||
triggerChannel(alarm3Channel, event);
|
||||
}
|
||||
if ((outputChannels & 0x80) == 0x80) {
|
||||
triggerChannel(alarm4Channel, event);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isThermostatChannel(ChannelUID channelUID) {
|
||||
return channelUID.equals(currentTemperatureSetpointChannel)
|
||||
|| channelUID.equals(heatingModeComfortTemperatureSetpointChannel)
|
||||
|| channelUID.equals(heatingModeDayTemperatureSetpointChannel)
|
||||
|| channelUID.equals(heatingModeNightTemperatureSetpointChannel)
|
||||
|| channelUID.equals(heatingModeAntifrostTemperatureSetpointChannel)
|
||||
|| channelUID.equals(coolingModeComfortTemperatureSetpointChannel)
|
||||
|| channelUID.equals(coolingModeDayTemperatureSetpointChannel)
|
||||
|| channelUID.equals(coolingModeNightTemperatureSetpointChannel)
|
||||
|| channelUID.equals(coolingModeSafeTemperatureSetpointChannel)
|
||||
|| channelUID.equals(operatingModeChannel) || channelUID.equals(modeChannel);
|
||||
}
|
||||
|
||||
protected byte determineTemperatureVariable(ChannelUID channelUID) {
|
||||
if (channelUID.equals(currentTemperatureSetpointChannel)) {
|
||||
return 0x00;
|
||||
} else if (channelUID.equals(heatingModeComfortTemperatureSetpointChannel)) {
|
||||
return 0x01;
|
||||
} else if (channelUID.equals(heatingModeDayTemperatureSetpointChannel)) {
|
||||
return 0x02;
|
||||
} else if (channelUID.equals(heatingModeNightTemperatureSetpointChannel)) {
|
||||
return 0x03;
|
||||
} else if (channelUID.equals(heatingModeAntifrostTemperatureSetpointChannel)) {
|
||||
return 0x04;
|
||||
} else if (channelUID.equals(coolingModeComfortTemperatureSetpointChannel)) {
|
||||
return 0x07;
|
||||
} else if (channelUID.equals(coolingModeDayTemperatureSetpointChannel)) {
|
||||
return 0x08;
|
||||
} else if (channelUID.equals(coolingModeNightTemperatureSetpointChannel)) {
|
||||
return 0x09;
|
||||
} else if (channelUID.equals(coolingModeSafeTemperatureSetpointChannel)) {
|
||||
return 0x0A;
|
||||
} else {
|
||||
throw new IllegalArgumentException("The given channelUID is not a thermostat channel: " + channelUID);
|
||||
}
|
||||
}
|
||||
|
||||
protected double convertFromTwoComplementByte(byte value, double resolution) {
|
||||
return ((value & 0x80) == 0x00) ? value * resolution : ((value & 0x7F) - 0x80) * resolution;
|
||||
}
|
||||
|
||||
protected byte convertToTwoComplementByte(double value, double resolution) {
|
||||
return (byte) (value / resolution);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.SUB_ADDRESS;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.velbus.internal.VelbusModuleAddress;
|
||||
import org.openhab.binding.velbus.internal.VelbusPacketListener;
|
||||
import org.openhab.binding.velbus.internal.config.VelbusThingConfig;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusReadMemoryBlockPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusReadMemoryPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusStatusRequestPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusWriteMemoryPacket;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Channel;
|
||||
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.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.builder.ChannelBuilder;
|
||||
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||
import org.openhab.core.thing.type.ChannelKind;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.openhab.core.util.HexUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Base ThingHandler for all Velbus handlers.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class VelbusThingHandler extends BaseThingHandler implements VelbusPacketListener {
|
||||
protected final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
protected @Nullable VelbusThingConfig velbusThingConfig;
|
||||
private @Nullable VelbusBridgeHandler velbusBridgeHandler;
|
||||
private @NonNullByDefault({}) VelbusModuleAddress velbusModuleAddress;
|
||||
|
||||
private int numberOfSubAddresses;
|
||||
|
||||
public VelbusThingHandler(Thing thing, int numberOfSubAddresses) {
|
||||
super(thing);
|
||||
|
||||
this.numberOfSubAddresses = numberOfSubAddresses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initializing velbus handler.");
|
||||
|
||||
this.velbusThingConfig = getConfigAs(VelbusThingConfig.class);
|
||||
|
||||
Bridge bridge = getBridge();
|
||||
initializeThing(bridge == null ? ThingStatus.OFFLINE : bridge.getStatus());
|
||||
initializeChannelNames();
|
||||
initializeChannelStates();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRemoval() {
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
|
||||
if (velbusBridgeHandler != null && velbusModuleAddress != null) {
|
||||
byte[] activeAddresses = velbusModuleAddress.getActiveAddresses();
|
||||
|
||||
for (int i = 0; i < activeAddresses.length; i++) {
|
||||
velbusBridgeHandler.unregisterRelayStatusListener(activeAddresses[i]);
|
||||
}
|
||||
}
|
||||
|
||||
super.handleRemoval();
|
||||
}
|
||||
|
||||
protected VelbusModuleAddress getModuleAddress() {
|
||||
return velbusModuleAddress;
|
||||
}
|
||||
|
||||
protected void updateChannelLabel(ChannelUID channelUID, String channelName) {
|
||||
Channel existingChannel = thing.getChannel(channelUID.getId());
|
||||
if (existingChannel != null) {
|
||||
String acceptedItem = existingChannel.getAcceptedItemType();
|
||||
Configuration configuration = existingChannel.getConfiguration();
|
||||
Set<String> defaultTags = existingChannel.getDefaultTags();
|
||||
String description = existingChannel.getDescription();
|
||||
ChannelKind kind = existingChannel.getKind();
|
||||
Map<String, String> properties = existingChannel.getProperties();
|
||||
ChannelTypeUID type = existingChannel.getChannelTypeUID();
|
||||
|
||||
ThingBuilder thingBuilder = editThing();
|
||||
Channel channel = ChannelBuilder.create(channelUID, acceptedItem).withConfiguration(configuration)
|
||||
.withDefaultTags(defaultTags).withDescription(description != null ? description : "").withKind(kind)
|
||||
.withLabel(channelName).withProperties(properties).withType(type).build();
|
||||
thingBuilder.withoutChannel(channelUID).withChannel(channel);
|
||||
updateThing(thingBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeThing(ThingStatus bridgeStatus) {
|
||||
this.velbusModuleAddress = createVelbusModuleAddress(numberOfSubAddresses);
|
||||
|
||||
if (this.velbusModuleAddress != null) {
|
||||
logger.debug("initializeThing thing {} with address {} bridge status {}", getThing().getUID(),
|
||||
velbusModuleAddress.getAddress(), bridgeStatus);
|
||||
|
||||
// note: this call implicitly registers our handler as a listener on
|
||||
// the bridge
|
||||
if (getVelbusBridgeHandler() != null) {
|
||||
if (bridgeStatus == ThingStatus.ONLINE) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, "Address is not known!");
|
||||
}
|
||||
}
|
||||
|
||||
protected @Nullable VelbusModuleAddress createVelbusModuleAddress(int numberOfSubAddresses) {
|
||||
final VelbusThingConfig velbusThingConfig = this.velbusThingConfig;
|
||||
if (velbusThingConfig != null) {
|
||||
byte address = hexToByte(velbusThingConfig.address);
|
||||
|
||||
byte[] subAddresses = new byte[numberOfSubAddresses];
|
||||
for (int i = 0; i < numberOfSubAddresses; i++) {
|
||||
String propertyKey = SUB_ADDRESS + (i + 1);
|
||||
if (getThing().getProperties().containsKey(propertyKey)) {
|
||||
String subAddress = getThing().getProperties().get(propertyKey);
|
||||
subAddresses[i] = hexToByte(subAddress);
|
||||
} else {
|
||||
subAddresses[i] = (byte) 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
return new VelbusModuleAddress(address, subAddresses);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void initializeChannelNames() {
|
||||
List<Channel> channels = this.getThing().getChannels();
|
||||
for (int i = 0; i < channels.size(); i++) {
|
||||
Channel channel = channels.get(i);
|
||||
String channelUID = channel.getUID().getIdWithoutGroup();
|
||||
|
||||
if (getConfig().containsKey(channelUID)) {
|
||||
String channelName = getConfig().get(channelUID).toString();
|
||||
if (!channelName.equals(channel.getLabel())) {
|
||||
updateChannelLabel(channel.getUID(), channelName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeChannelStates() {
|
||||
VelbusBridgeHandler velbusBridgeHandler = this.velbusBridgeHandler;
|
||||
if (velbusBridgeHandler != null) {
|
||||
VelbusStatusRequestPacket packet = new VelbusStatusRequestPacket(getModuleAddress().getAddress());
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
}
|
||||
|
||||
protected byte hexToByte(String hexString) {
|
||||
if (hexString.length() > 2) {
|
||||
throw new IllegalArgumentException("hexString contains more than one byte: " + hexString);
|
||||
}
|
||||
|
||||
return HexUtils.hexToBytes(hexString)[0];
|
||||
}
|
||||
|
||||
protected void sendReadMemoryBlockPacket(VelbusBridgeHandler velbusBridgeHandler, int memoryAddress) {
|
||||
VelbusReadMemoryBlockPacket packet = new VelbusReadMemoryBlockPacket(getModuleAddress().getAddress(),
|
||||
memoryAddress);
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
|
||||
protected void sendReadMemoryPacket(VelbusBridgeHandler velbusBridgeHandler, int memoryAddress) {
|
||||
VelbusReadMemoryPacket packet = new VelbusReadMemoryPacket(getModuleAddress().getAddress(), memoryAddress);
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
|
||||
protected void sendWriteMemoryPacket(VelbusBridgeHandler velbusBridgeHandler, int memoryAddress, byte data) {
|
||||
VelbusWriteMemoryPacket packet = new VelbusWriteMemoryPacket(getModuleAddress().getAddress(), memoryAddress,
|
||||
data);
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
|
||||
protected @Nullable synchronized VelbusBridgeHandler getVelbusBridgeHandler() {
|
||||
if (this.velbusBridgeHandler == null) {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
return null;
|
||||
}
|
||||
ThingHandler bridgeHandler = bridge.getHandler();
|
||||
if (bridgeHandler instanceof VelbusBridgeHandler) {
|
||||
VelbusBridgeHandler velbusBridgeHandler = (VelbusBridgeHandler) bridgeHandler;
|
||||
this.velbusBridgeHandler = velbusBridgeHandler;
|
||||
|
||||
if (velbusModuleAddress != null) {
|
||||
byte[] activeAddresses = velbusModuleAddress.getActiveAddresses();
|
||||
|
||||
for (int i = 0; i < activeAddresses.length; i++) {
|
||||
velbusBridgeHandler.registerPacketListener(activeAddresses[i], this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.velbusBridgeHandler;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.THING_TYPE_VMB1TS;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link VelbusVMB1TSHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusVMB1TSHandler extends VelbusThermostatHandler {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(Arrays.asList(THING_TYPE_VMB1TS));
|
||||
|
||||
public VelbusVMB1TSHandler(Thing thing) {
|
||||
super(thing, 0, new ChannelUID(thing.getUID(), "input", "CH1"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
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.velbus.internal.VelbusChannelIdentifier;
|
||||
import org.openhab.binding.velbus.internal.config.VelbusSensorConfig;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusDimmerPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusSensorReadoutRequestPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusStatusRequestPacket;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.unit.MetricPrefix;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
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.ThingTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
/**
|
||||
* The {@link VelbusVMB4ANHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusVMB4ANHandler extends VelbusSensorWithAlarmClockHandler {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(Arrays.asList(THING_TYPE_VMB4AN));
|
||||
|
||||
private static final String ALARM_GROUP = "alarm";
|
||||
private static final String ANALOG_INPUT_GROUP = "analogInput";
|
||||
private static final String ANALOG_OUTPUT_GROUP = "analogOutput";
|
||||
private static final String RAW_CHANNEL_SUFFIX = "Raw";
|
||||
|
||||
private static final byte VOLTAGE_SENSOR_TYPE = 0x00;
|
||||
private static final byte CURRENT_SENSOR_TYPE = 0x01;
|
||||
private static final byte RESISTANCE_SENSOR_TYPE = 0x02;
|
||||
private static final byte PERIOD_MEASUREMENT_SENSOR_TYPE = 0x03;
|
||||
|
||||
private String[] channelText = new String[] { "", "", "", "" };
|
||||
|
||||
private @Nullable ScheduledFuture<?> refreshJob;
|
||||
private @NonNullByDefault({}) VelbusSensorConfig sensorConfig;
|
||||
|
||||
public VelbusVMB4ANHandler(Thing thing) {
|
||||
super(thing, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
this.sensorConfig = getConfigAs(VelbusSensorConfig.class);
|
||||
|
||||
super.initialize();
|
||||
|
||||
initializeAutomaticRefresh();
|
||||
}
|
||||
|
||||
private void initializeAutomaticRefresh() {
|
||||
int refreshInterval = sensorConfig.refresh;
|
||||
|
||||
if (refreshInterval > 0) {
|
||||
startAutomaticRefresh(refreshInterval);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
final ScheduledFuture<?> refreshJob = this.refreshJob;
|
||||
if (refreshJob != null) {
|
||||
refreshJob.cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void startAutomaticRefresh(int refreshInterval) {
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
refreshJob = scheduler.scheduleWithFixedDelay(() -> {
|
||||
sendSensorReadoutRequest(velbusBridgeHandler, ALL_CHANNELS);
|
||||
}, 0, refreshInterval, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
super.handleCommand(channelUID, command);
|
||||
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
byte channelByte = convertChannelUIDToChannelByte(channelUID);
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
VelbusStatusRequestPacket packet = new VelbusStatusRequestPacket(channelByte);
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
} else if (command instanceof PercentType && isAnalogOutputChannel(channelUID)) {
|
||||
VelbusDimmerPacket packet = new VelbusDimmerPacket(
|
||||
new VelbusChannelIdentifier(this.getModuleAddress().getAddress(), channelByte), COMMAND_SET_VALUE,
|
||||
((PercentType) command).byteValue(), 0x00, false);
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
}
|
||||
|
||||
protected void sendSensorReadoutRequest(VelbusBridgeHandler velbusBridgeHandler, byte channel) {
|
||||
VelbusSensorReadoutRequestPacket packet = new VelbusSensorReadoutRequestPacket(getModuleAddress().getAddress(),
|
||||
channel);
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceived(byte[] packet) {
|
||||
super.onPacketReceived(packet);
|
||||
|
||||
logger.trace("onPacketReceived() was called");
|
||||
|
||||
if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
|
||||
byte command = packet[4];
|
||||
|
||||
if (command == COMMAND_SENSOR_RAW_DATA && packet.length >= 10) {
|
||||
byte channel = packet[5];
|
||||
byte operatingMode = packet[6];
|
||||
byte upperByteSensorValue = packet[7];
|
||||
byte highByteSensorValue = packet[8];
|
||||
byte lowByteSensorValue = packet[9];
|
||||
|
||||
double sensorValue = (((upperByteSensorValue & 0xff) << 16) + ((highByteSensorValue & 0xff) << 8)
|
||||
+ (lowByteSensorValue & 0xff));
|
||||
String channelUID = convertAnalogInputChannelByteToRawChannelUID(channel);
|
||||
|
||||
switch (operatingMode) {
|
||||
case VOLTAGE_SENSOR_TYPE:
|
||||
double voltageResolution = 0.25;
|
||||
double voltageSensorValueState = sensorValue * voltageResolution;
|
||||
updateState(channelUID,
|
||||
new QuantityType<>(voltageSensorValueState, MetricPrefix.MILLI(SmartHomeUnits.VOLT)));
|
||||
break;
|
||||
case CURRENT_SENSOR_TYPE:
|
||||
double currentResolution = 5;
|
||||
double currentSensorValueState = sensorValue * currentResolution;
|
||||
updateState(channelUID,
|
||||
new QuantityType<>(currentSensorValueState, MetricPrefix.MICRO(SmartHomeUnits.AMPERE)));
|
||||
break;
|
||||
case RESISTANCE_SENSOR_TYPE:
|
||||
double resistanceResolution = 0.25;
|
||||
double resistanceSensorValueState = sensorValue * resistanceResolution;
|
||||
updateState(channelUID, new QuantityType<>(resistanceSensorValueState, SmartHomeUnits.OHM));
|
||||
break;
|
||||
case PERIOD_MEASUREMENT_SENSOR_TYPE:
|
||||
double periodResolution = 0.5;
|
||||
double periodSensorValueState = sensorValue * periodResolution;
|
||||
updateState(channelUID,
|
||||
new QuantityType<>(periodSensorValueState, MetricPrefix.MICRO(SmartHomeUnits.SECOND)));
|
||||
break;
|
||||
}
|
||||
} else if (command == COMMAND_TEXT) {
|
||||
byte channel = packet[5];
|
||||
byte textStartPosition = packet[6];
|
||||
|
||||
StringBuilder contents = new StringBuilder();
|
||||
for (int i = 7; i < packet.length - 2; i++) {
|
||||
byte currentChar = packet[i];
|
||||
if (currentChar == (byte) -0x50) {
|
||||
contents.append("°");
|
||||
} else if (currentChar != (byte) 0x00) {
|
||||
contents.append((char) currentChar);
|
||||
}
|
||||
}
|
||||
|
||||
channelText[channel - 9] = channelText[channel - 9].substring(0, textStartPosition)
|
||||
+ contents.toString()
|
||||
+ (channelText[channel - 9].length() > textStartPosition + 5 ? channelText[channel - 9]
|
||||
.substring(textStartPosition + 5, channelText[channel - 9].length()) : "");
|
||||
|
||||
String channelUID = convertAnalogInputChannelByteToChannelUID(channel);
|
||||
updateState(channelUID, new StringType(channelText[channel - 9]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected byte convertChannelUIDToChannelByte(ChannelUID channelUID) {
|
||||
if (isAlarmChannel(channelUID)) {
|
||||
return convertAlarmChannelUIDToChannelByte(channelUID);
|
||||
} else if (isTextAnalogInputChannel(channelUID)) {
|
||||
return convertTextAnalogInputChannelUIDToChannelByte(channelUID);
|
||||
} else if (isRawAnalogInputChannel(channelUID)) {
|
||||
return convertRawAnalogInputChannelUIDToChannelByte(channelUID);
|
||||
} else if (isAnalogOutputChannel(channelUID)) {
|
||||
return convertAnalogOutputChannelUIDToChannelByte(channelUID);
|
||||
} else {
|
||||
throw new UnsupportedOperationException(
|
||||
"The channel '" + channelUID + "' is not supported on a VMB4AN module.");
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isAlarmChannel(ChannelUID channelUID) {
|
||||
return ALARM_GROUP.equals(channelUID.getGroupId());
|
||||
}
|
||||
|
||||
protected byte convertAlarmChannelUIDToChannelByte(ChannelUID channelUID) {
|
||||
return Byte.parseByte(channelUID.getIdWithoutGroup());
|
||||
}
|
||||
|
||||
protected boolean isTextAnalogInputChannel(ChannelUID channelUID) {
|
||||
return ANALOG_INPUT_GROUP.equals(channelUID.getGroupId())
|
||||
&& !channelUID.getIdWithoutGroup().endsWith(RAW_CHANNEL_SUFFIX);
|
||||
}
|
||||
|
||||
protected boolean isRawAnalogInputChannel(ChannelUID channelUID) {
|
||||
return ANALOG_INPUT_GROUP.equals(channelUID.getGroupId())
|
||||
&& channelUID.getIdWithoutGroup().endsWith(RAW_CHANNEL_SUFFIX);
|
||||
}
|
||||
|
||||
protected byte convertRawAnalogInputChannelUIDToChannelByte(ChannelUID channelUID) {
|
||||
return Byte.parseByte(channelUID.getIdWithoutGroup().replaceAll(RAW_CHANNEL_SUFFIX, ""));
|
||||
}
|
||||
|
||||
protected byte convertTextAnalogInputChannelUIDToChannelByte(ChannelUID channelUID) {
|
||||
return Byte.parseByte(channelUID.getIdWithoutGroup());
|
||||
}
|
||||
|
||||
protected String convertAnalogInputChannelByteToRawChannelUID(byte channelByte) {
|
||||
return convertAnalogInputChannelByteToChannelUID(channelByte) + RAW_CHANNEL_SUFFIX;
|
||||
}
|
||||
|
||||
protected String convertAnalogInputChannelByteToChannelUID(byte channelByte) {
|
||||
return ANALOG_INPUT_GROUP + "#" + channelByte;
|
||||
}
|
||||
|
||||
protected boolean isAnalogOutputChannel(ChannelUID channelUID) {
|
||||
return ANALOG_OUTPUT_GROUP.equals(channelUID.getGroupId());
|
||||
}
|
||||
|
||||
protected byte convertAnalogOutputChannelUIDToChannelByte(ChannelUID channelUID) {
|
||||
return Byte.parseByte(channelUID.getIdWithoutGroup());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
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.velbus.internal.VelbusChannelIdentifier;
|
||||
import org.openhab.binding.velbus.internal.config.VelbusVMB7INConfig;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusCounterStatusRequestPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusPacket;
|
||||
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.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
/**
|
||||
* The {@link VelbusVMB7INHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusVMB7INHandler extends VelbusSensorWithAlarmClockHandler {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(Arrays.asList(THING_TYPE_VMB7IN));
|
||||
|
||||
private final ChannelUID counter1Channel = new ChannelUID(thing.getUID(), "counter", "counter1");
|
||||
private final ChannelUID counter1ChannelCurrent = new ChannelUID(thing.getUID(), "counter", "counter1Current");
|
||||
private final ChannelUID counter2Channel = new ChannelUID(thing.getUID(), "counter", "counter2");
|
||||
private final ChannelUID counter2ChannelCurrent = new ChannelUID(thing.getUID(), "counter", "counter2Current");
|
||||
private final ChannelUID counter3Channel = new ChannelUID(thing.getUID(), "counter", "counter3");
|
||||
private final ChannelUID counter3ChannelCurrent = new ChannelUID(thing.getUID(), "counter", "counter3Current");
|
||||
private final ChannelUID counter4Channel = new ChannelUID(thing.getUID(), "counter", "counter4");
|
||||
private final ChannelUID counter4ChannelCurrent = new ChannelUID(thing.getUID(), "counter", "counter4Current");
|
||||
|
||||
public @NonNullByDefault({}) VelbusVMB7INConfig vmb7inConfig;
|
||||
|
||||
private @Nullable ScheduledFuture<?> refreshJob;
|
||||
|
||||
public VelbusVMB7INHandler(Thing thing) {
|
||||
super(thing, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
this.vmb7inConfig = getConfigAs(VelbusVMB7INConfig.class);
|
||||
|
||||
super.initialize();
|
||||
|
||||
initializeAutomaticRefresh();
|
||||
}
|
||||
|
||||
private void initializeAutomaticRefresh() {
|
||||
int refreshInterval = vmb7inConfig.refresh;
|
||||
|
||||
if (refreshInterval > 0) {
|
||||
startAutomaticRefresh(refreshInterval);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
final ScheduledFuture<?> refreshJob = this.refreshJob;
|
||||
if (refreshJob != null) {
|
||||
refreshJob.cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void startAutomaticRefresh(int refreshInterval) {
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
refreshJob = scheduler.scheduleWithFixedDelay(() -> {
|
||||
sendCounterStatusRequest(velbusBridgeHandler, ALL_CHANNELS);
|
||||
}, 0, refreshInterval, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
super.handleCommand(channelUID, command);
|
||||
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
if (channelUID.equals(counter1Channel)) {
|
||||
sendCounterStatusRequest(velbusBridgeHandler, (byte) 0x01);
|
||||
} else if (channelUID.equals(counter2Channel)) {
|
||||
sendCounterStatusRequest(velbusBridgeHandler, (byte) 0x02);
|
||||
} else if (channelUID.equals(counter3Channel)) {
|
||||
sendCounterStatusRequest(velbusBridgeHandler, (byte) 0x03);
|
||||
} else if (channelUID.equals(counter4Channel)) {
|
||||
sendCounterStatusRequest(velbusBridgeHandler, (byte) 0x04);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void sendCounterStatusRequest(VelbusBridgeHandler velbusBridgeHandler, byte channel) {
|
||||
VelbusCounterStatusRequestPacket packet = new VelbusCounterStatusRequestPacket(
|
||||
new VelbusChannelIdentifier(getModuleAddress().getAddress(), channel));
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceived(byte[] packet) {
|
||||
super.onPacketReceived(packet);
|
||||
|
||||
logger.trace("onPacketReceived() was called");
|
||||
|
||||
if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
|
||||
byte command = packet[4];
|
||||
|
||||
if (command == COMMAND_COUNTER_STATUS && packet.length >= 6) {
|
||||
int counterChannel = packet[5] & 0x03;
|
||||
int pulsesPerUnit = ((packet[5] & 0x7C) / 0x04) * 0x64;
|
||||
|
||||
double counterValue = ((double) (((packet[6] & 0xff) << 24) | ((packet[7] & 0xff) << 16)
|
||||
| ((packet[8] & 0xff) << 8) | (packet[9] & 0xff))) / pulsesPerUnit;
|
||||
double currentValue = (1000 * 3600)
|
||||
/ (((double) (((packet[10] & 0xff) << 8) | (packet[11] & 0xff))) * pulsesPerUnit);
|
||||
|
||||
switch (counterChannel) {
|
||||
case 0x00:
|
||||
double counter1PulseMultiplier = vmb7inConfig.counter1PulseMultiplier;
|
||||
updateState(counter1Channel, new DecimalType(counterValue / counter1PulseMultiplier));
|
||||
updateState(counter1ChannelCurrent, new DecimalType(currentValue / counter1PulseMultiplier));
|
||||
break;
|
||||
case 0x01:
|
||||
double counter2PulseMultiplier = vmb7inConfig.counter2PulseMultiplier;
|
||||
updateState(counter2Channel, new DecimalType(counterValue / counter2PulseMultiplier));
|
||||
updateState(counter2ChannelCurrent, new DecimalType(currentValue / counter2PulseMultiplier));
|
||||
break;
|
||||
case 0x02:
|
||||
double counter3PulseMultiplier = vmb7inConfig.counter3PulseMultiplier;
|
||||
updateState(counter3Channel, new DecimalType(counterValue / counter3PulseMultiplier));
|
||||
updateState(counter3ChannelCurrent, new DecimalType(currentValue / counter3PulseMultiplier));
|
||||
break;
|
||||
case 0x03:
|
||||
double counter4PulseMultiplier = vmb7inConfig.counter4PulseMultiplier;
|
||||
updateState(counter4Channel, new DecimalType(counterValue / counter4PulseMultiplier));
|
||||
updateState(counter4ChannelCurrent, new DecimalType(currentValue / counter4PulseMultiplier));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"The given channel is not a counter channel: " + counterChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link VelbusVMBELHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusVMBELHandler extends VelbusThermostatHandler {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(
|
||||
Arrays.asList(THING_TYPE_VMBEL1, THING_TYPE_VMBEL2, THING_TYPE_VMBEL4));
|
||||
|
||||
public VelbusVMBELHandler(Thing thing) {
|
||||
super(thing, 4, new ChannelUID(thing.getUID(), "input", "CH9"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.THING_TYPE_VMBELO;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link VelbusVMBELOHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusVMBELOHandler extends VelbusMemoHandler {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(Arrays.asList(THING_TYPE_VMBELO));
|
||||
|
||||
public VelbusVMBELOHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link VelbusVMBGPHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusVMBGPHandler extends VelbusThermostatHandler {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(
|
||||
Arrays.asList(THING_TYPE_VMBGP1, THING_TYPE_VMBGP1_2, THING_TYPE_VMBGP2, THING_TYPE_VMBGP2_2,
|
||||
THING_TYPE_VMBGP4, THING_TYPE_VMBGP4_2, THING_TYPE_VMBGP4PIR, THING_TYPE_VMBGP4PIR_2));
|
||||
|
||||
public VelbusVMBGPHandler(Thing thing) {
|
||||
super(thing, 4, new ChannelUID(thing.getUID(), "input", "CH9"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusPacket;
|
||||
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.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
/**
|
||||
* The {@link VelbusVMBGPOHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusVMBGPOHandler extends VelbusMemoHandler {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(
|
||||
Arrays.asList(THING_TYPE_VMBGPO, THING_TYPE_VMBGPOD, THING_TYPE_VMBGPOD_2));
|
||||
|
||||
public static final int MODULESETTINGS_MEMORY_ADDRESS = 0x02F0;
|
||||
public static final int LAST_MEMORY_LOCATION_ADDRESS = 0x1A03;
|
||||
|
||||
private final ChannelUID screensaverChannel = new ChannelUID(thing.getUID(), "oledDisplay", "SCREENSAVER");
|
||||
|
||||
private byte moduleSettings;
|
||||
|
||||
public VelbusVMBGPOHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
super.handleCommand(channelUID, command);
|
||||
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (channelUID.equals(screensaverChannel) && command instanceof RefreshType) {
|
||||
sendReadMemoryPacket(velbusBridgeHandler, MODULESETTINGS_MEMORY_ADDRESS);
|
||||
}
|
||||
|
||||
if (channelUID.equals(screensaverChannel) && command instanceof OnOffType) {
|
||||
byte screenSaverOnOffByte = (byte) ((command == OnOffType.ON) ? 0x80 : 0x00);
|
||||
moduleSettings = (byte) (screenSaverOnOffByte | (moduleSettings & 0x7F));
|
||||
sendWriteMemoryPacket(velbusBridgeHandler, MODULESETTINGS_MEMORY_ADDRESS, moduleSettings);
|
||||
sendWriteMemoryPacket(velbusBridgeHandler, LAST_MEMORY_LOCATION_ADDRESS, (byte) 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceived(byte[] packet) {
|
||||
super.onPacketReceived(packet);
|
||||
|
||||
logger.trace("onPacketReceived() was called");
|
||||
|
||||
if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
|
||||
byte command = packet[4];
|
||||
|
||||
if ((command == COMMAND_MEMORY_DATA_BLOCK && packet.length >= 11)
|
||||
|| (command == COMMAND_MEMORY_DATA && packet.length >= 8)) {
|
||||
byte highMemoryAddress = packet[5];
|
||||
byte lowMemoryAddress = packet[6];
|
||||
int memoryAddress = ((highMemoryAddress & 0xff) << 8) | (lowMemoryAddress & 0xff);
|
||||
byte[] data = (command == COMMAND_MEMORY_DATA_BLOCK)
|
||||
? new byte[] { packet[7], packet[8], packet[9], packet[10] }
|
||||
: new byte[] { packet[7] };
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
|
||||
if ((memoryAddress + i) == MODULESETTINGS_MEMORY_ADDRESS) {
|
||||
this.moduleSettings = data[i];
|
||||
OnOffType state = ((this.moduleSettings & 0x80) != 0x00) ? OnOffType.ON : OnOffType.OFF;
|
||||
updateState(screensaverChannel, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.measure.quantity.Illuminance;
|
||||
import javax.measure.quantity.Length;
|
||||
import javax.measure.quantity.Speed;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusSensorReadoutRequestPacket;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.MetricPrefix;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
/**
|
||||
* The {@link VelbusVMBMeteoHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusVMBMeteoHandler extends VelbusTemperatureSensorHandler {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(Arrays.asList(THING_TYPE_VMBMETEO));
|
||||
|
||||
private static final byte RAIN_SENSOR_CHANNEL = 0x02;
|
||||
private static final byte LIGHT_SENSOR_CHANNEL = 0x04;
|
||||
private static final byte WIND_SENSOR_CHANNEL = 0x08;
|
||||
private static final byte ALL_SENSOR_CHANNELS = RAIN_SENSOR_CHANNEL | LIGHT_SENSOR_CHANNEL | WIND_SENSOR_CHANNEL;
|
||||
|
||||
private ChannelUID rainfallChannel;
|
||||
private ChannelUID illuminanceChannel;
|
||||
private ChannelUID windspeedChannel;
|
||||
|
||||
public VelbusVMBMeteoHandler(Thing thing) {
|
||||
super(thing, 0, new ChannelUID(thing.getUID(), "weatherStation", "CH10"));
|
||||
|
||||
this.rainfallChannel = new ChannelUID(thing.getUID(), "weatherStation", "CH11");
|
||||
this.illuminanceChannel = new ChannelUID(thing.getUID(), "weatherStation", "CH12");
|
||||
this.windspeedChannel = new ChannelUID(thing.getUID(), "weatherStation", "CH13");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
super.handleCommand(channelUID, command);
|
||||
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
logger.warn("Velbus bridge handler not found. Cannot handle command without bridge.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
if (channelUID.equals(rainfallChannel)) {
|
||||
sendSensorReadoutRequest(velbusBridgeHandler, RAIN_SENSOR_CHANNEL);
|
||||
} else if (channelUID.equals(illuminanceChannel)) {
|
||||
sendSensorReadoutRequest(velbusBridgeHandler, LIGHT_SENSOR_CHANNEL);
|
||||
} else if (channelUID.equals(windspeedChannel)) {
|
||||
sendSensorReadoutRequest(velbusBridgeHandler, WIND_SENSOR_CHANNEL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sendSensorReadoutRequest(VelbusBridgeHandler velbusBridgeHandler) {
|
||||
super.sendSensorReadoutRequest(velbusBridgeHandler);
|
||||
|
||||
sendSensorReadoutRequest(velbusBridgeHandler, ALL_SENSOR_CHANNELS);
|
||||
}
|
||||
|
||||
protected void sendSensorReadoutRequest(VelbusBridgeHandler velbusBridgeHandler, byte channel) {
|
||||
VelbusSensorReadoutRequestPacket packet = new VelbusSensorReadoutRequestPacket(getModuleAddress().getAddress(),
|
||||
channel);
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getClockAlarmAndProgramSelectionIndexInModuleStatus() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceived(byte[] packet) {
|
||||
super.onPacketReceived(packet);
|
||||
|
||||
logger.trace("onPacketReceived() was called");
|
||||
|
||||
if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
|
||||
byte command = packet[4];
|
||||
|
||||
if (command == COMMAND_SENSOR_RAW_DATA && packet.length >= 10) {
|
||||
byte highByteCurrentRainValue = packet[5];
|
||||
byte lowByteCurrentRainValue = packet[6];
|
||||
byte highByteCurrentLightValue = packet[7];
|
||||
byte lowByteCurrentLightValue = packet[8];
|
||||
byte highByteCurrentWindValue = packet[9];
|
||||
byte lowByteCurrentWindValue = packet[10];
|
||||
|
||||
double rainValue = (((highByteCurrentRainValue & 0xff) << 8) + (lowByteCurrentRainValue & 0xff)) / 10;
|
||||
double lightValue = (((highByteCurrentLightValue & 0xff) << 8) + (lowByteCurrentLightValue & 0xff));
|
||||
double windValue = (((highByteCurrentWindValue & 0xff) << 8) + (lowByteCurrentWindValue & 0xff)) / 10;
|
||||
|
||||
QuantityType<Length> rainValueState = new QuantityType<>(rainValue, MetricPrefix.MILLI(SIUnits.METRE));
|
||||
QuantityType<Illuminance> lightValueState = new QuantityType<>(lightValue, SmartHomeUnits.LUX);
|
||||
QuantityType<Speed> windValueState = new QuantityType<>(windValue, SIUnits.KILOMETRE_PER_HOUR);
|
||||
|
||||
updateState(rainfallChannel, rainValueState);
|
||||
updateState(illuminanceChannel, lightValueState);
|
||||
updateState(windspeedChannel, windValueState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.handler;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.measure.quantity.Illuminance;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusLightValueRequestPacket;
|
||||
import org.openhab.binding.velbus.internal.packets.VelbusPacket;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
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.ThingTypeUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
/**
|
||||
* The {@link VelbusVMBPIROHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusVMBPIROHandler extends VelbusTemperatureSensorHandler {
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(Arrays.asList(THING_TYPE_VMBPIRO));
|
||||
|
||||
private ChannelUID illuminanceChannel;
|
||||
|
||||
public VelbusVMBPIROHandler(Thing thing) {
|
||||
super(thing, 0, new ChannelUID(thing.getUID(), "input", "CH9"));
|
||||
|
||||
this.illuminanceChannel = new ChannelUID(thing.getUID(), "input", "LIGHT");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
super.handleCommand(channelUID, command);
|
||||
|
||||
VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
|
||||
if (velbusBridgeHandler == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
if (channelUID.equals(illuminanceChannel)) {
|
||||
VelbusLightValueRequestPacket packet = new VelbusLightValueRequestPacket(
|
||||
getModuleAddress().getAddress());
|
||||
|
||||
byte[] packetBytes = packet.getBytes();
|
||||
velbusBridgeHandler.sendPacket(packetBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceived(byte[] packet) {
|
||||
super.onPacketReceived(packet);
|
||||
|
||||
logger.trace("onPacketReceived() was called");
|
||||
|
||||
if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
|
||||
byte command = packet[4];
|
||||
|
||||
if (command == COMMAND_MODULE_STATUS && packet.length >= 6) {
|
||||
byte highByteCurrentLightValue = packet[6];
|
||||
byte lowByteCurrentLightValue = packet[7];
|
||||
|
||||
double lightValue = (((highByteCurrentLightValue & 0xff) << 8) + (lowByteCurrentLightValue & 0xff));
|
||||
QuantityType<Illuminance> lightValueState = new QuantityType<>(lightValue, SmartHomeUnits.LUX);
|
||||
updateState(illuminanceChannel, lightValueState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_SWITCH_BLIND_OFF;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
|
||||
|
||||
/**
|
||||
* The {@link VelbusBlindOffPacket} represents a Velbus packet that can be used to
|
||||
* stop a moving blind.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusBlindOffPacket extends VelbusPacket {
|
||||
private byte channel;
|
||||
|
||||
public VelbusBlindOffPacket(VelbusChannelIdentifier velbusChannelIdentifier) {
|
||||
super(velbusChannelIdentifier.getAddress(), PRIO_HI);
|
||||
|
||||
this.channel = velbusChannelIdentifier.getChannelByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_SWITCH_BLIND_OFF, channel };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_BLIND_POS;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
|
||||
|
||||
/**
|
||||
* The {@link VelbusBlindPositionPacket} represents a Velbus packet that can be used to
|
||||
* set blinds to a given position.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusBlindPositionPacket extends VelbusPacket {
|
||||
private byte channel;
|
||||
private byte percentage;
|
||||
|
||||
public VelbusBlindPositionPacket(VelbusChannelIdentifier velbusChannelIdentifier, byte percentage) {
|
||||
super(velbusChannelIdentifier.getAddress(), PRIO_HI);
|
||||
|
||||
this.channel = velbusChannelIdentifier.getChannelByte();
|
||||
this.percentage = percentage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_BLIND_POS, channel, percentage };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
|
||||
|
||||
/**
|
||||
* The {@link VelbusBlindUpDownPacket} represents a Velbus packet that can be used to
|
||||
* move a blind up or down.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusBlindUpDownPacket extends VelbusPacket {
|
||||
private final byte timeoutHighByte = 0x00;
|
||||
private final byte timeoutMidByte = 0x00;
|
||||
private final byte timeoutLowByte = 0x00;
|
||||
|
||||
private byte command;
|
||||
private byte channel;
|
||||
|
||||
public VelbusBlindUpDownPacket(VelbusChannelIdentifier velbusChannelIdentifier, byte command) {
|
||||
super(velbusChannelIdentifier.getAddress(), PRIO_HI);
|
||||
|
||||
this.channel = velbusChannelIdentifier.getChannelByte();
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { command, channel, timeoutHighByte, timeoutMidByte, timeoutLowByte };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusChannelNameRequestPacket} represents a Velbus packet that can be used to
|
||||
* request the name of a given channel.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusChannelNameRequestPacket extends VelbusPacket {
|
||||
|
||||
public VelbusChannelNameRequestPacket(byte address) {
|
||||
super(address, PRIO_LOW);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_MODULE_NAME_REQUEST, ALL_CHANNELS };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_COUNTER_STATUS_REQUEST;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
|
||||
|
||||
/**
|
||||
* The {@link VelbusCounterStatusRequestPacket} represents a Velbus packet that can be used to
|
||||
* request the counter status of the given Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusCounterStatusRequestPacket extends VelbusPacket {
|
||||
private byte channel;
|
||||
|
||||
private final byte autosendTimeInterval = 0x00;
|
||||
|
||||
public VelbusCounterStatusRequestPacket(VelbusChannelIdentifier velbusChannelIdentifier) {
|
||||
super(velbusChannelIdentifier.getAddress(), PRIO_LOW);
|
||||
|
||||
this.channel = velbusChannelIdentifier.getChannelByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_COUNTER_STATUS_REQUEST, channel, autosendTimeInterval };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
|
||||
|
||||
/**
|
||||
* The {@link VelbusDimmerPacket} represents a Velbus packet that can be used to
|
||||
* dim a light to a given percentage.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusDimmerPacket extends VelbusPacket {
|
||||
private static final byte FIRST_GENERATION_DEVICE_FASTEST_DIMSPEED_HIGH_BYTE = (byte) 0xFF;
|
||||
private static final byte FIRST_GENERATION_DEVICE_FASTEST_DIMSPEED_LOW_BYTE = (byte) 0xFF;
|
||||
|
||||
private Boolean isFirstGenerationDevice;
|
||||
private byte command;
|
||||
private byte channel;
|
||||
private byte percentage;
|
||||
private int dimspeed;
|
||||
|
||||
public VelbusDimmerPacket(VelbusChannelIdentifier velbusChannelIdentifier, byte command, byte percentage,
|
||||
int dimspeed, Boolean isFirstGenerationDevice) {
|
||||
super(velbusChannelIdentifier.getAddress(), PRIO_HI);
|
||||
|
||||
this.channel = velbusChannelIdentifier.getChannelByte();
|
||||
this.command = command;
|
||||
this.percentage = percentage;
|
||||
this.dimspeed = dimspeed;
|
||||
this.isFirstGenerationDevice = isFirstGenerationDevice;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
byte dimspeedHighByte = (byte) ((dimspeed & 0xFF00) / 0x100);
|
||||
byte dimspeedLowByte = (byte) (dimspeed & 0xFF);
|
||||
|
||||
if (dimspeed == 0 && isFirstGenerationDevice) {
|
||||
dimspeedHighByte = FIRST_GENERATION_DEVICE_FASTEST_DIMSPEED_HIGH_BYTE;
|
||||
dimspeedLowByte = FIRST_GENERATION_DEVICE_FASTEST_DIMSPEED_LOW_BYTE;
|
||||
}
|
||||
|
||||
return new byte[] { command, channel, percentage, dimspeedHighByte, dimspeedLowByte };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
|
||||
|
||||
/**
|
||||
* The {@link VelbusFeedbackLEDPacket} represents a Velbus packet that can be used to
|
||||
* set the feedback led (clear/set/slow blink/fast blink/very fast blink) of the given Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusFeedbackLEDPacket extends VelbusPacket {
|
||||
private byte command;
|
||||
private byte channel;
|
||||
|
||||
public VelbusFeedbackLEDPacket(VelbusChannelIdentifier velbusChannelIdentifier, byte command) {
|
||||
super(velbusChannelIdentifier.getAddress(), PRIO_LOW);
|
||||
|
||||
this.channel = velbusChannelIdentifier.getChannelByte();
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { command, channel };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_LIGHT_VALUE_REQUEST;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusLightValueRequestPacket} represents a Velbus packet that can be used to
|
||||
* request the value of the light sensor of the given Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusLightValueRequestPacket extends VelbusPacket {
|
||||
|
||||
private final byte autosendTimeInterval = 0x00;
|
||||
|
||||
public VelbusLightValueRequestPacket(byte address) {
|
||||
super(address, PRIO_LOW);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_LIGHT_VALUE_REQUEST, autosendTimeInterval };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_TEXT;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusMemoTextPacket} represents a Velbus packet that can be used to
|
||||
* set the mode (comfort/day/night/safe) of the given Velbus thermostat module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusMemoTextPacket extends VelbusPacket {
|
||||
private byte textStartPosition;
|
||||
private byte character1;
|
||||
private byte character2;
|
||||
private byte character3;
|
||||
private byte character4;
|
||||
private byte character5;
|
||||
|
||||
public VelbusMemoTextPacket(byte address, byte textStartPosition, char[] text) {
|
||||
super(address, PRIO_LOW);
|
||||
|
||||
if (textStartPosition < 0 || textStartPosition > 63) {
|
||||
throw new IllegalArgumentException("The text start position '" + textStartPosition
|
||||
+ "' is invalid, because it should be between 0 and 63.");
|
||||
}
|
||||
|
||||
if (text.length > 5) {
|
||||
throw new IllegalArgumentException(
|
||||
"The text '" + text.toString() + "' is invalid, because it cannot be longer than 5 characters.");
|
||||
}
|
||||
|
||||
this.textStartPosition = textStartPosition;
|
||||
this.character1 = text.length > 0 ? (byte) text[0] : 0x00;
|
||||
this.character2 = text.length > 1 ? (byte) text[1] : 0x00;
|
||||
this.character3 = text.length > 2 ? (byte) text[2] : 0x00;
|
||||
this.character4 = text.length > 3 ? (byte) text[3] : 0x00;
|
||||
this.character5 = text.length > 4 ? (byte) text[4] : 0x00;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_TEXT, 0x00, textStartPosition, character1, character2, character3, character4,
|
||||
character5 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusPacket} represents a base class for a Velbus packet and contains
|
||||
* functionality that is applicable to all Velbus packets.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class VelbusPacket {
|
||||
public static final byte STX = 0x0F;
|
||||
public static final byte PRIO_HI = (byte) 0xF8;
|
||||
public static final byte PRIO_LOW = (byte) 0xFB;
|
||||
public static final byte ETX = 0x04;
|
||||
|
||||
private byte address;
|
||||
private byte priority;
|
||||
private byte rtr;
|
||||
|
||||
protected VelbusPacket(byte address, byte priority) {
|
||||
this(address, priority, false);
|
||||
}
|
||||
|
||||
protected VelbusPacket(byte address, byte priority, boolean rtr) {
|
||||
this.address = address;
|
||||
this.priority = priority;
|
||||
this.rtr = rtr ? (byte) 0x40 : (byte) 0x00;
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
byte[] dataBytes = getDataBytes();
|
||||
int dataBytesLength = dataBytes.length;
|
||||
byte[] packetBytes = new byte[6 + dataBytesLength];
|
||||
|
||||
packetBytes[0] = STX;
|
||||
packetBytes[1] = priority;
|
||||
packetBytes[2] = address;
|
||||
packetBytes[3] = (byte) (rtr | dataBytesLength);
|
||||
|
||||
System.arraycopy(dataBytes, 0, packetBytes, 4, dataBytes.length);
|
||||
|
||||
packetBytes[4 + dataBytesLength] = computeCRCByte(packetBytes);
|
||||
packetBytes[5 + dataBytesLength] = ETX;
|
||||
|
||||
return packetBytes;
|
||||
}
|
||||
|
||||
protected abstract byte[] getDataBytes();
|
||||
|
||||
public static byte computeCRCByte(byte[] packetBytes) {
|
||||
int crc = 0;
|
||||
|
||||
for (int i = 0; i < packetBytes.length - 2; i++) {
|
||||
crc = (crc + (packetBytes[i] & 0xFF)) & 0xFF;
|
||||
}
|
||||
|
||||
return (byte) (0x100 - crc);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_READ_MEMORY_BLOCK;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusReadMemoryBlockPacket} represents a Velbus packet that can be used to
|
||||
* request a block of 4 bytes from the memory of the given Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusReadMemoryBlockPacket extends VelbusPacket {
|
||||
private byte highMemoryAddress;
|
||||
private byte lowMemoryAddress;
|
||||
|
||||
public VelbusReadMemoryBlockPacket(byte address, int memoryAddress) {
|
||||
super(address, PRIO_LOW);
|
||||
|
||||
highMemoryAddress = (byte) ((memoryAddress >> 8) & 0xFF);
|
||||
lowMemoryAddress = (byte) (memoryAddress & 0xFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_READ_MEMORY_BLOCK, highMemoryAddress, lowMemoryAddress };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_READ_DATA_FROM_MEMORY;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusReadMemoryPacket} represents a Velbus packet that can be used to
|
||||
* request a byte from the memory of the given Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusReadMemoryPacket extends VelbusPacket {
|
||||
private byte highMemoryAddress;
|
||||
private byte lowMemoryAddress;
|
||||
|
||||
public VelbusReadMemoryPacket(byte address, int memoryAddress) {
|
||||
super(address, PRIO_LOW);
|
||||
|
||||
highMemoryAddress = (byte) ((memoryAddress >> 8) & 0xFF);
|
||||
lowMemoryAddress = (byte) (memoryAddress & 0xFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_READ_DATA_FROM_MEMORY, highMemoryAddress, lowMemoryAddress };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
|
||||
|
||||
/**
|
||||
* The {@link VelbusRelayPacket} represents a Velbus packet that can be used to
|
||||
* send commands to a Velbus relay module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusRelayPacket extends VelbusPacket {
|
||||
private byte command;
|
||||
private byte channel;
|
||||
|
||||
public VelbusRelayPacket(VelbusChannelIdentifier velbusChannelIdentifier, byte command) {
|
||||
super(velbusChannelIdentifier.getAddress(), PRIO_HI);
|
||||
|
||||
this.channel = velbusChannelIdentifier.getChannelByte();
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { command, channel };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusScanPacket} represents a Velbus packet that can be used to
|
||||
* check if a Velbus module exists on the given address and to request this module's
|
||||
* basic properties.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusScanPacket extends VelbusPacket {
|
||||
|
||||
public VelbusScanPacket(byte address) {
|
||||
super(address, PRIO_LOW, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_SENSOR_READOUT_REQUEST;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusSensorReadoutRequestPacket} represents a Velbus packet that can be used to
|
||||
* request the value of a sensor channel of the given Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusSensorReadoutRequestPacket extends VelbusPacket {
|
||||
|
||||
private final byte autosendTimeInterval = 0x00;
|
||||
|
||||
private byte channel;
|
||||
|
||||
public VelbusSensorReadoutRequestPacket(byte address, byte channel) {
|
||||
super(address, PRIO_LOW);
|
||||
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_SENSOR_READOUT_REQUEST, channel, autosendTimeInterval };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_TEMP_SENSOR_SETTINGS_REQUEST;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusSensorSettingsRequestPacket} represents a Velbus packet that can be used to
|
||||
* request the sensor settings of the given Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusSensorSettingsRequestPacket extends VelbusPacket {
|
||||
public VelbusSensorSettingsRequestPacket(byte address) {
|
||||
super(address, PRIO_LOW);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_TEMP_SENSOR_SETTINGS_REQUEST, 0x00 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_SENSOR_READOUT_REQUEST;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusSensorTemperatureRequestPacket} represents a Velbus packet that can be used to
|
||||
* request the value of the temperature sensor of the given Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusSensorTemperatureRequestPacket extends VelbusPacket {
|
||||
|
||||
private final byte autosendTimeInterval = 0x00;
|
||||
|
||||
public VelbusSensorTemperatureRequestPacket(byte address) {
|
||||
super(address, PRIO_LOW);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_SENSOR_READOUT_REQUEST, autosendTimeInterval };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_SET_REALTIME_DATE;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusSetDatePacket} represents a Velbus packet that can be used to
|
||||
* set the date of the given Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusSetDatePacket extends VelbusPacket {
|
||||
private ZonedDateTime zonedDateTime;
|
||||
|
||||
public VelbusSetDatePacket(byte address, ZonedDateTime zonedDateTime) {
|
||||
super(address, PRIO_LOW);
|
||||
|
||||
this.zonedDateTime = zonedDateTime;
|
||||
}
|
||||
|
||||
public byte getDay() {
|
||||
return (byte) this.zonedDateTime.getDayOfMonth();
|
||||
}
|
||||
|
||||
public byte getMonth() {
|
||||
return (byte) this.zonedDateTime.getMonthValue();
|
||||
}
|
||||
|
||||
public byte getYearHighByte() {
|
||||
return (byte) ((zonedDateTime.getYear() & 0xff00) / 0x100);
|
||||
}
|
||||
|
||||
public byte getYearLowByte() {
|
||||
return (byte) (zonedDateTime.getYear() & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_SET_REALTIME_DATE, getDay(), getMonth(), getYearHighByte(), getYearLowByte() };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_DAYLIGHT_SAVING_STATUS;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusSetDaylightSavingsStatusPacket} represents a Velbus packet that can be used to
|
||||
* set the daylight saving status of the given Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusSetDaylightSavingsStatusPacket extends VelbusPacket {
|
||||
private ZonedDateTime zonedDateTime;
|
||||
|
||||
public VelbusSetDaylightSavingsStatusPacket(byte address, ZonedDateTime zonedDateTime) {
|
||||
super(address, PRIO_LOW);
|
||||
|
||||
this.zonedDateTime = zonedDateTime;
|
||||
}
|
||||
|
||||
public boolean isDaylightSavings() {
|
||||
return zonedDateTime.getZone().getRules().isDaylightSavings(zonedDateTime.toInstant());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_DAYLIGHT_SAVING_STATUS, (byte) (isDaylightSavings() ? 0x01 : 0x00) };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_SET_ALARM_CLOCK;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.VelbusClockAlarm;
|
||||
|
||||
/**
|
||||
* The {@link VelbusSetLocalClockAlarmPacket} represents a Velbus packet that can be used to
|
||||
* set the value of the local clock alarm of the given Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusSetLocalClockAlarmPacket extends VelbusPacket {
|
||||
private byte alarmNumber;
|
||||
private VelbusClockAlarm alarmClock;
|
||||
|
||||
public VelbusSetLocalClockAlarmPacket(byte address, byte alarmNumber, VelbusClockAlarm alarmClock) {
|
||||
super(address, PRIO_LOW);
|
||||
|
||||
this.alarmNumber = alarmNumber;
|
||||
this.alarmClock = alarmClock;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_SET_ALARM_CLOCK, alarmNumber, alarmClock.getWakeupHour(),
|
||||
alarmClock.getWakeupMinute(), alarmClock.getBedtimeHour(), alarmClock.getBedtimeMinute(),
|
||||
alarmClock.isEnabled() ? (byte) 0x01 : (byte) 0x00 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_SET_REALTIME_CLOCK;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusSetRealtimeClockPacket} represents a Velbus packet that can be used to
|
||||
* set the clock of the given Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusSetRealtimeClockPacket extends VelbusPacket {
|
||||
private ZonedDateTime zonedDateTime;
|
||||
|
||||
public VelbusSetRealtimeClockPacket(byte address, ZonedDateTime zonedDateTime) {
|
||||
super(address, PRIO_LOW);
|
||||
|
||||
this.zonedDateTime = zonedDateTime;
|
||||
}
|
||||
|
||||
public byte getHour() {
|
||||
return (byte) this.zonedDateTime.getHour();
|
||||
}
|
||||
|
||||
public byte getMinute() {
|
||||
return (byte) this.zonedDateTime.getMinute();
|
||||
}
|
||||
|
||||
public byte getWeekDay() {
|
||||
DayOfWeek dayOfWeek = zonedDateTime.getDayOfWeek();
|
||||
switch (dayOfWeek) {
|
||||
case MONDAY:
|
||||
return 0x00;
|
||||
case TUESDAY:
|
||||
return 0x01;
|
||||
case WEDNESDAY:
|
||||
return 0x02;
|
||||
case THURSDAY:
|
||||
return 0x03;
|
||||
case FRIDAY:
|
||||
return 0x04;
|
||||
case SATURDAY:
|
||||
return 0x05;
|
||||
case SUNDAY:
|
||||
return 0x06;
|
||||
default:
|
||||
throw new IllegalArgumentException("Day " + dayOfWeek + " is not a valid weekday.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_SET_REALTIME_CLOCK, this.getWeekDay(), getHour(), getMinute() };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_SET_TEMP;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusSetTemperaturePacket} represents a Velbus packet that can be used to
|
||||
* set the value of a temperature variable of the given Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusSetTemperaturePacket extends VelbusPacket {
|
||||
|
||||
private byte temperatureVariable;
|
||||
private byte temperature;
|
||||
|
||||
public VelbusSetTemperaturePacket(byte address, byte temperatureVariable, byte temperature) {
|
||||
super(address, PRIO_LOW);
|
||||
|
||||
this.temperatureVariable = temperatureVariable;
|
||||
this.temperature = temperature;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_SET_TEMP, temperatureVariable, temperature };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
|
||||
|
||||
/**
|
||||
* The {@link VelbusStatusRequestPacket} represents a Velbus packet that can be used to
|
||||
* request the state of the given Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusStatusRequestPacket extends VelbusPacket {
|
||||
private byte channel;
|
||||
|
||||
public VelbusStatusRequestPacket(byte address) {
|
||||
this(new VelbusChannelIdentifier(address, ALL_CHANNELS));
|
||||
}
|
||||
|
||||
public VelbusStatusRequestPacket(VelbusChannelIdentifier velbusChannelIdentifier) {
|
||||
super(velbusChannelIdentifier.getAddress(), PRIO_LOW);
|
||||
|
||||
this.channel = velbusChannelIdentifier.getChannelByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_STATUS_REQUEST, channel };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusThermostatModePacket} represents a Velbus packet that can be used to
|
||||
* set the mode (comfort/day/night/safe) of the given Velbus thermostat module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusThermostatModePacket extends VelbusPacket {
|
||||
|
||||
private byte commandByte;
|
||||
|
||||
public VelbusThermostatModePacket(byte address, byte commandByte) {
|
||||
super(address, PRIO_LOW);
|
||||
|
||||
this.commandByte = commandByte;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { commandByte, 0x00, 0x00 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusThermostatOperatingModePacket} represents a Velbus packet that can be used to
|
||||
* set the operating mode (heating/cooling) of the given Velbus thermostat module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusThermostatOperatingModePacket extends VelbusPacket {
|
||||
|
||||
private byte commandByte;
|
||||
|
||||
public VelbusThermostatOperatingModePacket(byte address, byte commandByte) {
|
||||
super(address, PRIO_LOW);
|
||||
|
||||
this.commandByte = commandByte;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { commandByte, 0x00 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.velbus.internal.packets;
|
||||
|
||||
import static org.openhab.binding.velbus.internal.VelbusBindingConstants.COMMAND_WRITE_DATA_TO_MEMORY;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link VelbusWriteMemoryPacket} represents a Velbus packet that can be used to
|
||||
* request a byte from the memory of the given Velbus module.
|
||||
*
|
||||
* @author Cedric Boon - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class VelbusWriteMemoryPacket extends VelbusPacket {
|
||||
private byte highMemoryAddress;
|
||||
private byte lowMemoryAddress;
|
||||
private byte data;
|
||||
|
||||
public VelbusWriteMemoryPacket(byte address, int memoryAddress, byte data) {
|
||||
super(address, PRIO_LOW);
|
||||
|
||||
this.highMemoryAddress = (byte) ((memoryAddress >> 8) & 0xFF);
|
||||
this.lowMemoryAddress = (byte) (memoryAddress & 0xFF);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getDataBytes() {
|
||||
return new byte[] { COMMAND_WRITE_DATA_TO_MEMORY, highMemoryAddress, lowMemoryAddress, data };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="velbus" 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>Velbus Binding</name>
|
||||
<description>This is the binding for Velbus.</description>
|
||||
<author>Cedric Boon</author>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,902 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<config-description:config-descriptions
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https://openhab.org/schemas/config-description-1.0.0.xsd">
|
||||
|
||||
<config-description uri="bridge-type:velbus:bridge">
|
||||
<parameter name="port" type="text">
|
||||
<context>serial-port</context>
|
||||
<limitToOptions>false</limitToOptions>
|
||||
<label>Serial Port</label>
|
||||
<description>Select serial port (COM1, /dev/ttyS0, ...)</description>
|
||||
<required>true</required>
|
||||
</parameter>
|
||||
<parameter name="timeUpdateInterval" type="integer" unit="min">
|
||||
<label>Time Update Interval</label>
|
||||
<description>The interval (in minutes) at which the realtime clock, date and daylight savings status of the modules
|
||||
will be updated, default 360. If set to 0 or left empty, no refresh will be scheduled.</description>
|
||||
<default>360</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="reconnectionInterval" type="integer" unit="s">
|
||||
<label>Reconnection Interval</label>
|
||||
<description>The interval (in seconds) at which reconnections should be reattempted in case of a communication
|
||||
problem, default 15. If set to 0 or left empty, no reconnections will be attempted.</description>
|
||||
<default>15</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="bridge-type:velbus:networkbridge">
|
||||
<parameter name="address" type="text" required="true">
|
||||
<context>network-address</context>
|
||||
<label>IP Address or Hostname</label>
|
||||
<description>IP Address or hostname of Velbus server</description>
|
||||
<required>true</required>
|
||||
</parameter>
|
||||
<parameter name="port" type="integer" required="false">
|
||||
<label>Port</label>
|
||||
<description>Network port to communicate with Velbus server</description>
|
||||
<required>true</required>
|
||||
</parameter>
|
||||
<parameter name="timeUpdateInterval" type="integer" unit="min">
|
||||
<label>Time Update Interval</label>
|
||||
<description>The interval (in minutes) at which the realtime clock, date and daylight savings status of the modules
|
||||
will be updated, default 360. If set to 0 or left empty, no refresh will be scheduled.</description>
|
||||
<default>360</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="reconnectionInterval" type="integer" unit="s">
|
||||
<label>Reconnection Interval</label>
|
||||
<description>The interval (in seconds) at which reconnections should be reattempted in case of a communication
|
||||
problem, default 15. If set to 0 or left empty, no reconnections will be attempted.</description>
|
||||
<default>15</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:velbus:temperatureSensorDevice">
|
||||
<parameter name="address" type="text" required="true">
|
||||
<label>Address</label>
|
||||
<description>The velbus address of the device</description>
|
||||
</parameter>
|
||||
<parameter name="refresh" type="integer" unit="s">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Refresh interval for the temperature sensor (in seconds), default 300. If set to 0 or left empty, no
|
||||
refresh will be scheduled.</description>
|
||||
<default>300</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:velbus:1channelDevice">
|
||||
<parameter name="address" type="text" required="true">
|
||||
<label>Address</label>
|
||||
<description>The velbus address of the device</description>
|
||||
</parameter>
|
||||
<parameter name="CH1" type="text">
|
||||
<label>CH1 Name</label>
|
||||
<description>The name of CH1.</description>
|
||||
<default>CH1</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:velbus:1channelDeviceWithDimspeed">
|
||||
<parameter name="address" type="text" required="true">
|
||||
<label>Address</label>
|
||||
<description>The velbus address of the device</description>
|
||||
</parameter>
|
||||
<parameter name="CH1" type="text">
|
||||
<label>CH1 Name</label>
|
||||
<description>The name of CH1.</description>
|
||||
<default>CH1</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="dimspeed" type="integer" unit="s">
|
||||
<label>Dimspeed</label>
|
||||
<description>The time (in seconds) needed for dimming from 0 to 100%.</description>
|
||||
<default>0</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:velbus:2channelDevice">
|
||||
<parameter name="address" type="text" required="true">
|
||||
<label>Address</label>
|
||||
<description>The velbus address of the device</description>
|
||||
</parameter>
|
||||
<parameter name="CH1" type="text">
|
||||
<label>CH1 Name</label>
|
||||
<description>The name of CH1.</description>
|
||||
<default>CH1</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH2" type="text">
|
||||
<label>CH2 Name</label>
|
||||
<description>The name of CH2.</description>
|
||||
<default>CH2</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:velbus:4channelDevice">
|
||||
<parameter name="address" type="text" required="true">
|
||||
<label>Address</label>
|
||||
<description>The velbus address of the device</description>
|
||||
</parameter>
|
||||
<parameter name="CH1" type="text">
|
||||
<label>CH1 Name</label>
|
||||
<description>The name of CH1.</description>
|
||||
<default>CH1</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH2" type="text">
|
||||
<label>CH2 Name</label>
|
||||
<description>The name of CH2.</description>
|
||||
<default>CH2</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH3" type="text">
|
||||
<label>CH3 Name</label>
|
||||
<description>The name of CH3.</description>
|
||||
<default>CH3</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH4" type="text">
|
||||
<label>CH4 Name</label>
|
||||
<description>The name of CH4.</description>
|
||||
<default>CH4</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:velbus:4channelDeviceWithDimspeed">
|
||||
<parameter name="address" type="text" required="true">
|
||||
<label>Address</label>
|
||||
<description>The velbus address of the device</description>
|
||||
</parameter>
|
||||
<parameter name="CH1" type="text">
|
||||
<label>CH1 Name</label>
|
||||
<description>The name of CH1.</description>
|
||||
<default>CH1</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH2" type="text">
|
||||
<label>CH2 Name</label>
|
||||
<description>The name of CH2.</description>
|
||||
<default>CH2</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH3" type="text">
|
||||
<label>CH3 Name</label>
|
||||
<description>The name of CH3.</description>
|
||||
<default>CH3</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH4" type="text">
|
||||
<label>CH4 Name</label>
|
||||
<description>The name of CH4.</description>
|
||||
<default>CH4</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="dimspeed" type="integer" unit="s">
|
||||
<label>Dimspeed</label>
|
||||
<description>The time (in seconds) needed for dimming from 0 to 100%.</description>
|
||||
<default>0</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:velbus:5channelDevice">
|
||||
<parameter name="address" type="text" required="true">
|
||||
<label>Address</label>
|
||||
<description>The velbus address of the device</description>
|
||||
</parameter>
|
||||
<parameter name="CH1" type="text">
|
||||
<label>CH1 Name</label>
|
||||
<description>The name of CH1.</description>
|
||||
<default>CH1</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH2" type="text">
|
||||
<label>CH2 Name</label>
|
||||
<description>The name of CH2.</description>
|
||||
<default>CH2</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH3" type="text">
|
||||
<label>CH3 Name</label>
|
||||
<description>The name of CH3.</description>
|
||||
<default>CH3</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH4" type="text">
|
||||
<label>CH4 Name</label>
|
||||
<description>The name of CH4.</description>
|
||||
<default>CH4</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH5" type="text">
|
||||
<label>CH5 Name</label>
|
||||
<description>The name of CH5.</description>
|
||||
<default>CH5</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:velbus:6channelDevice">
|
||||
<parameter name="address" type="text" required="true">
|
||||
<label>Address</label>
|
||||
<description>The velbus address of the device</description>
|
||||
</parameter>
|
||||
<parameter name="CH1" type="text">
|
||||
<label>CH1 Name</label>
|
||||
<description>The name of CH1.</description>
|
||||
<default>CH1</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH2" type="text">
|
||||
<label>CH2 Name</label>
|
||||
<description>The name of CH2.</description>
|
||||
<default>CH2</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH3" type="text">
|
||||
<label>CH3 Name</label>
|
||||
<description>The name of CH3.</description>
|
||||
<default>CH3</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH4" type="text">
|
||||
<label>CH4 Name</label>
|
||||
<description>The name of CH4.</description>
|
||||
<default>CH4</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH5" type="text">
|
||||
<label>CH5 Name</label>
|
||||
<description>The name of CH5.</description>
|
||||
<default>CH5</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH6" type="text">
|
||||
<label>CH6 Name</label>
|
||||
<description>The name of CH6.</description>
|
||||
<default>CH6</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:velbus:7channelDeviceWithCounters">
|
||||
<parameter name="address" type="text" required="true">
|
||||
<label>Address</label>
|
||||
<description>The velbus address of the device</description>
|
||||
</parameter>
|
||||
<parameter name="refresh" type="integer" unit="s">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Refresh interval for the counters (in seconds), default 300. If set to 0 or left empty, no refresh will
|
||||
be scheduled.</description>
|
||||
<default>300</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH1" type="text">
|
||||
<label>CH1 Name</label>
|
||||
<description>The name of CH1.</description>
|
||||
<default>CH1</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH2" type="text">
|
||||
<label>CH2 Name</label>
|
||||
<description>The name of CH2.</description>
|
||||
<default>CH2</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH3" type="text">
|
||||
<label>CH3 Name</label>
|
||||
<description>The name of CH3.</description>
|
||||
<default>CH3</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH4" type="text">
|
||||
<label>CH4 Name</label>
|
||||
<description>The name of CH4.</description>
|
||||
<default>CH4</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH5" type="text">
|
||||
<label>CH5 Name</label>
|
||||
<description>The name of CH5.</description>
|
||||
<default>CH5</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH6" type="text">
|
||||
<label>CH6 Name</label>
|
||||
<description>The name of CH6.</description>
|
||||
<default>CH6</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH7" type="text">
|
||||
<label>CH7 Name</label>
|
||||
<description>The name of CH7.</description>
|
||||
<default>CH7</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="counter1Unit" type="text">
|
||||
<label>Counter 1 Unit</label>
|
||||
<description>The unit for Counter 1.</description>
|
||||
<default>kWh</default>
|
||||
<options>
|
||||
<option value="kWh">kWh</option>
|
||||
<option value="liters">liters</option>
|
||||
<option value="m³">m³</option>
|
||||
</options>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="counter1PulseMultiplier" type="decimal">
|
||||
<label>Counter 1 Pulse Multiplier</label>
|
||||
<description>The pulse multiplier for counter 1</description>
|
||||
<default>1</default>
|
||||
<options>
|
||||
<option value="1">x1</option>
|
||||
<option value="2.5">x2.5</option>
|
||||
<option value="0.05">x0.05</option>
|
||||
<option value="0.01">x0.01</option>
|
||||
</options>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="counter2Unit" type="text">
|
||||
<label>Counter 2 Unit</label>
|
||||
<description>The unit for Counter 2.</description>
|
||||
<default>kWh</default>
|
||||
<options>
|
||||
<option value="kWh">kWh</option>
|
||||
<option value="liters">liters</option>
|
||||
<option value="m³">m³</option>
|
||||
</options>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="counter2PulseMultiplier" type="decimal">
|
||||
<label>Counter 2 Pulse Multiplier</label>
|
||||
<description>The pulse multiplier for counter 2</description>
|
||||
<default>1</default>
|
||||
<options>
|
||||
<option value="1">x1</option>
|
||||
<option value="2.5">x2.5</option>
|
||||
<option value="0.05">x0.05</option>
|
||||
<option value="0.01">x0.01</option>
|
||||
</options>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="counter3Unit" type="text">
|
||||
<label>Counter 3 Unit</label>
|
||||
<description>The unit for Counter 3.</description>
|
||||
<default>kWh</default>
|
||||
<options>
|
||||
<option value="kWh">kWh</option>
|
||||
<option value="liters">liters</option>
|
||||
<option value="m³">m³</option>
|
||||
</options>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="counter3PulseMultiplier" type="decimal">
|
||||
<label>Counter 3 Pulse Multiplier</label>
|
||||
<description>The pulse multiplier for counter 3</description>
|
||||
<default>1</default>
|
||||
<options>
|
||||
<option value="1">x1</option>
|
||||
<option value="2.5">x2.5</option>
|
||||
<option value="0.05">x0.05</option>
|
||||
<option value="0.01">x0.01</option>
|
||||
</options>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="counter4Unit" type="text">
|
||||
<label>Counter 4 Unit</label>
|
||||
<description>The unit for Counter 4.</description>
|
||||
<default>kWh</default>
|
||||
<options>
|
||||
<option value="kWh">kWh</option>
|
||||
<option value="liters">liters</option>
|
||||
<option value="m³">m³</option>
|
||||
</options>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="counter4PulseMultiplier" type="decimal">
|
||||
<label>Counter 4 Pulse Multiplier</label>
|
||||
<description>The pulse multiplier for counter 4</description>
|
||||
<default>1</default>
|
||||
<options>
|
||||
<option value="1">x1</option>
|
||||
<option value="2.5">x2.5</option>
|
||||
<option value="0.05">x0.05</option>
|
||||
<option value="0.01">x0.01</option>
|
||||
</options>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:velbus:7channelDeviceWithTemperatureSensor">
|
||||
<parameter name="address" type="text" required="true">
|
||||
<label>Address</label>
|
||||
<description>The velbus address of the device</description>
|
||||
</parameter>
|
||||
<parameter name="refresh" type="integer" unit="s">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Refresh interval for the temperature sensor (in seconds), default 300. If set to 0 or left empty, no
|
||||
refresh will be scheduled.</description>
|
||||
<default>300</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH1" type="text">
|
||||
<label>CH1 Name</label>
|
||||
<description>The name of CH1.</description>
|
||||
<default>CH1</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH2" type="text">
|
||||
<label>CH2 Name</label>
|
||||
<description>The name of CH2.</description>
|
||||
<default>CH2</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH3" type="text">
|
||||
<label>CH3 Name</label>
|
||||
<description>The name of CH3.</description>
|
||||
<default>CH3</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH4" type="text">
|
||||
<label>CH4 Name</label>
|
||||
<description>The name of CH4.</description>
|
||||
<default>CH4</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH5" type="text">
|
||||
<label>CH5 Name</label>
|
||||
<description>The name of CH5.</description>
|
||||
<default>CH5</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH6" type="text">
|
||||
<label>CH6 Name</label>
|
||||
<description>The name of CH6.</description>
|
||||
<default>CH6</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH7" type="text">
|
||||
<label>CH7 Name</label>
|
||||
<description>The name of CH7.</description>
|
||||
<default>CH7</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:velbus:8channelDevice">
|
||||
<parameter name="address" type="text" required="true">
|
||||
<label>Address</label>
|
||||
<description>The velbus address of the device</description>
|
||||
</parameter>
|
||||
<parameter name="CH1" type="text">
|
||||
<label>CH1 Name</label>
|
||||
<description>The name of CH1.</description>
|
||||
<default>CH1</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH2" type="text">
|
||||
<label>CH2 Name</label>
|
||||
<description>The name of CH2.</description>
|
||||
<default>CH2</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH3" type="text">
|
||||
<label>CH3 Name</label>
|
||||
<description>The name of CH3.</description>
|
||||
<default>CH3</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH4" type="text">
|
||||
<label>CH4 Name</label>
|
||||
<description>The name of CH4.</description>
|
||||
<default>CH4</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH5" type="text">
|
||||
<label>CH5 Name</label>
|
||||
<description>The name of CH5.</description>
|
||||
<default>CH5</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH6" type="text">
|
||||
<label>CH6 Name</label>
|
||||
<description>The name of CH6.</description>
|
||||
<default>CH6</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH7" type="text">
|
||||
<label>CH7 Name</label>
|
||||
<description>The name of CH7.</description>
|
||||
<default>CH7</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH8" type="text">
|
||||
<label>CH8 Name</label>
|
||||
<description>The name of CH8.</description>
|
||||
<default>CH8</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:velbus:9channelDeviceWithTemperatureSensor">
|
||||
<parameter name="address" type="text" required="true">
|
||||
<label>Address</label>
|
||||
<description>The velbus address of the device</description>
|
||||
</parameter>
|
||||
<parameter name="refresh" type="integer" unit="s">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Refresh interval for the temperature sensor (in seconds), default 300. If set to 0 or left empty, no
|
||||
refresh will be scheduled.</description>
|
||||
<default>300</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH1" type="text">
|
||||
<label>CH1 Name</label>
|
||||
<description>The name of CH1.</description>
|
||||
<default>CH1</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH2" type="text">
|
||||
<label>CH2 Name</label>
|
||||
<description>The name of CH2.</description>
|
||||
<default>CH2</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH3" type="text">
|
||||
<label>CH3 Name</label>
|
||||
<description>The name of CH3.</description>
|
||||
<default>CH3</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH4" type="text">
|
||||
<label>CH4 Name</label>
|
||||
<description>The name of CH4.</description>
|
||||
<default>CH4</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH5" type="text">
|
||||
<label>CH5 Name</label>
|
||||
<description>The name of CH5.</description>
|
||||
<default>CH5</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH6" type="text">
|
||||
<label>CH6 Name</label>
|
||||
<description>The name of CH6.</description>
|
||||
<default>CH6</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH7" type="text">
|
||||
<label>CH7 Name</label>
|
||||
<description>The name of CH7.</description>
|
||||
<default>CH7</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH8" type="text">
|
||||
<label>CH8 Name</label>
|
||||
<description>The name of CH8.</description>
|
||||
<default>CH8</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH9" type="text">
|
||||
<label>CH9 Name</label>
|
||||
<description>The name of CH9 (temperature sensor channel).</description>
|
||||
<default>Temperature</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:velbus:13channelDevice">
|
||||
<parameter name="address" type="text" required="true">
|
||||
<label>Address</label>
|
||||
<description>The velbus address of the device</description>
|
||||
</parameter>
|
||||
<parameter name="refresh" type="integer" unit="s">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Refresh interval for the sensors (in seconds), default 300. If set to 0 or left empty, no refresh will
|
||||
be scheduled.</description>
|
||||
<default>300</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH1" type="text">
|
||||
<label>CH1 Name</label>
|
||||
<description>The name of CH1.</description>
|
||||
<default>CH1</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH2" type="text">
|
||||
<label>CH2 Name</label>
|
||||
<description>The name of CH2.</description>
|
||||
<default>CH2</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH3" type="text">
|
||||
<label>CH3 Name</label>
|
||||
<description>The name of CH3.</description>
|
||||
<default>CH3</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH4" type="text">
|
||||
<label>CH4 Name</label>
|
||||
<description>The name of CH4.</description>
|
||||
<default>CH4</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH5" type="text">
|
||||
<label>CH5 Name</label>
|
||||
<description>The name of CH5.</description>
|
||||
<default>CH5</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH6" type="text">
|
||||
<label>CH6 Name</label>
|
||||
<description>The name of CH6.</description>
|
||||
<default>CH6</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH7" type="text">
|
||||
<label>CH7 Name</label>
|
||||
<description>The name of CH7.</description>
|
||||
<default>CH7</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH8" type="text">
|
||||
<label>CH8 Name</label>
|
||||
<description>The name of CH8.</description>
|
||||
<default>CH8</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH9" type="text">
|
||||
<label>CH9 Name</label>
|
||||
<description>The name of CH9.</description>
|
||||
<default>CH9</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH10" type="text">
|
||||
<label>CH10 Name</label>
|
||||
<description>The name of CH10.</description>
|
||||
<default>CH10</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH11" type="text">
|
||||
<label>CH11 Name</label>
|
||||
<description>The name of CH11.</description>
|
||||
<default>CH11</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH12" type="text">
|
||||
<label>CH12 Name</label>
|
||||
<description>The name of CH12.</description>
|
||||
<default>CH12</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH13" type="text">
|
||||
<label>CH13 Name</label>
|
||||
<description>The name of CH13.</description>
|
||||
<default>CH13</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
<config-description uri="thing-type:velbus:33channelDeviceWithTemperatureSensor">
|
||||
<parameter name="address" type="text" required="true">
|
||||
<label>Address</label>
|
||||
<description>The velbus address of the device</description>
|
||||
</parameter>
|
||||
<parameter name="refresh" type="integer" unit="s">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Refresh interval for the temperature sensor (in seconds), default 300. If set to 0 or left empty, no
|
||||
refresh will be scheduled.</description>
|
||||
<default>300</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH1" type="text">
|
||||
<label>CH1 Name</label>
|
||||
<description>The name of CH1.</description>
|
||||
<default>CH1</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH2" type="text">
|
||||
<label>CH2 Name</label>
|
||||
<description>The name of CH2.</description>
|
||||
<default>CH2</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH3" type="text">
|
||||
<label>CH3 Name</label>
|
||||
<description>The name of CH3.</description>
|
||||
<default>CH3</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH4" type="text">
|
||||
<label>CH4 Name</label>
|
||||
<description>The name of CH4.</description>
|
||||
<default>CH4</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH5" type="text">
|
||||
<label>CH5 Name</label>
|
||||
<description>The name of CH5.</description>
|
||||
<default>CH5</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH6" type="text">
|
||||
<label>CH6 Name</label>
|
||||
<description>The name of CH6.</description>
|
||||
<default>CH6</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH7" type="text">
|
||||
<label>CH7 Name</label>
|
||||
<description>The name of CH7.</description>
|
||||
<default>CH7</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH8" type="text">
|
||||
<label>CH8 Name</label>
|
||||
<description>The name of CH8.</description>
|
||||
<default>CH8</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH9" type="text">
|
||||
<label>CH9 Name</label>
|
||||
<description>The name of CH9.</description>
|
||||
<default>CH9</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH10" type="text">
|
||||
<label>CH10 Name</label>
|
||||
<description>The name of CH10.</description>
|
||||
<default>CH10</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH11" type="text">
|
||||
<label>CH11 Name</label>
|
||||
<description>The name of CH11.</description>
|
||||
<default>CH11</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH12" type="text">
|
||||
<label>CH12 Name</label>
|
||||
<description>The name of CH12.</description>
|
||||
<default>CH12</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH13" type="text">
|
||||
<label>CH13 Name</label>
|
||||
<description>The name of CH13.</description>
|
||||
<default>CH13</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH14" type="text">
|
||||
<label>CH14 Name</label>
|
||||
<description>The name of CH14.</description>
|
||||
<default>CH14</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH15" type="text">
|
||||
<label>CH15 Name</label>
|
||||
<description>The name of CH15.</description>
|
||||
<default>CH15</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH16" type="text">
|
||||
<label>CH16 Name</label>
|
||||
<description>The name of CH16.</description>
|
||||
<default>CH16</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH17" type="text">
|
||||
<label>CH17 Name</label>
|
||||
<description>The name of CH17.</description>
|
||||
<default>CH17</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH18" type="text">
|
||||
<label>CH18 Name</label>
|
||||
<description>The name of CH18.</description>
|
||||
<default>CH18</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH19" type="text">
|
||||
<label>CH19 Name</label>
|
||||
<description>The name of CH19.</description>
|
||||
<default>CH19</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH20" type="text">
|
||||
<label>CH20 Name</label>
|
||||
<description>The name of CH20.</description>
|
||||
<default>CH20</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH21" type="text">
|
||||
<label>CH21 Name</label>
|
||||
<description>The name of CH21.</description>
|
||||
<default>CH21</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH22" type="text">
|
||||
<label>CH22 Name</label>
|
||||
<description>The name of CH22.</description>
|
||||
<default>CH22</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH23" type="text">
|
||||
<label>CH23 Name</label>
|
||||
<description>The name of CH23.</description>
|
||||
<default>CH23</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH24" type="text">
|
||||
<label>CH24 Name</label>
|
||||
<description>The name of CH24.</description>
|
||||
<default>CH24</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH25" type="text">
|
||||
<label>CH25 Name</label>
|
||||
<description>The name of CH25.</description>
|
||||
<default>CH25</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH26" type="text">
|
||||
<label>CH26 Name</label>
|
||||
<description>The name of CH26.</description>
|
||||
<default>CH26</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH27" type="text">
|
||||
<label>CH27 Name</label>
|
||||
<description>The name of CH27.</description>
|
||||
<default>CH27</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH28" type="text">
|
||||
<label>CH28 Name</label>
|
||||
<description>The name of CH28.</description>
|
||||
<default>CH28</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH29" type="text">
|
||||
<label>CH29 Name</label>
|
||||
<description>The name of CH29.</description>
|
||||
<default>CH29</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH30" type="text">
|
||||
<label>CH30 Name</label>
|
||||
<description>The name of CH30.</description>
|
||||
<default>CH30</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH31" type="text">
|
||||
<label>CH31 Name</label>
|
||||
<description>The name of CH31.</description>
|
||||
<default>CH31</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH32" type="text">
|
||||
<label>CH32 Name</label>
|
||||
<description>The name of CH32.</description>
|
||||
<default>CH32</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="CH33" type="text">
|
||||
<label>CH33 Name</label>
|
||||
<description>The name of CH33 (temperature sensor channel).</description>
|
||||
<default>Temperature</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</config-description:config-descriptions>
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user