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.enocean.internal.eep.A5_20;
15 import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.*;
17 import java.util.function.Function;
19 import javax.measure.quantity.Temperature;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.enocean.internal.messages.ERP1Message;
24 import org.openhab.core.config.core.Configuration;
25 import org.openhab.core.library.types.DecimalType;
26 import org.openhab.core.library.types.OnOffType;
27 import org.openhab.core.library.types.QuantityType;
28 import org.openhab.core.library.unit.SIUnits;
29 import org.openhab.core.library.unit.Units;
30 import org.openhab.core.types.Command;
31 import org.openhab.core.types.State;
32 import org.openhab.core.types.UnDefType;
35 * Heating radiator valve actuating drive with feed and room temperature measurement, local set point control and
38 * @author Dominik Vorreiter - Initial contribution
41 public class A5_20_04 extends A5_20 {
47 public A5_20_04(ERP1Message packet) {
52 protected @Nullable String convertToEventImpl(String channelId, String channelTypeId, String lastEvent,
53 Configuration config) {
55 case CHANNEL_STATUS_REQUEST_EVENT:
56 return getStatusRequestEvent();
62 private String getStatusRequestEvent() {
63 return Boolean.valueOf(getBit(getDB0Value(), 6)).toString();
64 // return getBit(getDB_0Value(), 6) ? "triggered" : null;
67 private byte getPos(Function<String, State> getCurrentStateFunc) {
68 State current = getCurrentStateFunc.apply(CHANNEL_VALVE_POSITION);
70 if (current instanceof DecimalType) {
71 DecimalType state = current.as(DecimalType.class);
74 return state.byteValue();
81 private byte getTsp(Function<String, State> getCurrentStateFunc) {
82 State current = getCurrentStateFunc.apply(CHANNEL_TEMPERATURE_SETPOINT);
84 double value = 20.0; // 20 °C
86 if (current instanceof QuantityType) {
87 @SuppressWarnings("unchecked")
88 QuantityType<Temperature> raw = current.as(QuantityType.class);
91 QuantityType<Temperature> celsius = raw.toUnit(SIUnits.CELSIUS);
93 if (celsius != null) {
94 value = celsius.doubleValue();
99 return (byte) ((value - 10.0) * (255.0 / 20.0));
102 private byte getMc(Function<String, State> getCurrentStateFunc) {
103 State current = getCurrentStateFunc.apply(CHANNEL_MEASUREMENT_CONTROL);
105 if (current instanceof OnOffType) {
106 OnOffType state = current.as(OnOffType.class);
109 return (byte) (state.equals(OnOffType.ON) ? 0x00 : 0x40);
116 private byte getWuc(Function<String, State> getCurrentStateFunc) {
117 State current = getCurrentStateFunc.apply(CHANNEL_WAKEUPCYCLE);
119 if (current instanceof DecimalType) {
120 DecimalType state = current.as(DecimalType.class);
123 return (byte) (state.byteValue() & 0x3F);
127 return 0x13; // 19 = 600 sec = 10 min
130 private byte getDso(Function<String, State> getCurrentStateFunc) {
131 State current = getCurrentStateFunc.apply(CHANNEL_DISPLAY_ORIENTATION);
133 if (current instanceof DecimalType) {
134 DecimalType state = current.as(DecimalType.class);
137 return (byte) (((state.byteValue() / 90) << 4) & 0x30);
144 private byte getBlc(Function<String, State> getCurrentStateFunc) {
145 State current = getCurrentStateFunc.apply(CHANNEL_BUTTON_LOCK);
147 if (current instanceof OnOffType) {
148 OnOffType state = current.as(OnOffType.class);
151 return (byte) (state.equals(OnOffType.ON) ? 0x04 : 0x00);
155 return 0x00; // unlocked
158 private byte getSer(Function<String, State> getCurrentStateFunc) {
159 State current = getCurrentStateFunc.apply(CHANNEL_SERVICECOMMAND);
161 if (current instanceof DecimalType) {
162 DecimalType state = current.as(DecimalType.class);
165 return (byte) (state.byteValue() & 0x03);
169 return 0x00; // 0 = no change
173 protected void convertFromCommandImpl(String channelId, String channelTypeId, Command command,
174 Function<String, State> getCurrentStateFunc, @Nullable Configuration config) {
175 if (VIRTUALCHANNEL_SEND_COMMAND.equals(channelId)) {
176 byte db3 = getPos(getCurrentStateFunc);
177 byte db2 = getTsp(getCurrentStateFunc);
178 byte db1 = (byte) (0x00 | getMc(getCurrentStateFunc) | getWuc(getCurrentStateFunc));
179 byte db0 = (byte) (0x00 | getDso(getCurrentStateFunc) | TEACHIN_BIT | getBlc(getCurrentStateFunc)
180 | getSer(getCurrentStateFunc));
182 setData(db3, db2, db1, db0);
189 protected State convertToStateImpl(String channelId, String channelTypeId,
190 Function<String, @Nullable State> getCurrentStateFunc, Configuration config) {
192 case CHANNEL_VALVE_POSITION:
193 return getValvePosition();
194 case CHANNEL_BUTTON_LOCK:
195 return getButtonLock();
196 case CHANNEL_TEMPERATURE_SETPOINT:
197 return getTemperatureSetpoint();
198 case CHANNEL_TEMPERATURE:
199 return getTemperature();
200 case CHANNEL_FEED_TEMPERATURE:
201 return getFeedTemperature();
202 case CHANNEL_MEASUREMENT_CONTROL:
203 return getMeasurementControl();
204 case CHANNEL_FAILURE_CODE:
205 return getFailureCode();
208 return UnDefType.UNDEF;
211 private State getTemperature() {
212 boolean fl = getBit(getDB0Value(), 0);
213 boolean mst = getBit(getDB0Value(), 7);
216 return UnDefType.UNDEF;
219 double value = getDB1Value() * (20.0 / 255.0) + 10.0;
221 return new QuantityType<>(value, SIUnits.CELSIUS);
224 private State getFailureCode() {
225 boolean fl = getBit(getDB0Value(), 0);
228 return new QuantityType<>(-1, Units.ONE);
231 return new QuantityType<>(getDB1Value(), Units.ONE);
234 private State getMeasurementControl() {
235 return getBit(getDB0Value(), 7) ? OnOffType.OFF : OnOffType.ON;
238 private State getFeedTemperature() {
239 boolean ts = getBit(getDB0Value(), 1);
240 boolean mst = getBit(getDB0Value(), 7);
243 return UnDefType.UNDEF;
246 double value = getDB2Value() * (60.0 / 255.0) + 20.0;
248 return new QuantityType<>(value, SIUnits.CELSIUS);
251 private State getTemperatureSetpoint() {
252 boolean ts = getBit(getDB0Value(), 1);
255 return UnDefType.UNDEF;
258 double value = getDB2Value() * (20.0 / 255.0) + 10.0;
260 return new QuantityType<>(value, SIUnits.CELSIUS);
263 private State getButtonLock() {
264 return getBit(getDB0Value(), 2) ? OnOffType.ON : OnOffType.OFF;
267 private State getValvePosition() {
268 return new QuantityType<>(getDB3Value(), Units.PERCENT);