]> git.basschouten.com Git - openhab-addons.git/blob
b94cece7fa8383c4f15e8a988d4f74176c3cb312
[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.D2_50;
14
15 import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.*;
16
17 import java.util.function.Function;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.enocean.internal.Helper;
22 import org.openhab.binding.enocean.internal.eep.Base._VLDMessage;
23 import org.openhab.binding.enocean.internal.messages.ERP1Message;
24 import org.openhab.core.config.core.Configuration;
25 import org.openhab.core.config.discovery.DiscoveryResultBuilder;
26 import org.openhab.core.library.types.DecimalType;
27 import org.openhab.core.library.types.OnOffType;
28 import org.openhab.core.library.types.OpenClosedType;
29 import org.openhab.core.library.types.QuantityType;
30 import org.openhab.core.library.types.StringType;
31 import org.openhab.core.library.unit.SIUnits;
32 import org.openhab.core.library.unit.Units;
33 import org.openhab.core.types.Command;
34 import org.openhab.core.types.RefreshType;
35 import org.openhab.core.types.State;
36 import org.openhab.core.types.UnDefType;
37
38 /**
39  *
40  * @author Daniel Weber - Initial contribution
41  */
42 @NonNullByDefault
43 public class D2_50 extends _VLDMessage {
44
45     protected static final byte MT_MASK = (byte) 0xf0;
46     protected static final byte MT_REMOTE_TRANSMISSION_REQUEST = 0x00;
47     protected static final byte MT_CONTROL = 0x20;
48     protected static final byte MT_BASIC_STATUS = 0x40;
49     protected static final byte MT_EXTENDED_STATUS = 0x60; // not yet implemented
50     protected static final byte MT_UNKNOWN_STATUS = (byte) 0x80; // Sent by some systems during teach in
51
52     protected static final byte RMT_MASK = (byte) 0x0f;
53     protected static final byte RMT_BASIC_STATUS = 0x00;
54     protected static final byte RMT_EXTENDED_STATUS = 0x01; // not yet implemented
55
56     protected static final byte DOMC_NOACTION = 0x0f;
57     protected static final byte CONTROL_NOACTION = 0;
58     protected static final byte TMOC_NOACTION = 127;
59     protected static final byte TMOC_ACTIVATE = (byte) 0xff;
60     protected static final byte THRESHOLD_NOACTION = 127;
61
62     public D2_50() {
63         super();
64     }
65
66     public D2_50(ERP1Message packet) {
67         super(packet);
68     }
69
70     protected byte getMessageType(byte b) {
71         return (byte) (b & MT_MASK);
72     }
73
74     @Override
75     public void addConfigPropertiesTo(DiscoveryResultBuilder discoveredThingResultBuilder) {
76         discoveredThingResultBuilder.withProperty(PARAMETER_SENDINGEEPID, getEEPType().getId())
77                 .withProperty(PARAMETER_RECEIVINGEEPID, getEEPType().getId());
78     }
79
80     @Override
81     protected void convertFromCommandImpl(String channelId, String channelTypeId, Command command,
82             Function<String, State> getCurrentStateFunc, @Nullable Configuration config) {
83         // we need to send just a single message to refresh all channel states, hence just send refresh for OM
84         if (command == RefreshType.REFRESH && CHANNEL_VENTILATIONOPERATIONMODE.equals(channelId)) {
85             setData((byte) (MT_REMOTE_TRANSMISSION_REQUEST + RMT_BASIC_STATUS));
86         } else {
87             switch (channelId) {
88                 case CHANNEL_VENTILATIONOPERATIONMODE:
89                     if (command instanceof StringType stringCommand) {
90                         byte value = (byte) (Helper.tryParseInt(stringCommand.toString(), 15) & 0x0f);
91                         setData((byte) (MT_CONTROL + value), CONTROL_NOACTION, TMOC_NOACTION, THRESHOLD_NOACTION,
92                                 THRESHOLD_NOACTION, CONTROL_NOACTION);
93                     }
94                     break;
95                 case CHANNEL_TIMEROPERATIONMODE:
96                     if (command instanceof OnOffType onOffCommand) {
97                         byte value = onOffCommand == OnOffType.ON ? TMOC_ACTIVATE : TMOC_NOACTION;
98                         setData((byte) (MT_CONTROL + DOMC_NOACTION), CONTROL_NOACTION, value, THRESHOLD_NOACTION,
99                                 THRESHOLD_NOACTION, CONTROL_NOACTION);
100                     }
101                     break;
102             }
103         }
104     }
105
106     @Override
107     protected State convertToStateImpl(String channelId, String channelTypeId,
108             Function<String, State> getCurrentStateFunc, Configuration config) {
109         if (getMessageType(bytes[0]) != MT_BASIC_STATUS) {
110             return UnDefType.UNDEF;
111         }
112
113         switch (channelId) {
114             case CHANNEL_VENTILATIONOPERATIONMODE:
115                 return new StringType(String.valueOf(bytes[0] & 0x0f));
116             case CHANNEL_FIREPLACESAFETYMODE:
117                 return OnOffType.from(getBit(bytes[1], 3));
118             case CHANNEL_HEATEXCHANGERBYPASSSTATUS:
119                 return getBit(bytes[1], 2) ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
120             case CHANNEL_SUPPLYAIRFLAPSTATUS:
121                 return getBit(bytes[1], 1) ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
122             case CHANNEL_EXHAUSTAIRFLAPSTATUS:
123                 return getBit(bytes[1], 0) ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
124             case CHANNEL_DEFROSTMODE:
125                 return OnOffType.from(getBit(bytes[2], 7));
126             case CHANNEL_COOLINGPROTECTIONMODE:
127                 return OnOffType.from(getBit(bytes[2], 6));
128             case CHANNEL_OUTDOORAIRHEATERSTATUS:
129                 return OnOffType.from(getBit(bytes[2], 5));
130             case CHANNEL_SUPPLYAIRHEATERSTATUS:
131                 return OnOffType.from(getBit(bytes[2], 4));
132             case CHANNEL_DRAINHEATERSTATUS:
133                 return OnOffType.from(getBit(bytes[2], 3));
134             case CHANNEL_TIMEROPERATIONMODE:
135                 return OnOffType.from(getBit(bytes[2], 2));
136             case CHANNEL_MAINTENANCESTATUS:
137                 return OnOffType.from(getBit(bytes[2], 1));
138             case CHANNEL_WEEKLYTIMERPROGRAMSTATUS:
139                 return OnOffType.from(getBit(bytes[2], 0));
140             case CHANNEL_ROOMTEMPERATURECONTROLSTATUS:
141                 return OnOffType.from(getBit(bytes[3], 7));
142             case CHANNEL_AIRQUALITYVALUE1:
143                 return new QuantityType<>((bytes[3] & 0x7f), Units.PERCENT);
144             case CHANNEL_AIRQUALITYVALUE2:
145                 return new QuantityType<>((bytes[4] & 0x7f), Units.PERCENT);
146             case CHANNEL_OUTDOORAIRTEMPERATURE:
147                 return new QuantityType<>(-63 + (bytes[5] >>> 1), SIUnits.CELSIUS);
148             case CHANNEL_SUPPLYAIRTEMPERATURE:
149                 return new QuantityType<>(-63 + (bytes[6] >>> 2) + ((bytes[5] & 1) << 6), SIUnits.CELSIUS);
150             case CHANNEL_INDOORAIRTEMPERATURE:
151                 return new QuantityType<>(-63 + (bytes[7] >>> 3) + ((bytes[6] & 0b11) << 5), SIUnits.CELSIUS);
152             case CHANNEL_EXHAUSTAIRTEMPERATURE:
153                 return new QuantityType<>(-63 + (bytes[8] >>> 4) + ((bytes[7] & 0b111) << 4), SIUnits.CELSIUS);
154             case CHANNEL_SUPPLYAIRFANAIRFLOWRATE:
155                 return new QuantityType<>((bytes[9] >>> 2) + ((bytes[8] & 0b1111) << 6), Units.CUBICMETRE_PER_MINUTE);
156             case CHANNEL_EXHAUSTAIRFANAIRFLOWRATE:
157                 return new QuantityType<>((bytes[10] & 0xff) + ((bytes[9] & 0b11) << 8), Units.CUBICMETRE_PER_MINUTE);
158             case CHANNEL_SUPPLYFANSPEED:
159                 return new DecimalType((bytes[12] >>> 4) + (bytes[11] << 4));
160             case CHANNEL_EXHAUSTFANSPEED:
161                 return new DecimalType((bytes[13] & 0xff) + ((bytes[12] & 0b1111) << 8));
162         }
163
164         return UnDefType.UNDEF;
165     }
166
167     @Override
168     protected boolean validateData(byte[] bytes) {
169         if (bytes.length == 0) {
170             return false;
171         }
172
173         switch (getMessageType(bytes[0])) {
174             case MT_REMOTE_TRANSMISSION_REQUEST:
175                 return bytes.length == 1;
176             case MT_CONTROL:
177                 return bytes.length == 6;
178             case MT_BASIC_STATUS:
179                 return bytes.length == 14;
180             case MT_EXTENDED_STATUS: // MT_EXTENDED_STATUS is not yet supported, however return true to avoid Exceptions
181                 return true;
182             case MT_UNKNOWN_STATUS:
183                 return true;
184             default:
185                 logger.error("Invalid data, unknown message type: {} ({})", getMessageType(bytes[0]), bytes);
186                 return false;
187         }
188     }
189 }