2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.velbus.internal.handler;
15 import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
17 import java.util.Arrays;
18 import java.util.HashSet;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
23 import org.openhab.binding.velbus.internal.packets.VelbusButtonPacket;
24 import org.openhab.binding.velbus.internal.packets.VelbusFeedbackLEDPacket;
25 import org.openhab.binding.velbus.internal.packets.VelbusPacket;
26 import org.openhab.core.library.types.StringType;
27 import org.openhab.core.thing.ChannelUID;
28 import org.openhab.core.thing.CommonTriggerEvents;
29 import org.openhab.core.thing.Thing;
30 import org.openhab.core.thing.ThingStatus;
31 import org.openhab.core.thing.ThingStatusDetail;
32 import org.openhab.core.thing.ThingTypeUID;
33 import org.openhab.core.types.Command;
36 * The {@link VelbusSensorHandler} is responsible for handling commands, which are
37 * sent to one of the channels.
39 * @author Cedric Boon - Initial contribution
40 * @author Daniel Rosengarten - Add button simulation
43 public class VelbusSensorHandler extends VelbusThingHandler {
44 public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(
45 Arrays.asList(THING_TYPE_VMB6IN, THING_TYPE_VMB8IR, THING_TYPE_VMB8PB));
47 private static final StringType SET_LED = new StringType("SET_LED");
48 private static final StringType SLOW_BLINK_LED = new StringType("SLOW_BLINK_LED");
49 private static final StringType FAST_BLINK_LED = new StringType("FAST_BLINK_LED");
50 private static final StringType VERY_FAST_BLINK_LED = new StringType("VERY_FAST_BLINK_LED");
51 private static final StringType CLEAR_LED = new StringType("CLEAR_LED");
53 private static final StringType PRESSED = new StringType("PRESSED");
54 private static final StringType LONG_PRESSED = new StringType("LONG_PRESSED");
56 public VelbusSensorHandler(Thing thing) {
60 public VelbusSensorHandler(Thing thing, int numberOfSubAddresses) {
61 super(thing, numberOfSubAddresses);
65 public void handleCommand(ChannelUID channelUID, Command command) {
66 VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
67 if (velbusBridgeHandler == null) {
68 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
72 if (isFeedbackChannel(channelUID) && command instanceof StringType stringCommand) {
74 if (stringCommand.equals(SET_LED)) {
75 commandByte = COMMAND_SET_LED;
76 } else if (stringCommand.equals(SLOW_BLINK_LED)) {
77 commandByte = COMMAND_SLOW_BLINK_LED;
78 } else if (stringCommand.equals(FAST_BLINK_LED)) {
79 commandByte = COMMAND_FAST_BLINK_LED;
80 } else if (stringCommand.equals(VERY_FAST_BLINK_LED)) {
81 commandByte = COMMAND_VERY_FAST_BLINK_LED;
82 } else if (stringCommand.equals(CLEAR_LED)) {
83 commandByte = COMMAND_CLEAR_LED;
85 throw new UnsupportedOperationException(
86 "The command '" + command + "' is not supported on channel '" + channelUID + "'.");
89 VelbusFeedbackLEDPacket packet = new VelbusFeedbackLEDPacket(
90 getModuleAddress().getChannelIdentifier(channelUID), commandByte);
92 byte[] packetBytes = packet.getBytes();
93 velbusBridgeHandler.sendPacket(packetBytes);
96 if (isButtonChannel(channelUID) && command instanceof StringType stringCommand) {
97 if (stringCommand.equals(PRESSED) || stringCommand.equals(LONG_PRESSED)) {
98 VelbusButtonPacket packet = new VelbusButtonPacket(getModuleAddress().getChannelIdentifier(channelUID));
101 velbusBridgeHandler.sendPacket(packet.getBytes());
102 triggerChannel("input#CH" + getModuleAddress().getChannelNumber(channelUID),
103 CommonTriggerEvents.PRESSED);
105 if (stringCommand.equals(LONG_PRESSED)) {
106 packet.LongPressed();
107 velbusBridgeHandler.sendPacket(packet.getBytes());
108 triggerChannel("input#CH" + getModuleAddress().getChannelNumber(channelUID),
109 CommonTriggerEvents.LONG_PRESSED);
113 velbusBridgeHandler.sendPacket(packet.getBytes());
114 triggerChannel("input#CH" + getModuleAddress().getChannelNumber(channelUID),
115 CommonTriggerEvents.RELEASED);
117 throw new UnsupportedOperationException(
118 "The command '" + command + "' is not supported on channel '" + channelUID + "'.");
123 private boolean isFeedbackChannel(ChannelUID channelUID) {
124 return "feedback".equals(channelUID.getGroupId());
127 private boolean isButtonChannel(ChannelUID channelUID) {
128 return "button".equals(channelUID.getGroupId());
132 public void onPacketReceived(byte[] packet) {
133 logger.trace("onPacketReceived() was called");
135 if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
136 byte address = packet[2];
137 byte command = packet[4];
139 if (command == COMMAND_PUSH_BUTTON_STATUS && packet.length >= 6) {
140 for (int channel = 0; channel < 8; channel++) {
141 byte channelMask = (byte) Math.pow(2, channel);
143 byte channelJustPressed = (byte) (packet[5] & channelMask);
144 if (channelJustPressed != 0) {
145 VelbusChannelIdentifier velbusChannelIdentifier = new VelbusChannelIdentifier(address,
147 triggerChannel("input#" + getModuleAddress().getChannelId(velbusChannelIdentifier),
148 CommonTriggerEvents.PRESSED);
151 byte channelJustReleased = (byte) (packet[6] & channelMask);
152 if (channelJustReleased != 0) {
153 VelbusChannelIdentifier velbusChannelIdentifier = new VelbusChannelIdentifier(address,
154 channelJustReleased);
155 triggerChannel("input#" + getModuleAddress().getChannelId(velbusChannelIdentifier),
156 CommonTriggerEvents.RELEASED);
159 byte channelLongPressed = (byte) (packet[7] & channelMask);
160 if (channelLongPressed != 0) {
161 VelbusChannelIdentifier velbusChannelIdentifier = new VelbusChannelIdentifier(address,
163 triggerChannel("input#" + getModuleAddress().getChannelId(velbusChannelIdentifier),
164 CommonTriggerEvents.LONG_PRESSED);