2 * Copyright (c) 2010-2021 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.rfxcom.internal.messages;
15 import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
17 import java.nio.ByteBuffer;
18 import java.nio.charset.StandardCharsets;
20 import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
21 import org.openhab.core.types.Type;
24 * RFXCOM data class for interface message.
26 * @author Pauli Anttila - Initial contribution
27 * @author Ivan Martinez - Older firmware support (OH1)
29 public class RFXComInterfaceMessage extends RFXComBaseMessage {
31 public enum SubType implements ByteEnumWrapper {
34 UNKNOWN_RTS_REMOTE(1),
35 NO_EXTENDED_HW_PRESENT(2),
40 private final int subType;
42 SubType(int subType) {
43 this.subType = subType;
47 public byte toByte() {
48 return (byte) subType;
52 public enum Commands implements ByteEnumWrapper {
53 RESET(0), // Reset the receiver/transceiver. No answer is transmitted!
54 GET_STATUS(2), // Get Status, return firmware versions and configuration of the interface
55 SET_MODE(3), // Set mode msg1-msg5, return firmware versions and configuration of the interface
56 ENABLE_ALL(4), // Enable all receiving modes of the receiver/transceiver
57 ENABLE_UNDECODED_PACKETS(5), // Enable reporting of undecoded packets
58 SAVE_RECEIVING_MODES(6), // Save receiving modes of the receiver/transceiver in non-volatile memory
59 START_RECEIVER(7), // Start RFXtrx receiver
60 T1(8), // For internal use by RFXCOM
61 T2(9), // For internal use by RFXCOM
63 UNSUPPORTED_COMMAND(-1); // wrong command received from the application
65 private final int command;
67 Commands(int command) {
68 this.command = command;
72 public byte toByte() {
73 return (byte) command;
77 public enum TransceiverType implements ByteEnumWrapper {
78 _310MHZ(0x50, "RFXtrx315 operating at 310MHz"),
79 _315MHZ(0x51, "RFXtrx315 operating at 315MHz"),
80 _433_92MHZ_RECEIVER_ONLY(0x52, "RFXrec433 operating at 433.92MHz (receiver only)"),
81 _433_92MHZ_TRANSCEIVER(0x53, "RFXtrx433 operating at 433.92MHz"),
82 _433_42MHZ(0x54, "RFXtrx433 operating at 433.42MHz"),
83 _868_00MHZ(0x55, "RFXtrx868X operating at 868MHz"),
84 _868_00MHZ_FSK(0x56, "RFXtrx868X operating at 868.00MHz FSK"),
85 _868_30MHZ(0x57, "RFXtrx868X operating at 868.30MHz"),
86 _868_30MHZ_FSK(0x58, "RFXtrx868X operating at 868.30MHz FSK"),
87 _868_35MHZ(0x59, "RFXtrx868X operating at 868.35MHz"),
88 _868_35MHZ_FSK(0x5A, "RFXtrx868X operating at 868.35MHz FSK"),
89 _868_95MHZ_FSK(0x5B, "RFXtrx868X operating at 868.95MHz"),
90 _433_92MHZ_IOT(0x5C, "RFXtrxIOT operating at 433.92MHz"),
91 _868_00MHZ_IOT(0x5D, "RFXtrxIOT operating at 868MHz"),
92 _434_50MHZ(0x5F, "RFXtrx433 operating at 434.50MHz");
94 private final int type;
95 private final String name;
97 TransceiverType(int type, String name) {
103 public byte toByte() {
108 public String toString() {
113 public enum FirmwareType implements ByteEnumWrapper {
114 TYPE1_RX_ONLY(0x00, "Type1 RFXrec receive only firmware"),
115 TYPE1(0x01, "Type1"),
116 TYPE2(0x02, "Type2"),
121 PROXL1(0x10, "ProXL 1");
123 private final int type;
124 private final String name;
126 FirmwareType(int type, String name) {
132 public byte toByte() {
137 public String toString() {
142 public SubType subType;
143 public Commands command;
144 public String text = "";
146 public TransceiverType transceiverType;
147 public int firmwareVersion;
149 public boolean enableUndecodedPackets; // 0x80 - Undecoded packets
150 public boolean enableImagintronixOpusPackets; // 0x40 - Imagintronix/Opus (433.92)
151 public boolean enableByronSXPackets; // 0x20 - Byron SX (433.92)
152 public boolean enableRSLPackets; // 0x10 - RSL (433.92)
153 public boolean enableLighting4Packets; // 0x08 - Lighting4 (433.92)
154 public boolean enableFineOffsetPackets; // 0x04 - FineOffset / Viking (433.92)
155 public boolean enableRubicsonPackets; // 0x02 - Rubicson (433.92)
156 public boolean enableAEPackets; // 0x01 - AE (433.92)
158 public boolean enableBlindsT1T2T3T4Packets; // 0x80 - BlindsT1/T2/T3/T4 (433.92)
159 public boolean enableBlindsT0Packets; // 0x40 - BlindsT0 (433.92)
160 public boolean enableProGuardPackets; // 0x20 - ProGuard (868.35 FSK)
161 public boolean enableFS20Packets; // 0x10 - FS20 (868.35)
162 public boolean enableLaCrossePackets; // 0x08 - La Crosse (433.92/868.30)
163 public boolean enableHidekiUPMPackets; // 0x04 - Hideki/UPM (433.92)
164 public boolean enableADPackets; // 0x02 - AD LightwaveRF (433.92)
165 public boolean enableMertikPackets; // 0x01 - Mertik (433.92)
167 public boolean enableVisonicPackets; // 0x80 - Visonic (315/868.95)
168 public boolean enableATIPackets; // 0x40 - ATI (433.92)
169 public boolean enableOregonPackets; // 0x20 - Oregon Scientific (433.92)
170 public boolean enableMeiantechPackets; // 0x10 - Meiantech (433.92)
171 public boolean enableHomeEasyPackets; // 0x08 - HomeEasy EU (433.92)
172 public boolean enableACPackets; // 0x04 - AC (433.92)
173 public boolean enableARCPackets; // 0x02 - ARC (433.92)
174 public boolean enableX10Packets; // 0x01 - X10 (310/433.92)
176 public boolean enableHomeConfortPackets; // 0x02 - HomeConfort (433.92)
177 public boolean enableKEELOQPackets; // 0x01 - KEELOQ (433.92)
179 public byte hardwareVersion1;
180 public byte hardwareVersion2;
182 public int outputPower; // -18dBm to +13dBm. N.B. maximum allowed is +10dBm
184 public FirmwareType firmwareType;
186 public RFXComInterfaceMessage(byte[] data) throws RFXComException {
191 public String toString() {
194 str += super.toString();
195 str += ", Sub type = " + subType;
196 str += ", Command = " + command;
198 if (subType == SubType.RESPONSE) {
199 str += ", Transceiver type = " + transceiverType;
200 str += ", Hardware version = " + hardwareVersion1 + "." + hardwareVersion2;
201 str += ", Firmware type = " + (firmwareType != null ? firmwareType : "unknown");
202 str += ", Firmware version = " + firmwareVersion;
203 str += ", Output power = " + outputPower + "dBm";
204 str += ", Undecoded packets = " + enableUndecodedPackets;
205 str += ", RFU6 packets = " + enableImagintronixOpusPackets;
206 str += ", Byron SX packets packets (433.92) = " + enableByronSXPackets;
207 str += ", RSL packets packets (433.92) = " + enableRSLPackets;
208 str += ", Lighting4 packets (433.92) = " + enableLighting4Packets;
209 str += ", FineOffset / Viking (433.92) packets = " + enableFineOffsetPackets;
210 str += ", Rubicson (433.92) packets = " + enableRubicsonPackets;
211 str += ", AE (433.92) packets = " + enableAEPackets;
213 str += ", BlindsT1/T2/T3 (433.92) packets = " + enableBlindsT1T2T3T4Packets;
214 str += ", BlindsT0 (433.92) packets = " + enableBlindsT0Packets;
215 str += ", ProGuard (868.35 FSK) packets = " + enableProGuardPackets;
216 str += ", FS20/Legrand CAD (868.35/433.92) packets = " + enableFS20Packets;
217 str += ", La Crosse (433.92/868.30) packets = " + enableLaCrossePackets;
218 str += ", Hideki/UPM (433.92) packets = " + enableHidekiUPMPackets;
219 str += ", AD LightwaveRF (433.92) packets = " + enableADPackets;
220 str += ", Mertik (433.92) packets = " + enableMertikPackets;
222 str += ", Visonic (315/868.95) packets = " + enableVisonicPackets;
223 str += ", ATI (433.92) packets = " + enableATIPackets;
224 str += ", Oregon Scientific (433.92) packets = " + enableOregonPackets;
225 str += ", Meiantech (433.92) packets = " + enableMeiantechPackets;
226 str += ", HomeEasy EU (433.92) packets = " + enableHomeEasyPackets;
227 str += ", AC (433.92) packets = " + enableACPackets;
228 str += ", ARC (433.92) packets = " + enableARCPackets;
229 str += ", X10 (310/433.92) packets = " + enableX10Packets;
231 str += ", HomeConfort (433.92) packets = " + enableHomeConfortPackets;
232 str += ", KEELOQ (433.92/868.95) packets = " + enableKEELOQPackets;
233 } else if (subType == SubType.START_RECEIVER) {
234 str += ", Text = " + text;
241 public void encodeMessage(byte[] data) throws RFXComException {
242 super.encodeMessage(data);
244 subType = fromByte(SubType.class, super.subType);
246 if (subType == SubType.RESPONSE) {
247 encodeResponseMessage(data);
248 } else if (subType == SubType.START_RECEIVER) {
249 encodeStartReceiverMessage(data);
251 // We don't handle the other subTypes but to avoid null pointer
252 // exceptions we set command to something. It doesn't really
253 // matter what but it may be printed in log messages so...
254 command = Commands.UNSUPPORTED_COMMAND;
258 private void encodeResponseMessage(byte[] data) throws RFXComException {
259 command = fromByte(Commands.class, data[4]);
260 transceiverType = fromByte(TransceiverType.class, data[5]);
262 hardwareVersion1 = data[11];
263 hardwareVersion2 = data[12];
265 outputPower = data[13] - 18;
268 * Firmware versions before 1000 did not include a firmware
269 * type in their response. Instead, versions 0-99 were for
270 * Type 1, versions 100-199 were for Type 2, and versions
271 * above 200 were for Ext.
273 * From version 1000, the response includes a longer message
274 * which adds a byte for firmware type. The version is calculated
275 * from the single byte, to which 1000 is added.
277 * Discovered through hints in the release notes and experimentation
278 * with RFXmngr. See RESPONSES.md for data.
280 if (data.length > 14) {
281 firmwareVersion = Byte.toUnsignedInt(data[6]) + 1000;
282 firmwareType = fromByte(FirmwareType.class, data[14]);
284 firmwareVersion = Byte.toUnsignedInt(data[6]);
286 if (firmwareVersion < 100) {
287 firmwareType = FirmwareType.TYPE1;
288 } else if (firmwareVersion < 200) {
289 firmwareType = FirmwareType.TYPE2;
291 firmwareType = FirmwareType.EXT;
296 * These are actually dependent on the type of device and
297 * firmware, this list is mainly for RFXtrx443 at 433.92MHz,
298 * which most of our users use.
300 * TODO: At some point, we should reconcile this with the SDK
301 * and accommodate for other devices and protocols. This is
302 * probably not worth doing until someone needs it and has
303 * suitable devices to test with!
305 enableUndecodedPackets = (data[7] & 0x80) != 0;
306 enableImagintronixOpusPackets = (data[7] & 0x40) != 0;
307 enableByronSXPackets = (data[7] & 0x20) != 0;
308 enableRSLPackets = (data[7] & 0x10) != 0;
309 enableLighting4Packets = (data[7] & 0x08) != 0;
310 enableFineOffsetPackets = (data[7] & 0x04) != 0;
311 enableRubicsonPackets = (data[7] & 0x02) != 0;
312 enableAEPackets = (data[7] & 0x01) != 0;
314 enableBlindsT1T2T3T4Packets = (data[8] & 0x80) != 0;
315 enableBlindsT0Packets = (data[8] & 0x40) != 0;
316 enableProGuardPackets = (data[8] & 0x20) != 0;
317 enableFS20Packets = (data[8] & 0x10) != 0;
318 enableLaCrossePackets = (data[8] & 0x08) != 0;
319 enableHidekiUPMPackets = (data[8] & 0x04) != 0;
320 enableADPackets = (data[8] & 0x02) != 0;
321 enableMertikPackets = (data[8] & 0x01) != 0;
323 enableVisonicPackets = (data[9] & 0x80) != 0;
324 enableATIPackets = (data[9] & 0x40) != 0;
325 enableOregonPackets = (data[9] & 0x20) != 0;
326 enableMeiantechPackets = (data[9] & 0x10) != 0;
327 enableHomeEasyPackets = (data[9] & 0x08) != 0;
328 enableACPackets = (data[9] & 0x04) != 0;
329 enableARCPackets = (data[9] & 0x02) != 0;
330 enableX10Packets = (data[9] & 0x01) != 0;
332 enableHomeConfortPackets = (data[10] & 0x02) != 0;
333 enableKEELOQPackets = (data[10] & 0x01) != 0;
338 private void encodeStartReceiverMessage(byte[] data) throws RFXComException {
339 command = fromByte(Commands.class, data[4]);
341 ByteBuffer text_bytes = ByteBuffer.wrap(data, 5, data.length - 5);
342 text = StandardCharsets.US_ASCII.decode(text_bytes).toString();
346 public byte[] decodeMessage() {
347 throw new UnsupportedOperationException();
351 public void convertFromState(String channelId, Type type) {
352 throw new UnsupportedOperationException();