2 * Copyright (c) 2010-2023 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.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
24 import org.openhab.binding.velbus.internal.VelbusFirstGenerationDeviceModuleAddress;
25 import org.openhab.binding.velbus.internal.VelbusModuleAddress;
26 import org.openhab.binding.velbus.internal.config.VelbusThingConfig;
27 import org.openhab.binding.velbus.internal.packets.VelbusBlindOffPacket;
28 import org.openhab.binding.velbus.internal.packets.VelbusBlindPositionPacket;
29 import org.openhab.binding.velbus.internal.packets.VelbusBlindUpDownPacket;
30 import org.openhab.binding.velbus.internal.packets.VelbusPacket;
31 import org.openhab.binding.velbus.internal.packets.VelbusStatusRequestPacket;
32 import org.openhab.core.library.types.PercentType;
33 import org.openhab.core.library.types.StopMoveType;
34 import org.openhab.core.library.types.UpDownType;
35 import org.openhab.core.thing.ChannelUID;
36 import org.openhab.core.thing.Thing;
37 import org.openhab.core.thing.ThingStatus;
38 import org.openhab.core.thing.ThingStatusDetail;
39 import org.openhab.core.thing.ThingTypeUID;
40 import org.openhab.core.types.Command;
41 import org.openhab.core.types.RefreshType;
44 * The {@link VelbusBlindsHandler} is responsible for handling commands, which are
45 * sent to one of the channels.
47 * @author Cedric Boon - Initial contribution
50 public class VelbusBlindsHandler extends VelbusThingHandler {
51 public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(
52 Arrays.asList(THING_TYPE_VMB1BL, THING_TYPE_VMB1BLS, THING_TYPE_VMB2BL, THING_TYPE_VMB2BLE));
54 public VelbusBlindsHandler(Thing thing) {
59 public void handleCommand(ChannelUID channelUID, Command command) {
60 VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
61 if (velbusBridgeHandler == null) {
62 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
66 if (command instanceof RefreshType) {
67 VelbusStatusRequestPacket packet = new VelbusStatusRequestPacket(
68 getModuleAddress().getChannelIdentifier(channelUID));
70 byte[] packetBytes = packet.getBytes();
71 velbusBridgeHandler.sendPacket(packetBytes);
72 } else if (command instanceof UpDownType upDownCommand) {
73 if (upDownCommand == UpDownType.UP) {
74 byte commandByte = COMMAND_BLIND_UP;
76 VelbusBlindUpDownPacket packet = new VelbusBlindUpDownPacket(
77 getModuleAddress().getChannelIdentifier(channelUID), commandByte);
79 byte[] packetBytes = packet.getBytes();
80 velbusBridgeHandler.sendPacket(packetBytes);
82 byte commandByte = COMMAND_BLIND_DOWN;
84 VelbusBlindUpDownPacket packet = new VelbusBlindUpDownPacket(
85 getModuleAddress().getChannelIdentifier(channelUID), commandByte);
87 byte[] packetBytes = packet.getBytes();
88 velbusBridgeHandler.sendPacket(packetBytes);
90 } else if (command instanceof StopMoveType stopMoveCommand) {
91 if (stopMoveCommand == StopMoveType.STOP) {
92 VelbusBlindOffPacket packet = new VelbusBlindOffPacket(
93 getModuleAddress().getChannelIdentifier(channelUID));
95 byte[] packetBytes = packet.getBytes();
96 velbusBridgeHandler.sendPacket(packetBytes);
98 } else if (command instanceof PercentType percentCommand) {
99 VelbusBlindPositionPacket packet = new VelbusBlindPositionPacket(
100 getModuleAddress().getChannelIdentifier(channelUID), percentCommand.byteValue());
102 byte[] packetBytes = packet.getBytes();
103 velbusBridgeHandler.sendPacket(packetBytes);
105 logger.debug("The command '{}' is not supported by this handler.", command.getClass());
110 protected @Nullable VelbusModuleAddress createVelbusModuleAddress(int numberOfSubAddresses) {
111 final VelbusThingConfig velbusThingConfig = this.velbusThingConfig;
112 if (velbusThingConfig != null) {
113 byte address = hexToByte(velbusThingConfig.address);
115 if (isFirstGenerationDevice()) {
116 return new VelbusFirstGenerationDeviceModuleAddress(address);
119 return new VelbusModuleAddress(address, numberOfSubAddresses);
125 private Boolean isFirstGenerationDevice() {
126 ThingTypeUID thingTypeUID = this.getThing().getThingTypeUID();
127 return thingTypeUID.equals(THING_TYPE_VMB1BL) || thingTypeUID.equals(THING_TYPE_VMB2BL);
131 public void onPacketReceived(byte[] packet) {
132 logger.trace("onPacketReceived() was called");
134 if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
135 byte command = packet[4];
137 if (command == COMMAND_BLIND_STATUS && packet.length >= 9) {
138 byte address = packet[2];
139 byte channel = packet[5];
140 byte blindPosition = packet[9];
142 VelbusChannelIdentifier velbusChannelIdentifier = new VelbusChannelIdentifier(address, channel);
143 PercentType state = new PercentType(blindPosition);
144 updateState(getModuleAddress().getChannelId(velbusChannelIdentifier), state);