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.COMMAND_SENSOR_TEMPERATURE;
17 import java.util.concurrent.ScheduledFuture;
18 import java.util.concurrent.TimeUnit;
20 import javax.measure.quantity.Temperature;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.binding.velbus.internal.config.VelbusSensorConfig;
25 import org.openhab.binding.velbus.internal.packets.VelbusPacket;
26 import org.openhab.binding.velbus.internal.packets.VelbusSensorTemperatureRequestPacket;
27 import org.openhab.core.library.types.QuantityType;
28 import org.openhab.core.library.unit.SIUnits;
29 import org.openhab.core.thing.ChannelUID;
30 import org.openhab.core.thing.Thing;
31 import org.openhab.core.thing.ThingStatus;
32 import org.openhab.core.thing.ThingStatusDetail;
33 import org.openhab.core.types.Command;
34 import org.openhab.core.types.RefreshType;
37 * The {@link VelbusTemperatureSensorHandler} is responsible for handling commands, which are
38 * sent to one of the channels.
40 * @author Cedric Boon - Initial contribution
43 public abstract class VelbusTemperatureSensorHandler extends VelbusSensorWithAlarmClockHandler {
44 private @Nullable ScheduledFuture<?> refreshJob;
45 private @NonNullByDefault({}) VelbusSensorConfig sensorConfig;
46 private ChannelUID temperatureChannel;
48 public VelbusTemperatureSensorHandler(Thing thing, int numberOfSubAddresses, ChannelUID temperatureChannel) {
49 super(thing, numberOfSubAddresses);
51 this.temperatureChannel = temperatureChannel;
55 public void initialize() {
56 this.sensorConfig = getConfigAs(VelbusSensorConfig.class);
60 initializeAutomaticRefresh();
63 private void initializeAutomaticRefresh() {
64 int refreshInterval = this.sensorConfig.refresh;
66 if (refreshInterval > 0) {
67 startAutomaticRefresh(refreshInterval);
72 public void dispose() {
73 final ScheduledFuture<?> refreshJob = this.refreshJob;
74 if (refreshJob != null) {
75 refreshJob.cancel(true);
79 private void startAutomaticRefresh(int refreshInterval) {
80 VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
81 if (velbusBridgeHandler == null) {
82 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
86 refreshJob = scheduler.scheduleWithFixedDelay(() -> {
87 sendSensorReadoutRequest(velbusBridgeHandler);
88 }, 0, refreshInterval, TimeUnit.SECONDS);
92 public void handleCommand(ChannelUID channelUID, Command command) {
93 super.handleCommand(channelUID, command);
95 VelbusBridgeHandler velbusBridgeHandler = getVelbusBridgeHandler();
96 if (velbusBridgeHandler == null) {
97 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
101 if (command instanceof RefreshType) {
102 if (channelUID.equals(temperatureChannel)) {
103 sendSensorReadoutRequest(velbusBridgeHandler);
108 protected void sendSensorReadoutRequest(VelbusBridgeHandler velbusBridgeHandler) {
109 VelbusSensorTemperatureRequestPacket packet = new VelbusSensorTemperatureRequestPacket(
110 getModuleAddress().getAddress());
112 byte[] packetBytes = packet.getBytes();
113 velbusBridgeHandler.sendPacket(packetBytes);
117 public void onPacketReceived(byte[] packet) {
118 super.onPacketReceived(packet);
120 logger.trace("onPacketReceived() was called");
122 if (packet[0] == VelbusPacket.STX && packet.length >= 5) {
123 byte command = packet[4];
125 if (command == COMMAND_SENSOR_TEMPERATURE && packet.length >= 6) {
126 byte highByteCurrentSensorTemperature = packet[5];
127 byte lowByteCurrentSensorTemperature = packet[6];
129 boolean negative = (highByteCurrentSensorTemperature & 0x80) == 0x80;
130 double temperature = ((((highByteCurrentSensorTemperature & 0x7f) << 3)
131 + ((lowByteCurrentSensorTemperature & 0xff) >> 5)) - (negative ? 0x400 : 0)) * 0.0625;
132 QuantityType<Temperature> state = new QuantityType<>(temperature, SIUnits.CELSIUS);
133 updateState(temperatureChannel, state);