]> git.basschouten.com Git - openhab-addons.git/blob
78704471728a2400c9f6cb63599d7b7038bf3311
[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.enocean.internal.eep.A5_20;
14
15 import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.*;
16
17 import java.util.function.Function;
18
19 import javax.measure.quantity.Temperature;
20
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;
33
34 /**
35  * Heating radiator valve actuating drive with feed and room temperature measurement, local set point control and
36  * display
37  *
38  * @author Dominik Vorreiter - Initial contribution
39  */
40 @NonNullByDefault
41 public class A5_20_04 extends A5_20 {
42
43     public A5_20_04() {
44         super();
45     }
46
47     public A5_20_04(ERP1Message packet) {
48         super(packet);
49     }
50
51     @Override
52     protected @Nullable String convertToEventImpl(String channelId, String channelTypeId, @Nullable String lastEvent,
53             Configuration config) {
54         switch (channelId) {
55             case CHANNEL_STATUS_REQUEST_EVENT:
56                 return getStatusRequestEvent();
57         }
58
59         return null;
60     }
61
62     private String getStatusRequestEvent() {
63         return Boolean.toString(getBit(getDB0Value(), 6));
64         // return getBit(getDB_0Value(), 6) ? "triggered" : null;
65     }
66
67     private byte getPos(Function<String, State> getCurrentStateFunc) {
68         State current = getCurrentStateFunc.apply(CHANNEL_VALVE_POSITION);
69
70         if (current instanceof DecimalType) {
71             DecimalType state = current.as(DecimalType.class);
72
73             if (state != null) {
74                 return state.byteValue();
75             }
76         }
77
78         return 25; // 25 %
79     }
80
81     private byte getTsp(Function<String, State> getCurrentStateFunc) {
82         State current = getCurrentStateFunc.apply(CHANNEL_TEMPERATURE_SETPOINT);
83
84         double value = 20.0; // 20 °C
85
86         if (current instanceof QuantityType) {
87             @SuppressWarnings("unchecked")
88             QuantityType<Temperature> raw = current.as(QuantityType.class);
89
90             if (raw != null) {
91                 QuantityType<Temperature> celsius = raw.toUnit(SIUnits.CELSIUS);
92
93                 if (celsius != null) {
94                     value = celsius.doubleValue();
95                 }
96             }
97         }
98
99         return (byte) ((value - 10.0) * (255.0 / 20.0));
100     }
101
102     private byte getMc(Function<String, State> getCurrentStateFunc) {
103         State current = getCurrentStateFunc.apply(CHANNEL_MEASUREMENT_CONTROL);
104
105         if (current instanceof OnOffType) {
106             OnOffType state = current.as(OnOffType.class);
107
108             if (state != null) {
109                 return (byte) (state.equals(OnOffType.ON) ? 0x00 : 0x40);
110             }
111         }
112
113         return 0x00; // on
114     }
115
116     private byte getWuc(Function<String, State> getCurrentStateFunc) {
117         State current = getCurrentStateFunc.apply(CHANNEL_WAKEUPCYCLE);
118
119         if (current instanceof DecimalType) {
120             DecimalType state = current.as(DecimalType.class);
121
122             if (state != null) {
123                 return (byte) (state.byteValue() & 0x3F);
124             }
125         }
126
127         return 0x13; // 19 = 600 sec = 10 min
128     }
129
130     private byte getDso(Function<String, State> getCurrentStateFunc) {
131         State current = getCurrentStateFunc.apply(CHANNEL_DISPLAY_ORIENTATION);
132
133         if (current instanceof DecimalType) {
134             DecimalType state = current.as(DecimalType.class);
135
136             if (state != null) {
137                 return (byte) (((state.byteValue() / 90) << 4) & 0x30);
138             }
139         }
140
141         return 0x00; // 0°
142     }
143
144     private byte getBlc(Function<String, State> getCurrentStateFunc) {
145         State current = getCurrentStateFunc.apply(CHANNEL_BUTTON_LOCK);
146
147         if (current instanceof OnOffType) {
148             OnOffType state = current.as(OnOffType.class);
149
150             if (state != null) {
151                 return (byte) (state.equals(OnOffType.ON) ? 0x04 : 0x00);
152             }
153         }
154
155         return 0x00; // unlocked
156     }
157
158     private byte getSer(Function<String, State> getCurrentStateFunc) {
159         State current = getCurrentStateFunc.apply(CHANNEL_SERVICECOMMAND);
160
161         if (current instanceof DecimalType) {
162             DecimalType state = current.as(DecimalType.class);
163
164             if (state != null) {
165                 return (byte) (state.byteValue() & 0x03);
166             }
167         }
168
169         return 0x00; // 0 = no change
170     }
171
172     @Override
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));
181
182             setData(db3, db2, db1, db0);
183
184             return;
185         }
186     }
187
188     @Override
189     protected State convertToStateImpl(String channelId, String channelTypeId,
190             Function<String, @Nullable State> getCurrentStateFunc, Configuration config) {
191         switch (channelId) {
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();
206         }
207
208         return UnDefType.UNDEF;
209     }
210
211     private State getTemperature() {
212         boolean fl = getBit(getDB0Value(), 0);
213         boolean mst = getBit(getDB0Value(), 7);
214
215         if (fl || mst) {
216             return UnDefType.UNDEF;
217         }
218
219         double value = getDB1Value() * (20.0 / 255.0) + 10.0;
220
221         return new QuantityType<>(value, SIUnits.CELSIUS);
222     }
223
224     private State getFailureCode() {
225         boolean fl = getBit(getDB0Value(), 0);
226
227         if (!fl) {
228             return new QuantityType<>(-1, Units.ONE);
229         }
230
231         return new QuantityType<>(getDB1Value(), Units.ONE);
232     }
233
234     private State getMeasurementControl() {
235         return OnOffType.from(!getBit(getDB0Value(), 7));
236     }
237
238     private State getFeedTemperature() {
239         boolean ts = getBit(getDB0Value(), 1);
240         boolean mst = getBit(getDB0Value(), 7);
241
242         if (ts || mst) {
243             return UnDefType.UNDEF;
244         }
245
246         double value = getDB2Value() * (60.0 / 255.0) + 20.0;
247
248         return new QuantityType<>(value, SIUnits.CELSIUS);
249     }
250
251     private State getTemperatureSetpoint() {
252         boolean ts = getBit(getDB0Value(), 1);
253
254         if (!ts) {
255             return UnDefType.UNDEF;
256         }
257
258         double value = getDB2Value() * (20.0 / 255.0) + 10.0;
259
260         return new QuantityType<>(value, SIUnits.CELSIUS);
261     }
262
263     private State getButtonLock() {
264         return OnOffType.from(getBit(getDB0Value(), 2));
265     }
266
267     private State getValvePosition() {
268         return new QuantityType<>(getDB3Value(), Units.PERCENT);
269     }
270 }