]> git.basschouten.com Git - openhab-addons.git/blob
ff170087b858d1d5b6946ced46b1a2df0289c4cc
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.velbus.internal.handler;
14
15 import static org.openhab.binding.velbus.internal.VelbusBindingConstants.*;
16
17 import java.util.Arrays;
18 import java.util.HashSet;
19 import java.util.Set;
20 import java.util.concurrent.ScheduledFuture;
21 import java.util.concurrent.TimeUnit;
22
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;
37
38 /**
39  * The {@link VelbusVMB7INHandler} is responsible for handling commands, which are
40  * sent to one of the channels.
41  *
42  * @author Cedric Boon - Initial contribution
43  */
44 @NonNullByDefault
45 public class VelbusVMB7INHandler extends VelbusSensorWithAlarmClockHandler {
46     public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(Arrays.asList(THING_TYPE_VMB7IN));
47
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");
56
57     public @NonNullByDefault({}) VelbusVMB7INConfig vmb7inConfig;
58
59     private @Nullable ScheduledFuture<?> refreshJob;
60
61     public VelbusVMB7INHandler(Thing thing) {
62         super(thing, 0);
63     }
64
65     @Override
66     public void initialize() {
67         this.vmb7inConfig = getConfigAs(VelbusVMB7INConfig.class);
68
69         super.initialize();
70
71         initializeAutomaticRefresh();
72     }
73
74     private void initializeAutomaticRefresh() {
75         int refreshInterval = vmb7inConfig.refresh;
76
77         if (refreshInterval > 0) {
78             startAutomaticRefresh(refreshInterval);
79         }
80     }
81
82     @Override
83     public void dispose() {
84         final ScheduledFuture<?> refreshJob = this.refreshJob;
85         if (refreshJob != null) {
86             refreshJob.cancel(true);
87         }
88     }
89
90     private void startAutomaticRefresh(int refreshInterval) {
91         VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
92         if (velbusBridgeHandler == null) {
93             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
94             return;
95         }
96
97         refreshJob = scheduler.scheduleWithFixedDelay(() -> {
98             sendCounterStatusRequest(velbusBridgeHandler, ALL_CHANNELS);
99         }, 0, refreshInterval, TimeUnit.SECONDS);
100     }
101
102     @Override
103     public void handleCommand(ChannelUID channelUID, Command command) {
104         super.handleCommand(channelUID, command);
105
106         VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
107         if (velbusBridgeHandler == null) {
108             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
109             return;
110         }
111
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);
121             }
122         }
123     }
124
125     protected void sendCounterStatusRequest(VelbusBridgeHandler velbusBridgeHandler, byte channel) {
126         VelbusCounterStatusRequestPacket packet = new VelbusCounterStatusRequestPacket(
127                 new VelbusChannelIdentifier(getModuleAddress().getAddress(), channel));
128
129         byte[] packetBytes = packet.getBytes();
130         velbusBridgeHandler.sendPacket(packetBytes);
131     }
132
133     @Override
134     public void onPacketReceived(byte[] packet) {
135         super.onPacketReceived(packet);
136
137         logger.trace("onPacketReceived() was called");
138
139         if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
140             byte command = packet[4];
141
142             if (command == COMMAND_COUNTER_STATUS && packet.length >= 6) {
143                 int counterChannel = packet[5] & 0x03;
144                 int pulsesPerUnit = ((packet[5] & 0x7C) / 0x04) * 0x64;
145
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);
150
151                 switch (counterChannel) {
152                     case 0x00:
153                         double counter1PulseMultiplier = vmb7inConfig.counter1PulseMultiplier;
154                         updateState(counter1Channel, new DecimalType(counterValue / counter1PulseMultiplier));
155                         updateState(counter1ChannelCurrent, new DecimalType(currentValue / counter1PulseMultiplier));
156                         break;
157                     case 0x01:
158                         double counter2PulseMultiplier = vmb7inConfig.counter2PulseMultiplier;
159                         updateState(counter2Channel, new DecimalType(counterValue / counter2PulseMultiplier));
160                         updateState(counter2ChannelCurrent, new DecimalType(currentValue / counter2PulseMultiplier));
161                         break;
162                     case 0x02:
163                         double counter3PulseMultiplier = vmb7inConfig.counter3PulseMultiplier;
164                         updateState(counter3Channel, new DecimalType(counterValue / counter3PulseMultiplier));
165                         updateState(counter3ChannelCurrent, new DecimalType(currentValue / counter3PulseMultiplier));
166                         break;
167                     case 0x03:
168                         double counter4PulseMultiplier = vmb7inConfig.counter4PulseMultiplier;
169                         updateState(counter4Channel, new DecimalType(counterValue / counter4PulseMultiplier));
170                         updateState(counter4ChannelCurrent, new DecimalType(currentValue / counter4PulseMultiplier));
171                         break;
172                     default:
173                         throw new IllegalArgumentException(
174                                 "The given channel is not a counter channel: " + counterChannel);
175                 }
176             }
177         }
178     }
179 }