[velbus] New module VMBELPIR + Improvement clock alarms management (#12390)

* [velbus] Add new functionality PRESSED and LONG PRESSED and fix bug

New functionnality :
Add the the possibility to simulate the PRESSED and LONG PRESSED message of an input.

Module supported with button simulation :
VMB1RYS (button : CH6)
VMB6IN (buttons : CH1 ... CH6)
VMB2PBN, VMB6PBN, VMB7IN, VMB8IR, VMB8PB, VMB8PBU, VMBEL1, VMBEL2, VMBEL4, VMBGP1, VMBGP1-2, VMBGP2, VMBGP2-2, VMBGP4, VMBGP4-2, VMBGP4PIR, VMBGP4PIR-2 (buttons : CH1 ... CH8)
VMBELO, VMBGPOD, VMBGPOD-2 (buttons : CH1 ... CH32)

Fix bug :

The channels names were not correctly assigned to the thing properties. The last channel had the default name, not the one retrieved from the module.

* Add trigger on channel when using button simulation

Remove uneeded  Thread.sleep in code.
Trigger the events PRESSED, LONG_PRESSED, RELEASED on the linked trigger channel when using the button simulation.

* Fix redundant superinterface DiscoveryService

Redundant superinterface DiscoveryService for the type VelbusThingDiscoveryService, already defined by AbstractDiscoveryService.

* Fix bug #11521

Typo in the Counter Channel name for VMB7IN.

* [velbus] Add VMBELPIR module

* [velbus] Updates clock alarms management

Changes the clocks alarm management :
- Global alarms are now set from the bridge thing.
- Local alarms are still set from the module thing, but the alarm type channels on modules are now readonly.

Reduces the flooding of the bus by adding a delay of 10 seconds before sending the update on the bus :
- Removes the send on the bus after each update of a clock alarm value.
- Sends only the values of the last update after 10 seconds.

Signed-off-by: Daniel Rosengarten <github@praetorians.be>
This commit is contained in:
Daniel Rosengarten
2022-03-27 23:21:17 +02:00
committed by GitHub
parent cd1bf9c950
commit 53bb6f48ad
8 changed files with 402 additions and 58 deletions

View File

@@ -66,6 +66,7 @@ public class VelbusBindingConstants {
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");
@@ -94,8 +95,8 @@ public class VelbusBindingConstants {
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)));
@@ -142,6 +143,7 @@ public class VelbusBindingConstants {
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;
@@ -224,4 +226,31 @@ public class VelbusBindingConstants {
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;
}

View File

@@ -239,6 +239,10 @@ public class VelbusThingDiscoveryService extends AbstractDiscoveryService
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);

View File

@@ -12,6 +12,8 @@
*/
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;
@@ -27,13 +29,18 @@ import java.util.concurrent.TimeUnit;
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;
@@ -49,6 +56,8 @@ import org.slf4j.LoggerFactory;
* 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 {
@@ -68,6 +77,11 @@ 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);
}
@@ -141,7 +155,90 @@ public abstract class VelbusBridgeHandler extends BaseBridgeHandler {
@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) {
@@ -282,4 +379,40 @@ public abstract class VelbusBridgeHandler extends BaseBridgeHandler {
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);
}
}

View File

@@ -18,6 +18,7 @@ import java.util.Arrays;
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;
@@ -40,6 +41,8 @@ import org.openhab.core.types.RefreshType;
* 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 {
@@ -58,6 +61,7 @@ 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);
@@ -110,6 +114,9 @@ public class VelbusSensorWithAlarmClockHandler extends VelbusSensorHandler {
private int clockAlarmConfigurationMemoryAddress;
private VelbusClockAlarmConfiguration alarmClockConfiguration = new VelbusClockAlarmConfiguration();
private long lastUpdateAlarm1TimeMillis;
private long lastUpdateAlarm2TimeMillis;
public VelbusSensorWithAlarmClockHandler(Thing thing) {
this(thing, 0);
}
@@ -146,42 +153,105 @@ public class VelbusSensorWithAlarmClockHandler extends VelbusSensorHandler {
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);
@@ -295,26 +365,43 @@ public class VelbusSensorWithAlarmClockHandler extends VelbusSensorHandler {
}
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() {

View File

@@ -28,11 +28,12 @@ import org.openhab.core.thing.ThingTypeUID;
* 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"));

View File

@@ -69,6 +69,8 @@ thing-type.velbus.vmbel4.label = VMBEL4
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
@@ -415,6 +417,8 @@ channel-group-type.velbus.1channelFeedbackModule.label = Feedback
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
@@ -449,7 +453,19 @@ channel-group-type.velbus.9channelInputModuleWithTemperatureAndLightSensor.label
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

View File

@@ -7,12 +7,18 @@
<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>
@@ -531,6 +537,25 @@
<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"/>
@@ -884,7 +909,7 @@
<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>
@@ -1292,6 +1317,16 @@
<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>
@@ -1444,8 +1479,46 @@
<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>