The supported Velbus devices are:
```
-vmb1bl, vmb1bls, vmb1dm, vmb1led, vmb1ry, vmb1ryno, vmb1rynos, vmb1rys, vmb1ts, vmb2bl, vmb2ble, vmb2pbn, vmb4an, vmb4dc, vmb4ry, vmb4ryld, vmb4ryno, vmb6in, vmb6pbn, vmb7in, vmb8ir, vmb8pb, vmb8pbu, vmbdme, vmbdmi, vmbdmir, vmbel1, vmbel2, vmbel4, vmbelo, vmbgp1, vmbgp2, vmbgp4, vmbgp4pir, vmbgpo, vmbgpod, vmbmeteo, vmbpirc, vmbpirm, vmbpiro, vmbvp1
+vmb1bl, vmb1bls, vmb1dm, vmb1led, vmb1ry, vmb1ryno, vmb1rynos, vmb1rys, vmb1ts, vmb2bl, vmb2ble, vmb2pbn, vmb4an, vmb4dc, vmb4ry, vmb4ryld, vmb4ryno, vmb6in, vmb6pbn, vmb7in, vmb8ir, vmb8pb, vmb8pbu, vmbdme, vmbdmi, vmbdmir, vmbel1, vmbel2, vmbel4, vmbelo, vmbelpir, vmbgp1, vmbgp2, vmbgp4, vmbgp4pir, vmbgpo, vmbgpod, vmbmeteo, vmbpirc, vmbpirm, vmbpiro, vmbvp1
```
The type of a specific device can be found in the configuration section for things in the UI.
The following thing types are valid for configuration:
```
-vmb1bl, vmb1bls, vmb1dm, vmb1led, vmb1ry, vmb1ryno, vmb1rynos, vmb1rys, vmb1ts, vmb2bl, vmb2ble, vmb2pbn, vmb4an, vmb4dc, vmb4ry, vmb4ryld, vmb4ryno, vmb6in, vmb6pbn, vmb7in, vmb8ir, vmb8pb, vmb8pbu, vmbdme, vmbdmi, vmbdmir, vmbel1, vmbel2, vmbel4, vmbelo, vmbgp1, vmbgp2, vmbgp4, vmbgp4pir, vmbgpo, vmbgpod, vmbmeteo, vmbpirc, vmbpirm, vmbpiro, vmbvp1
+vmb1bl, vmb1bls, vmb1dm, vmb1led, vmb1ry, vmb1ryno, vmb1rynos, vmb1rys, vmb1ts, vmb2bl, vmb2ble, vmb2pbn, vmb4an, vmb4dc, vmb4ry, vmb4ryld, vmb4ryno, vmb6in, vmb6pbn, vmb7in, vmb8ir, vmb8pb, vmb8pbu, vmbdme, vmbdmi, vmbdmir, vmbel1, vmbel2, vmbel4, vmbelo, vmbelpir, vmbgp1, vmbgp2, vmbgp4, vmbgp4pir, vmbgpo, vmbgpod, vmbmeteo, vmbpirc, vmbpirm, vmbpiro, vmbvp1
```
`thingId` is the hexadecimal Velbus address of the thing.
The following thing types support a sensor refresh interval:
```
-vmb1ts, vmb4an, vmbel1, vmbel2, vmbel4, vmbelo, vmbgp1, vmbgp2, vmbgp4, vmbgp4pir, vmbgpo, vmbgpod, vmbmeteo, vmbpirc, vmbpirm, vmbpiro
+vmb1ts, vmb4an, vmbel1, vmbel2, vmbel4, vmbelo, vmbelpir, vmbgp1, vmbgp2, vmbgp4, vmbgp4pir, vmbgpo, vmbgpod, vmbmeteo, vmbpirc, vmbpirm, vmbpiro
```
The `vmb7in` thing type also supports a refresh interval. For this thing type, the refresh interval is the interval at which the counter values should be refreshed.
For thing type `vmb4ry` 4 channels are available `CH1` ... `CH4`.
OnOff command types are supported.
-Thing types `vmbel1`, `vmbel2`, `vmbel4`, `vmbgp1`, `vmbgp2`, `vmbgp4`, `vmbgp4pir` and `vmbpiro` have 8 trigger channels `input:CH1` ... `input:CH8` and one temperature channel `input:CH9`.
-Pressed and Long_Pressed command types are supported on channels `button#CH1` ... `button#CH8`.
+Thing types `vmbel1`, `vmbel2`, `vmbel4`, `vmbelpir`, `vmbgp1`, `vmbgp2`, `vmbgp4`, `vmbgp4pir` and `vmbpiro` have 8 trigger channels `input:CH1` ... `input:CH8` and one temperature channel `input:CH9`.
+Pressed and Long_Pressed command types are supported on channels `button#CH1` and `button#CH2` for the thing type `vmbelpir`.
+Pressed and Long_Pressed command types are supported on channels `button#CH1` ... `button#CH8` for the thing types `vmbel1`, `vmbel2`, `vmbel4`, `vmbgp1`, `vmbgp2`, `vmbgp4`, `vmbgp4pir` and `vmbpiro`.
The thing types `vmbel1` and `vmbgp1` have one channel to steer the button LED feedback `feedback:CH1`.
The thing types `vmbel2` and `vmbgp2` have two channels to steer the button LED feedback `feedback:CH1` and `feedback:CH2`.
The thing types `vmbel4`, `vmbgp4` and `vmbgp4pir` have four channels to steer the button LED feedback `feedback:CH1` ... `feedback:CH4`.
The thing type `vmbpiro` has a channel `input:LIGHT` indicating the illuminance.
-Thing types `vmbel1`, `vmbel2`, `vmbel4`, `vmbgp1`, `vmbgp2`, `vmbgp4` and `vmbgp4pir` have a number of channels to set the module's alarms: `clockAlarm:clockAlarm1Enabled`, `clockAlarm:clockAlarm1Type`, `clockAlarm:clockAlarm1WakeupHour`, `clockAlarm:clockAlarm1WakeupMinute`, `clockAlarm:clockAlarm1BedtimeHour`, `clockAlarm:clockAlarm1BedtimeMinute`, `clockAlarm:clockAlarm2Enabled`, `clockAlarm:clockAlarm2Type`, `clockAlarm:clockAlarm2WakeupHour`, `clockAlarm:clockAlarm2WakeupMinute`, `clockAlarm:clockAlarm2BedtimeHour` and `clockAlarm:clockAlarm2BedtimeMinute`.
-Thing types `vmbel1`, `vmbel2`, `vmbel4`, `vmbgp1`, `vmbgp2`, `vmbgp4` and `vmbgp4pir` also have a number of channels to set the module's thermostat (`thermostat:currentTemperatureSetpoint`, `thermostat:heatingModeComfortTemperatureSetpoint`, `thermostat:heatingModeDayTemperatureSetpoint`, `thermostat:heatingModeNightTemperatureSetpoint`, `thermostat:heatingModeAntiFrostTemperatureSetpoint`, `thermostat:coolingModeComfortTemperatureSetpoint`, `thermostat:coolingModeDayTemperatureSetpoint`, `thermostat:coolingModeNightTemperatureSetpoint`, `thermostat:coolingModeSafeTemperatureSetpoint`, `operatingMode` and `thermostat:mode`) and thermostat trigger channels: `thermostat:heater`, `thermostat:boost`, `thermostat:pump`, `thermostat:cooler`, `thermostat:alarm1`, `thermostat:alarm2`, `thermostat:alarm3`, `thermostat:alarm4`.
+Thing types `vmbel1`, `vmbel2`, `vmbel4`, `vmbelpir`, `vmbgp1`, `vmbgp2`, `vmbgp4` and `vmbgp4pir` have a number of channels to set the module's alarms: `clockAlarm:clockAlarm1Enabled`, `clockAlarm:clockAlarm1Type`, `clockAlarm:clockAlarm1WakeupHour`, `clockAlarm:clockAlarm1WakeupMinute`, `clockAlarm:clockAlarm1BedtimeHour`, `clockAlarm:clockAlarm1BedtimeMinute`, `clockAlarm:clockAlarm2Enabled`, `clockAlarm:clockAlarm2Type`, `clockAlarm:clockAlarm2WakeupHour`, `clockAlarm:clockAlarm2WakeupMinute`, `clockAlarm:clockAlarm2BedtimeHour` and `clockAlarm:clockAlarm2BedtimeMinute`.
+Thing types `vmbel1`, `vmbel2`, `vmbel4`, `vmbelpir`, `vmbgp1`, `vmbgp2`, `vmbgp4` and `vmbgp4pir` also have a number of channels to set the module's thermostat (`thermostat:currentTemperatureSetpoint`, `thermostat:heatingModeComfortTemperatureSetpoint`, `thermostat:heatingModeDayTemperatureSetpoint`, `thermostat:heatingModeNightTemperatureSetpoint`, `thermostat:heatingModeAntiFrostTemperatureSetpoint`, `thermostat:coolingModeComfortTemperatureSetpoint`, `thermostat:coolingModeDayTemperatureSetpoint`, `thermostat:coolingModeNightTemperatureSetpoint`, `thermostat:coolingModeSafeTemperatureSetpoint`, `operatingMode` and `thermostat:mode`) and thermostat trigger channels: `thermostat:heater`, `thermostat:boost`, `thermostat:pump`, `thermostat:cooler`, `thermostat:alarm1`, `thermostat:alarm2`, `thermostat:alarm3`, `thermostat:alarm4`.
Thing types `vmbelo`, `vmbgpo` and `vmbgpod` have 32 trigger channels `input:CH1` ... `input:CH32` and one temperature channel `input:CH33`.
Pressed and Long_Pressed command types are supported on channels `button#CH1` ... `button#CH32`.
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_VMBELPIR = new ThingTypeUID(BINDING_ID, "vmbelpir");
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");
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_VMBEL2, THING_TYPE_VMBEL4, THING_TYPE_VMBELO, THING_TYPE_VMBELPIR, 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, THING_TYPE_VMBVP1)));
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_VMBELPIR = 0x38;
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 String CHANNEL = "CH";
public static final String SUB_ADDRESS = "subaddress";
public static final String DIMSPEED = "dimspeed";
+
+ // Channels ids
+ public static final String CHANNEL_BRIDGE_CLOCK_ALARM1_ENABLED = "bridgeClockAlarm#clockAlarm1Enabled";
+ public static final String CHANNEL_BRIDGE_CLOCK_ALARM1_WAKEUP_HOUR = "bridgeClockAlarm#clockAlarm1WakeupHour";
+ public static final String CHANNEL_BRIDGE_CLOCK_ALARM1_WAKEUP_MINUTE = "bridgeClockAlarm#clockAlarm1WakeupMinute";
+ public static final String CHANNEL_BRIDGE_CLOCK_ALARM1_BEDTIME_HOUR = "bridgeClockAlarm#clockAlarm1BedtimeHour";
+ public static final String CHANNEL_BRIDGE_CLOCK_ALARM1_BEDTIME_MINUTE = "bridgeClockAlarm#clockAlarm1BedtimeMinute";
+ public static final String CHANNEL_BRIDGE_CLOCK_ALARM2_ENABLED = "bridgeClockAlarm#clockAlarm2Enabled";
+ public static final String CHANNEL_BRIDGE_CLOCK_ALARM2_WAKEUP_HOUR = "bridgeClockAlarm#clockAlarm2WakeupHour";
+ public static final String CHANNEL_BRIDGE_CLOCK_ALARM2_WAKEUP_MINUTE = "bridgeClockAlarm#clockAlarm2WakeupMinute";
+ public static final String CHANNEL_BRIDGE_CLOCK_ALARM2_BEDTIME_HOUR = "bridgeClockAlarm#clockAlarm2BedtimeHour";
+ public static final String CHANNEL_BRIDGE_CLOCK_ALARM2_BEDTIME_MINUTE = "bridgeClockAlarm#clockAlarm2BedtimeMinute";
+ public static final String CHANNEL_MODULE_CLOCK_ALARM1_ENABLED = "clockAlarm#clockAlarm1Enabled";
+ public static final String CHANNEL_MODULE_CLOCK_ALARM1_TYPE = "clockAlarm#clockAlarm1Type";
+ public static final String CHANNEL_MODULE_CLOCK_ALARM1_WAKEUP_HOUR = "clockAlarm#clockAlarm1WakeupHour";
+ public static final String CHANNEL_MODULE_CLOCK_ALARM1_WAKEUP_MINUTE = "clockAlarm#clockAlarm1WakeupMinute";
+ public static final String CHANNEL_MODULE_CLOCK_ALARM1_BEDTIME_HOUR = "clockAlarm#clockAlarm1BedtimeHour";
+ public static final String CHANNEL_MODULE_CLOCK_ALARM1_BEDTIME_MINUTE = "clockAlarm#clockAlarm1BedtimeMinute";
+ public static final String CHANNEL_MODULE_CLOCK_ALARM2_ENABLED = "clockAlarm#clockAlarm2Enabled";
+ public static final String CHANNEL_MODULE_CLOCK_ALARM2_TYPE = "clockAlarm#clockAlarm2Type";
+ public static final String CHANNEL_MODULE_CLOCK_ALARM2_WAKEUP_HOUR = "clockAlarm#clockAlarm2WakeupHour";
+ public static final String CHANNEL_MODULE_CLOCK_ALARM2_WAKEUP_MINUTE = "clockAlarm#clockAlarm2WakeupMinute";
+ public static final String CHANNEL_MODULE_CLOCK_ALARM2_BEDTIME_HOUR = "clockAlarm#clockAlarm2BedtimeHour";
+ public static final String CHANNEL_MODULE_CLOCK_ALARM2_BEDTIME_MINUTE = "clockAlarm#clockAlarm2BedtimeMinute";
+
+ // Delay
+ public static final Integer DELAY_SEND_CLOCK_ALARM_UPDATE = 10000;
}
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBELO, 33);
break;
+ case MODULE_TYPE_VMBELPIR:
+ velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
+ lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBELPIR, 9);
+ break;
case MODULE_TYPE_VMBGP1:
velbusModule = new VelbusModule(new VelbusModuleAddress(address, 4), moduleType, highByteOfSerialNumber,
lowByteOfSerialNumber, memoryMapVersion, buildYear, buildWeek, THING_TYPE_VMBGP1, 9);
*/
package org.openhab.binding.velbus.internal.handler;
+import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.velbus.internal.VelbusClockAlarm;
+import org.openhab.binding.velbus.internal.VelbusClockAlarmConfiguration;
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.VelbusSetLocalClockAlarmPacket;
import org.openhab.binding.velbus.internal.packets.VelbusSetRealtimeClockPacket;
+import org.openhab.core.library.types.DecimalType;
+import org.openhab.core.library.types.OnOffType;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.ThingStatus;
* the framework.
*
* @author Cedric Boon - Initial contribution
+ * @author Daniel Rosengarten - Add global alarm configuration from bridge (removed from modules), reduces bus flooding
+ * on alarm value update
*/
@NonNullByDefault
public abstract class VelbusBridgeHandler extends BaseBridgeHandler {
private boolean listenerStopped;
+ private VelbusClockAlarmConfiguration alarmClockConfiguration = new VelbusClockAlarmConfiguration();
+
+ private long lastUpdateAlarm1TimeMillis;
+ private long lastUpdateAlarm2TimeMillis;
+
public VelbusBridgeHandler(Bridge velbusBridge) {
super(velbusBridge);
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
- // There is nothing to handle in the bridge handler
+ if (isAlarmClockChannel(channelUID)) {
+ byte alarmNumber = determineAlarmNumber(channelUID);
+ VelbusClockAlarm alarmClock = alarmClockConfiguration.getAlarmClock(alarmNumber);
+
+ alarmClock.setLocal(false);
+
+ switch (channelUID.getId()) {
+ case CHANNEL_BRIDGE_CLOCK_ALARM1_ENABLED:
+ case CHANNEL_BRIDGE_CLOCK_ALARM2_ENABLED: {
+ if (command instanceof OnOffType) {
+ boolean enabled = command == OnOffType.ON;
+ alarmClock.setEnabled(enabled);
+ }
+ break;
+ }
+ case CHANNEL_BRIDGE_CLOCK_ALARM1_WAKEUP_HOUR:
+ case CHANNEL_BRIDGE_CLOCK_ALARM2_WAKEUP_HOUR: {
+ if (command instanceof DecimalType) {
+ byte wakeupHour = ((DecimalType) command).byteValue();
+ alarmClock.setWakeupHour(wakeupHour);
+ }
+ break;
+ }
+ case CHANNEL_BRIDGE_CLOCK_ALARM1_WAKEUP_MINUTE:
+ case CHANNEL_BRIDGE_CLOCK_ALARM2_WAKEUP_MINUTE: {
+ if (command instanceof DecimalType) {
+ byte wakeupMinute = ((DecimalType) command).byteValue();
+ alarmClock.setWakeupMinute(wakeupMinute);
+ }
+ break;
+ }
+ case CHANNEL_BRIDGE_CLOCK_ALARM1_BEDTIME_HOUR:
+ case CHANNEL_BRIDGE_CLOCK_ALARM2_BEDTIME_HOUR: {
+ if (command instanceof DecimalType) {
+ byte bedTimeHour = ((DecimalType) command).byteValue();
+ alarmClock.setBedtimeHour(bedTimeHour);
+ }
+ break;
+ }
+ case CHANNEL_BRIDGE_CLOCK_ALARM1_BEDTIME_MINUTE:
+ case CHANNEL_BRIDGE_CLOCK_ALARM2_BEDTIME_MINUTE: {
+ if (command instanceof DecimalType) {
+ byte bedTimeMinute = ((DecimalType) command).byteValue();
+ alarmClock.setBedtimeMinute(bedTimeMinute);
+ }
+ break;
+ }
+ }
+
+ if (alarmNumber == 1) {
+ lastUpdateAlarm1TimeMillis = System.currentTimeMillis();
+ } else {
+ lastUpdateAlarm2TimeMillis = System.currentTimeMillis();
+ }
+
+ VelbusSetLocalClockAlarmPacket packet = new VelbusSetLocalClockAlarmPacket((byte) 0x00, alarmNumber,
+ alarmClock);
+ byte[] packetBytes = packet.getBytes();
+
+ // Schedule the send of the packet to see if there is another update in less than 10 secondes (reduce
+ // flooding of the bus)
+ scheduler.schedule(() -> {
+ sendAlarmPacket(alarmNumber, packetBytes);
+ }, DELAY_SEND_CLOCK_ALARM_UPDATE, TimeUnit.MILLISECONDS);
+ } else {
+ logger.debug("The command '{}' is not supported by this handler.", command.getClass());
+ }
+ }
+
+ public synchronized void sendAlarmPacket(int alarmNumber, byte[] packetBytes) {
+ long timeSinceLastUpdate;
+
+ if (alarmNumber == 1) {
+ timeSinceLastUpdate = System.currentTimeMillis() - lastUpdateAlarm1TimeMillis;
+ } else {
+ timeSinceLastUpdate = System.currentTimeMillis() - lastUpdateAlarm2TimeMillis;
+ }
+
+ // If a value of the alarm has been updated, discard this old update
+ if (timeSinceLastUpdate < DELAY_SEND_CLOCK_ALARM_UPDATE) {
+ return;
+ }
+
+ sendPacket(packetBytes);
}
public synchronized void sendPacket(byte[] packet) {
public void unregisterRelayStatusListener(byte address) {
packetListeners.remove(Byte.valueOf(address));
}
+
+ protected boolean isAlarmClockChannel(ChannelUID channelUID) {
+ switch (channelUID.getId()) {
+ case CHANNEL_BRIDGE_CLOCK_ALARM1_ENABLED:
+ case CHANNEL_BRIDGE_CLOCK_ALARM1_WAKEUP_HOUR:
+ case CHANNEL_BRIDGE_CLOCK_ALARM1_WAKEUP_MINUTE:
+ case CHANNEL_BRIDGE_CLOCK_ALARM1_BEDTIME_HOUR:
+ case CHANNEL_BRIDGE_CLOCK_ALARM1_BEDTIME_MINUTE:
+ case CHANNEL_BRIDGE_CLOCK_ALARM2_ENABLED:
+ case CHANNEL_BRIDGE_CLOCK_ALARM2_WAKEUP_HOUR:
+ case CHANNEL_BRIDGE_CLOCK_ALARM2_WAKEUP_MINUTE:
+ case CHANNEL_BRIDGE_CLOCK_ALARM2_BEDTIME_HOUR:
+ case CHANNEL_BRIDGE_CLOCK_ALARM2_BEDTIME_MINUTE:
+ return true;
+ }
+ return false;
+ }
+
+ protected byte determineAlarmNumber(ChannelUID channelUID) {
+ switch (channelUID.getId()) {
+ case CHANNEL_BRIDGE_CLOCK_ALARM1_ENABLED:
+ case CHANNEL_BRIDGE_CLOCK_ALARM1_WAKEUP_HOUR:
+ case CHANNEL_BRIDGE_CLOCK_ALARM1_WAKEUP_MINUTE:
+ case CHANNEL_BRIDGE_CLOCK_ALARM1_BEDTIME_HOUR:
+ case CHANNEL_BRIDGE_CLOCK_ALARM1_BEDTIME_MINUTE:
+ return 1;
+ case CHANNEL_BRIDGE_CLOCK_ALARM2_ENABLED:
+ case CHANNEL_BRIDGE_CLOCK_ALARM2_WAKEUP_HOUR:
+ case CHANNEL_BRIDGE_CLOCK_ALARM2_WAKEUP_MINUTE:
+ case CHANNEL_BRIDGE_CLOCK_ALARM2_BEDTIME_HOUR:
+ case CHANNEL_BRIDGE_CLOCK_ALARM2_BEDTIME_MINUTE:
+ return 2;
+ }
+
+ throw new IllegalArgumentException("The given channelUID is not an alarm clock channel: " + channelUID);
+ }
}
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.velbus.internal.VelbusClockAlarm;
* sent to one of the channels.
*
* @author Cedric Boon - Initial contribution
+ * @author Daniel Rosengarten - Add VMBELPIR support, removes global alarm configuration from module (moved on bridge),
+ * reduces bus flooding on alarm value update
*/
@NonNullByDefault
public class VelbusSensorWithAlarmClockHandler extends VelbusSensorHandler {
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_VMBELPIR, 0x030F);
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);
private int clockAlarmConfigurationMemoryAddress;
private VelbusClockAlarmConfiguration alarmClockConfiguration = new VelbusClockAlarmConfiguration();
+ private long lastUpdateAlarm1TimeMillis;
+ private long lastUpdateAlarm2TimeMillis;
+
public VelbusSensorWithAlarmClockHandler(Thing thing) {
this(thing, 0);
}
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);
+ alarmClock.setLocal(true);
+
+ switch (channelUID.getId()) {
+ case CHANNEL_MODULE_CLOCK_ALARM1_TYPE:
+ case CHANNEL_MODULE_CLOCK_ALARM2_TYPE: {
+ if (command instanceof OnOffType) {
+ // If AlarmType is not read only, it's an old implementation of the module, warn user and
+ // discard the command
+ logger.warn(
+ "Old implementation of thing '{}', still works, but it's better to remove and recreate the thing.",
+ getThing().getUID());
+ }
+ return;
+ }
+ case CHANNEL_MODULE_CLOCK_ALARM1_ENABLED:
+ case CHANNEL_MODULE_CLOCK_ALARM2_ENABLED: {
+ if (command instanceof OnOffType) {
+ boolean enabled = command == OnOffType.ON;
+ alarmClock.setEnabled(enabled);
+ }
+ break;
+ }
+ case CHANNEL_MODULE_CLOCK_ALARM1_WAKEUP_HOUR:
+ case CHANNEL_MODULE_CLOCK_ALARM2_WAKEUP_HOUR: {
+ if (command instanceof DecimalType) {
+ byte wakeupHour = ((DecimalType) command).byteValue();
+ alarmClock.setWakeupHour(wakeupHour);
+ }
+ break;
+ }
+ case CHANNEL_MODULE_CLOCK_ALARM1_WAKEUP_MINUTE:
+ case CHANNEL_MODULE_CLOCK_ALARM2_WAKEUP_MINUTE: {
+ if (command instanceof DecimalType) {
+ byte wakeupMinute = ((DecimalType) command).byteValue();
+ alarmClock.setWakeupMinute(wakeupMinute);
+ }
+ break;
+ }
+ case CHANNEL_MODULE_CLOCK_ALARM1_BEDTIME_HOUR:
+ case CHANNEL_MODULE_CLOCK_ALARM2_BEDTIME_HOUR: {
+ if (command instanceof DecimalType) {
+ byte bedTimeHour = ((DecimalType) command).byteValue();
+ alarmClock.setBedtimeHour(bedTimeHour);
+ }
+ break;
+ }
+ case CHANNEL_MODULE_CLOCK_ALARM1_BEDTIME_MINUTE:
+ case CHANNEL_MODULE_CLOCK_ALARM2_BEDTIME_MINUTE: {
+ if (command instanceof DecimalType) {
+ byte bedTimeMinute = ((DecimalType) command).byteValue();
+ alarmClock.setBedtimeMinute(bedTimeMinute);
+ }
+ break;
+ }
}
- byte address = alarmClock.isLocal() ? getModuleAddress().getAddress() : 0x00;
- VelbusSetLocalClockAlarmPacket packet = new VelbusSetLocalClockAlarmPacket(address, alarmNumber,
- alarmClock);
+ if (alarmNumber == 1) {
+ lastUpdateAlarm1TimeMillis = System.currentTimeMillis();
+ } else {
+ lastUpdateAlarm2TimeMillis = System.currentTimeMillis();
+ }
+
+ VelbusSetLocalClockAlarmPacket packet = new VelbusSetLocalClockAlarmPacket(getModuleAddress().getAddress(),
+ alarmNumber, alarmClock);
byte[] packetBytes = packet.getBytes();
- velbusBridgeHandler.sendPacket(packetBytes);
+
+ // Schedule the send of the packet to see if there is another update in less than 10 secondes (reduce
+ // flooding of the bus)
+ scheduler.schedule(() -> {
+ sendAlarmPacket(alarmNumber, packetBytes);
+ }, DELAY_SEND_CLOCK_ALARM_UPDATE, TimeUnit.MILLISECONDS);
} else {
logger.debug("The command '{}' is not supported by this handler.", command.getClass());
}
}
+ public synchronized void sendAlarmPacket(int alarmNumber, byte[] packetBytes) {
+ VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
+ if (velbusBridgeHandler == null) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
+ return;
+ }
+
+ long timeSinceLastUpdate;
+
+ if (alarmNumber == 1) {
+ timeSinceLastUpdate = System.currentTimeMillis() - lastUpdateAlarm1TimeMillis;
+ } else {
+ timeSinceLastUpdate = System.currentTimeMillis() - lastUpdateAlarm2TimeMillis;
+ }
+
+ // If a value of the alarm has been updated, discard this old update
+ if (timeSinceLastUpdate < DELAY_SEND_CLOCK_ALARM_UPDATE) {
+ return;
+ }
+
+ velbusBridgeHandler.sendPacket(packetBytes);
+ }
+
@Override
public void onPacketReceived(byte[] packet) {
super.onPacketReceived(packet);
}
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);
+ switch (channelUID.getId()) {
+ case CHANNEL_MODULE_CLOCK_ALARM1_ENABLED:
+ case CHANNEL_MODULE_CLOCK_ALARM1_TYPE:
+ case CHANNEL_MODULE_CLOCK_ALARM1_WAKEUP_HOUR:
+ case CHANNEL_MODULE_CLOCK_ALARM1_WAKEUP_MINUTE:
+ case CHANNEL_MODULE_CLOCK_ALARM1_BEDTIME_HOUR:
+ case CHANNEL_MODULE_CLOCK_ALARM1_BEDTIME_MINUTE:
+ case CHANNEL_MODULE_CLOCK_ALARM2_ENABLED:
+ case CHANNEL_MODULE_CLOCK_ALARM2_TYPE:
+ case CHANNEL_MODULE_CLOCK_ALARM2_WAKEUP_HOUR:
+ case CHANNEL_MODULE_CLOCK_ALARM2_WAKEUP_MINUTE:
+ case CHANNEL_MODULE_CLOCK_ALARM2_BEDTIME_HOUR:
+ case CHANNEL_MODULE_CLOCK_ALARM2_BEDTIME_MINUTE:
+ return true;
+ }
+ return false;
}
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);
+ switch (channelUID.getId()) {
+ case CHANNEL_MODULE_CLOCK_ALARM1_ENABLED:
+ case CHANNEL_MODULE_CLOCK_ALARM1_TYPE:
+ case CHANNEL_MODULE_CLOCK_ALARM1_WAKEUP_HOUR:
+ case CHANNEL_MODULE_CLOCK_ALARM1_WAKEUP_MINUTE:
+ case CHANNEL_MODULE_CLOCK_ALARM1_BEDTIME_HOUR:
+ case CHANNEL_MODULE_CLOCK_ALARM1_BEDTIME_MINUTE:
+ return 1;
+ case CHANNEL_MODULE_CLOCK_ALARM2_ENABLED:
+ case CHANNEL_MODULE_CLOCK_ALARM2_TYPE:
+ case CHANNEL_MODULE_CLOCK_ALARM2_WAKEUP_HOUR:
+ case CHANNEL_MODULE_CLOCK_ALARM2_WAKEUP_MINUTE:
+ case CHANNEL_MODULE_CLOCK_ALARM2_BEDTIME_HOUR:
+ case CHANNEL_MODULE_CLOCK_ALARM2_BEDTIME_MINUTE:
+ return 2;
}
+
+ throw new IllegalArgumentException("The given channelUID is not an alarm clock channel: " + channelUID);
}
protected int getClockAlarmAndProgramSelectionIndexInModuleStatus() {
* sent to one of the channels.
*
* @author Cedric Boon - Initial contribution
+ * @author Daniel Rosengarten - Add VMBELPIR support
*/
@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));
+ Arrays.asList(THING_TYPE_VMBEL1, THING_TYPE_VMBEL2, THING_TYPE_VMBEL4, THING_TYPE_VMBELPIR));
public VelbusVMBELHandler(Thing thing) {
super(thing, 4, new ChannelUID(thing.getUID(), "input", "CH9"));
thing-type.velbus.vmbel4.description = Edge-lit four touch buttons module
thing-type.velbus.vmbelo.label = VMBELO
thing-type.velbus.vmbelo.description = Edge-lit touch panel with Oled display
+thing-type.velbus.vmbelpir.label = VMBELPIR
+thing-type.velbus.vmbelpir.description = Edge-lit Motion detector with one touch button
thing-type.velbus.vmbgp1-2.label = VMBGP1-2
thing-type.velbus.vmbgp1-2.description = Glass control module with 1 touch key (Edition 2)
thing-type.velbus.vmbgp1.label = VMBGP1
channel-group-type.velbus.1channelFeedbackModule.description = This is a generic module with 1 feedback channel.
channel-group-type.velbus.1channelInputModuleWithTemperatureSensor.label = Input with Temperature Sensor
channel-group-type.velbus.1channelInputModuleWithTemperatureSensor.description = This is a generic module with 8 input channels and a temperature sensor.
+channel-group-type.velbus.2channelButtonModule.label = Button
+channel-group-type.velbus.2channelButtonModule.description = This is a generic module with 2 button channels.
channel-group-type.velbus.2channelFeedbackModule.label = Feedback
channel-group-type.velbus.2channelFeedbackModule.description = This is a generic module with 2 feedback channels.
channel-group-type.velbus.32channelButtonModule.label = Button
channel-group-type.velbus.9channelInputModuleWithTemperatureAndLightSensor.description = This is a generic module with 8 input channels, a temperature sensor and a light sensor.
channel-group-type.velbus.9channelInputModuleWithTemperatureSensor.label = Input with Temperature Sensor
channel-group-type.velbus.9channelInputModuleWithTemperatureSensor.description = This is a generic module with 8 input channels and a temperature sensor.
-channel-group-type.velbus.clockAlarm.label = Clock Alarm
+channel-group-type.velbus.bridgeClockAlarm.label = Global Clock Alarm
+channel-group-type.velbus.bridgeClockAlarm.description = This is a clock alarm with two configurable alarms that can be programmed with a wake up time and a bed time.
+channel-group-type.velbus.bridgeClockAlarm.channel.clockAlarm1BedtimeHour.label = Clock Alarm 1 Bedtime Hour
+channel-group-type.velbus.bridgeClockAlarm.channel.clockAlarm1BedtimeMinute.label = Clock Alarm 1 Bedtime Minute
+channel-group-type.velbus.bridgeClockAlarm.channel.clockAlarm1Enabled.label = Clock Alarm 1 Enabled
+channel-group-type.velbus.bridgeClockAlarm.channel.clockAlarm1WakeupHour.label = Clock Alarm 1 Wakeup Hour
+channel-group-type.velbus.bridgeClockAlarm.channel.clockAlarm1WakeupMinute.label = Clock Alarm 1 Wakeup Minute
+channel-group-type.velbus.bridgeClockAlarm.channel.clockAlarm2BedtimeHour.label = Clock Alarm 2 Bedtime Hour
+channel-group-type.velbus.bridgeClockAlarm.channel.clockAlarm2BedtimeMinute.label = Clock Alarm 2 Bedtime Minute
+channel-group-type.velbus.bridgeClockAlarm.channel.clockAlarm2Enabled.label = Clock Alarm 2 Enabled
+channel-group-type.velbus.bridgeClockAlarm.channel.clockAlarm2WakeupHour.label = Clock Alarm 2 Wakeup Hour
+channel-group-type.velbus.bridgeClockAlarm.channel.clockAlarm2WakeupMinute.label = Clock Alarm 2 Wakeup Minute
+channel-group-type.velbus.clockAlarm.label = Local Clock Alarm
channel-group-type.velbus.clockAlarm.description = This is a clock alarm with two configurable alarms that can be programmed with a wake up time and a bed time.
channel-group-type.velbus.clockAlarm.channel.clockAlarm1BedtimeHour.label = Clock Alarm 1 Bedtime Hour
channel-group-type.velbus.clockAlarm.channel.clockAlarm1BedtimeMinute.label = Clock Alarm 1 Bedtime Minute
<bridge-type id="bridge">
<label>Velbus Serial Bridge</label>
<description>This bridge represents a Velbus Serial-interface</description>
+ <channel-groups>
+ <channel-group id="bridgeClockAlarm" typeId="clockAlarm"/>
+ </channel-groups>
<config-description-ref uri="bridge-type:velbus:bridge"/>
</bridge-type>
<bridge-type id="networkbridge">
<label>Velbus Network Bridge</label>
<description>This bridge represents a Velbus connection over TCP/IP</description>
+ <channel-groups>
+ <channel-group id="bridgeClockAlarm" typeId="clockAlarm"/>
+ </channel-groups>
<config-description-ref uri="bridge-type:velbus:networkbridge"/>
</bridge-type>
<config-description-ref uri="thing-type:velbus:33channelDeviceWithTemperatureSensor"/>
</thing-type>
+ <thing-type id="vmbelpir">
+ <supported-bridge-type-refs>
+ <bridge-type-ref id="bridge"/>
+ <bridge-type-ref id="networkbridge"/>
+ </supported-bridge-type-refs>
+
+ <label>VMBELPIR</label>
+ <description>Edge-lit Motion detector with one touch button</description>
+ <channel-groups>
+ <channel-group id="input" typeId="9channelInputModuleWithTemperatureSensor"/>
+ <channel-group id="button" typeId="2channelButtonModule"/>
+ <channel-group id="feedback" typeId="1channelFeedbackModule"/>
+ <channel-group id="thermostat" typeId="thermostat"/>
+ <channel-group id="clockAlarm" typeId="clockAlarm"/>
+ </channel-groups>
+
+ <config-description-ref uri="thing-type:velbus:9channelDeviceWithTemperatureSensor"/>
+ </thing-type>
+
<thing-type id="vmbgp1">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
<item-type>String</item-type>
<label>Alarm Type</label>
<description>Type (local/global) of the alarm clock in Velbus</description>
- <state>
+ <state readOnly="true">
<options>
<option value="LOCAL">Local</option>
<option value="GLOBAL">Global</option>
<channel id="CH32" typeId="ledFeedback"/>
</channels>
</channel-group-type>
+ <channel-group-type id="2channelButtonModule">
+ <label>Button</label>
+ <description>
+ This is a generic module with 2 button channels.
+ </description>
+ <channels>
+ <channel id="CH1" typeId="button-channel"/>
+ <channel id="CH2" typeId="button-channel"/>
+ </channels>
+ </channel-group-type>
<channel-group-type id="6channelButtonModule">
<label>Button</label>
<description>
<channel id="CH13" typeId="windspeed"/>
</channels>
</channel-group-type>
+ <channel-group-type id="bridgeClockAlarm">
+ <label>Global Clock Alarm</label>
+ <description>This is a clock alarm with two configurable alarms that can be programmed with a wake up time and a bed
+ time.
+ </description>
+ <channels>
+ <channel id="clockAlarm1Enabled" typeId="switch">
+ <label>Clock Alarm 1 Enabled</label>
+ </channel>
+ <channel id="clockAlarm1WakeupHour" typeId="hour">
+ <label>Clock Alarm 1 Wakeup Hour</label>
+ </channel>
+ <channel id="clockAlarm1WakeupMinute" typeId="minute">
+ <label>Clock Alarm 1 Wakeup Minute</label>
+ </channel>
+ <channel id="clockAlarm1BedtimeHour" typeId="hour">
+ <label>Clock Alarm 1 Bedtime Hour</label>
+ </channel>
+ <channel id="clockAlarm1BedtimeMinute" typeId="minute">
+ <label>Clock Alarm 1 Bedtime Minute</label>
+ </channel>
+ <channel id="clockAlarm2Enabled" typeId="switch">
+ <label>Clock Alarm 2 Enabled</label>
+ </channel>
+ <channel id="clockAlarm2WakeupHour" typeId="hour">
+ <label>Clock Alarm 2 Wakeup Hour</label>
+ </channel>
+ <channel id="clockAlarm2WakeupMinute" typeId="minute">
+ <label>Clock Alarm 2 Wakeup Minute</label>
+ </channel>
+ <channel id="clockAlarm2BedtimeHour" typeId="hour">
+ <label>Clock Alarm 2 Bedtime Hour</label>
+ </channel>
+ <channel id="clockAlarm2BedtimeMinute" typeId="minute">
+ <label>Clock Alarm 2 Bedtime Minute</label>
+ </channel>
+ </channels>
+ </channel-group-type>
<channel-group-type id="clockAlarm">
- <label>Clock Alarm</label>
+ <label>Local Clock Alarm</label>
<description>This is a clock alarm with two configurable alarms that can be programmed with a wake up time and a bed
time.
</description>