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;
20 import java.util.concurrent.ScheduledFuture;
21 import java.util.concurrent.TimeUnit;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.velbus.internal.VelbusChannelIdentifier;
26 import org.openhab.binding.velbus.internal.config.VelbusVMB7INConfig;
27 import org.openhab.binding.velbus.internal.packets.VelbusCounterStatusRequestPacket;
28 import org.openhab.binding.velbus.internal.packets.VelbusPacket;
29 import org.openhab.core.library.types.DecimalType;
30 import org.openhab.core.thing.ChannelUID;
31 import org.openhab.core.thing.Thing;
32 import org.openhab.core.thing.ThingStatus;
33 import org.openhab.core.thing.ThingStatusDetail;
34 import org.openhab.core.thing.ThingTypeUID;
35 import org.openhab.core.types.Command;
36 import org.openhab.core.types.RefreshType;
39 * The {@link VelbusVMB7INHandler} is responsible for handling commands, which are
40 * sent to one of the channels.
42 * @author Cedric Boon - Initial contribution
45 public class VelbusVMB7INHandler extends VelbusSensorWithAlarmClockHandler {
46 public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(Arrays.asList(THING_TYPE_VMB7IN));
48 private final ChannelUID counter1Channel = new ChannelUID(thing.getUID(), "counter", "counter1");
49 private final ChannelUID counter1ChannelCurrent = new ChannelUID(thing.getUID(), "counter", "counter1Current");
50 private final ChannelUID counter2Channel = new ChannelUID(thing.getUID(), "counter", "counter2");
51 private final ChannelUID counter2ChannelCurrent = new ChannelUID(thing.getUID(), "counter", "counter2Current");
52 private final ChannelUID counter3Channel = new ChannelUID(thing.getUID(), "counter", "counter3");
53 private final ChannelUID counter3ChannelCurrent = new ChannelUID(thing.getUID(), "counter", "counter3Current");
54 private final ChannelUID counter4Channel = new ChannelUID(thing.getUID(), "counter", "counter4");
55 private final ChannelUID counter4ChannelCurrent = new ChannelUID(thing.getUID(), "counter", "counter4Current");
57 public @NonNullByDefault({}) VelbusVMB7INConfig vmb7inConfig;
59 private @Nullable ScheduledFuture<?> refreshJob;
61 public VelbusVMB7INHandler(Thing thing) {
66 public void initialize() {
67 this.vmb7inConfig = getConfigAs(VelbusVMB7INConfig.class);
71 initializeAutomaticRefresh();
74 private void initializeAutomaticRefresh() {
75 int refreshInterval = vmb7inConfig.refresh;
77 if (refreshInterval > 0) {
78 startAutomaticRefresh(refreshInterval);
83 public void dispose() {
84 final ScheduledFuture<?> refreshJob = this.refreshJob;
85 if (refreshJob != null) {
86 refreshJob.cancel(true);
90 private void startAutomaticRefresh(int refreshInterval) {
91 VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
92 if (velbusBridgeHandler == null) {
93 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
97 refreshJob = scheduler.scheduleWithFixedDelay(() -> {
98 sendCounterStatusRequest(velbusBridgeHandler, ALL_CHANNELS);
99 }, 0, refreshInterval, TimeUnit.SECONDS);
103 public void handleCommand(ChannelUID channelUID, Command command) {
104 super.handleCommand(channelUID, command);
106 VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
107 if (velbusBridgeHandler == null) {
108 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
112 if (command instanceof RefreshType) {
113 if (channelUID.equals(counter1Channel)) {
114 sendCounterStatusRequest(velbusBridgeHandler, (byte) 0x01);
115 } else if (channelUID.equals(counter2Channel)) {
116 sendCounterStatusRequest(velbusBridgeHandler, (byte) 0x02);
117 } else if (channelUID.equals(counter3Channel)) {
118 sendCounterStatusRequest(velbusBridgeHandler, (byte) 0x03);
119 } else if (channelUID.equals(counter4Channel)) {
120 sendCounterStatusRequest(velbusBridgeHandler, (byte) 0x04);
125 protected void sendCounterStatusRequest(VelbusBridgeHandler velbusBridgeHandler, byte channel) {
126 VelbusCounterStatusRequestPacket packet = new VelbusCounterStatusRequestPacket(
127 new VelbusChannelIdentifier(getModuleAddress().getAddress(), channel));
129 byte[] packetBytes = packet.getBytes();
130 velbusBridgeHandler.sendPacket(packetBytes);
134 public void onPacketReceived(byte[] packet) {
135 super.onPacketReceived(packet);
137 logger.trace("onPacketReceived() was called");
139 if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
140 byte command = packet[4];
142 if (command == COMMAND_COUNTER_STATUS && packet.length >= 6) {
143 int counterChannel = packet[5] & 0x03;
144 int pulsesPerUnit = ((packet[5] & 0x7C) / 0x04) * 0x64;
146 double counterValue = ((double) (((packet[6] & 0xff) << 24) | ((packet[7] & 0xff) << 16)
147 | ((packet[8] & 0xff) << 8) | (packet[9] & 0xff))) / pulsesPerUnit;
148 double currentValue = (1000 * 3600)
149 / (((double) (((packet[10] & 0xff) << 8) | (packet[11] & 0xff))) * pulsesPerUnit);
151 switch (counterChannel) {
153 double counter1PulseMultiplier = vmb7inConfig.counter1PulseMultiplier;
154 updateState(counter1Channel, new DecimalType(counterValue / counter1PulseMultiplier));
155 updateState(counter1ChannelCurrent, new DecimalType(currentValue / counter1PulseMultiplier));
158 double counter2PulseMultiplier = vmb7inConfig.counter2PulseMultiplier;
159 updateState(counter2Channel, new DecimalType(counterValue / counter2PulseMultiplier));
160 updateState(counter2ChannelCurrent, new DecimalType(currentValue / counter2PulseMultiplier));
163 double counter3PulseMultiplier = vmb7inConfig.counter3PulseMultiplier;
164 updateState(counter3Channel, new DecimalType(counterValue / counter3PulseMultiplier));
165 updateState(counter3ChannelCurrent, new DecimalType(currentValue / counter3PulseMultiplier));
168 double counter4PulseMultiplier = vmb7inConfig.counter4PulseMultiplier;
169 updateState(counter4Channel, new DecimalType(counterValue / counter4PulseMultiplier));
170 updateState(counter4ChannelCurrent, new DecimalType(currentValue / counter4PulseMultiplier));
173 throw new IllegalArgumentException(
174 "The given channel is not a counter channel: " + counterChannel);