added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
@@ -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