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.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.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
22 import org.openhab.core.types.Type;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
27 * RFXCOM data class for interface message.
29 * @author Pauli Anttila - Initial contribution
30 * @author Ivan Martinez - Older firmware support (OH1)
32 public class RFXComInterfaceMessage extends RFXComBaseMessage {
34 private final Logger logger = LoggerFactory.getLogger(RFXComInterfaceMessage.class);
36 public enum SubType implements ByteEnumWrapper {
39 UNKNOWN_RTS_REMOTE(1),
40 NO_EXTENDED_HW_PRESENT(2),
45 private final int subType;
47 SubType(int subType) {
48 this.subType = subType;
52 public byte toByte() {
53 return (byte) subType;
57 public enum Commands implements ByteEnumWrapper {
58 RESET(0), // Reset the receiver/transceiver. No answer is transmitted!
59 GET_STATUS(2), // Get Status, return firmware versions and configuration of the interface
60 SET_MODE(3), // Set mode msg1-msg5, return firmware versions and configuration of the interface
61 ENABLE_ALL(4), // Enable all receiving modes of the receiver/transceiver
62 ENABLE_UNDECODED_PACKETS(5), // Enable reporting of undecoded packets
63 SAVE_RECEIVING_MODES(6), // Save receiving modes of the receiver/transceiver in non-volatile memory
64 START_RECEIVER(7), // Start RFXtrx receiver
65 T1(8), // For internal use by RFXCOM
66 T2(9), // For internal use by RFXCOM
68 UNSUPPORTED_COMMAND(-1); // wrong command received from the application
70 private final int command;
72 Commands(int command) {
73 this.command = command;
77 public byte toByte() {
78 return (byte) command;
82 public enum TransceiverType implements ByteEnumWrapper {
83 _310MHZ(0x50, "RFXtrx315 operating at 310MHz"),
84 _315MHZ(0x51, "RFXtrx315 operating at 315MHz"),
85 _433_92MHZ_RECEIVER_ONLY(0x52, "RFXrec433 operating at 433.92MHz (receiver only)"),
86 _433_92MHZ_TRANSCEIVER(0x53, "RFXtrx433 operating at 433.92MHz"),
87 _433_42MHZ(0x54, "RFXtrx433 operating at 433.42MHz"),
88 _868_00MHZ(0x55, "RFXtrx868X operating at 868MHz"),
89 _868_00MHZ_FSK(0x56, "RFXtrx868X operating at 868.00MHz FSK"),
90 _868_30MHZ(0x57, "RFXtrx868X operating at 868.30MHz"),
91 _868_30MHZ_FSK(0x58, "RFXtrx868X operating at 868.30MHz FSK"),
92 _868_35MHZ(0x59, "RFXtrx868X operating at 868.35MHz"),
93 _868_35MHZ_FSK(0x5A, "RFXtrx868X operating at 868.35MHz FSK"),
94 _868_95MHZ_FSK(0x5B, "RFXtrx868X operating at 868.95MHz"),
95 _433_92MHZ_IOT(0x5C, "RFXtrxIOT operating at 433.92MHz"),
96 _868_00MHZ_IOT(0x5D, "RFXtrxIOT operating at 868MHz"),
97 _434_50MHZ(0x5F, "RFXtrx433 operating at 434.50MHz"),
98 _UNKNOWN(0xFF, "Unknown");
100 private final int type;
101 private final String name;
103 TransceiverType(int type, String name) {
109 public byte toByte() {
114 public String toString() {
119 public enum FirmwareType implements ByteEnumWrapper {
120 TYPE1_RX_ONLY(0x00, "Type1 RFXrec receive only firmware"),
121 TYPE1(0x01, "Type1"),
122 TYPE2(0x02, "Type2"),
127 PROXL1(0x10, "ProXL1"),
128 PROXL2(0x12, "ProXL2"), // Discovered in the wild (not from RFXtrx SDK)
129 UNKNOWN(0xFF, "Unknown");
131 private final int type;
132 private final String name;
134 FirmwareType(int type, String name) {
140 public byte toByte() {
145 public String toString() {
150 public SubType subType;
151 public Commands command;
152 public String text = "";
154 public TransceiverType transceiverType;
155 public int firmwareVersion;
157 public boolean enableUndecodedPackets; // 0x80 - Undecoded packets
158 public boolean enableImagintronixOpusPackets; // 0x40 - Imagintronix/Opus (433.92)
159 public boolean enableByronSXPackets; // 0x20 - Byron SX (433.92)
160 public boolean enableRSLPackets; // 0x10 - RSL (433.92)
161 public boolean enableLighting4Packets; // 0x08 - Lighting4 (433.92)
162 public boolean enableFineOffsetPackets; // 0x04 - FineOffset / Viking (433.92)
163 public boolean enableRubicsonPackets; // 0x02 - Rubicson (433.92)
164 public boolean enableAEPackets; // 0x01 - AE (433.92)
166 public boolean enableBlindsT1T2T3T4Packets; // 0x80 - BlindsT1/T2/T3/T4 (433.92)
167 public boolean enableBlindsT0Packets; // 0x40 - BlindsT0 (433.92)
168 public boolean enableProGuardPackets; // 0x20 - ProGuard (868.35 FSK)
169 public boolean enableFS20Packets; // 0x10 - FS20 (868.35)
170 public boolean enableLaCrossePackets; // 0x08 - La Crosse (433.92/868.30)
171 public boolean enableHidekiUPMPackets; // 0x04 - Hideki/UPM (433.92)
172 public boolean enableADPackets; // 0x02 - AD LightwaveRF (433.92)
173 public boolean enableMertikPackets; // 0x01 - Mertik (433.92)
175 public boolean enableVisonicPackets; // 0x80 - Visonic (315/868.95)
176 public boolean enableATIPackets; // 0x40 - ATI (433.92)
177 public boolean enableOregonPackets; // 0x20 - Oregon Scientific (433.92)
178 public boolean enableMeiantechPackets; // 0x10 - Meiantech (433.92)
179 public boolean enableHomeEasyPackets; // 0x08 - HomeEasy EU (433.92)
180 public boolean enableACPackets; // 0x04 - AC (433.92)
181 public boolean enableARCPackets; // 0x02 - ARC (433.92)
182 public boolean enableX10Packets; // 0x01 - X10 (310/433.92)
184 public boolean enableHomeConfortPackets; // 0x02 - HomeConfort (433.92)
185 public boolean enableKEELOQPackets; // 0x01 - KEELOQ (433.92)
187 public byte hardwareVersion1;
188 public byte hardwareVersion2;
190 public int outputPower; // -18dBm to +13dBm. N.B. maximum allowed is +10dBm
192 public FirmwareType firmwareType;
194 public RFXComInterfaceMessage(byte[] data) throws RFXComException {
199 public String toString() {
202 str += super.toString();
203 str += ", Sub type = " + subType;
204 str += ", Command = " + command;
206 if (subType == SubType.RESPONSE) {
207 str += ", Transceiver type = " + transceiverType;
208 str += ", Hardware version = " + hardwareVersion1 + "." + hardwareVersion2;
209 str += ", Firmware type = " + (firmwareType != null ? firmwareType : "unknown");
210 str += ", Firmware version = " + firmwareVersion;
211 str += ", Output power = " + outputPower + "dBm";
212 str += ", Undecoded packets = " + enableUndecodedPackets;
213 str += ", RFU6 packets = " + enableImagintronixOpusPackets;
214 str += ", Byron SX packets packets (433.92) = " + enableByronSXPackets;
215 str += ", RSL packets packets (433.92) = " + enableRSLPackets;
216 str += ", Lighting4 packets (433.92) = " + enableLighting4Packets;
217 str += ", FineOffset / Viking (433.92) packets = " + enableFineOffsetPackets;
218 str += ", Rubicson (433.92) packets = " + enableRubicsonPackets;
219 str += ", AE (433.92) packets = " + enableAEPackets;
221 str += ", BlindsT1/T2/T3 (433.92) packets = " + enableBlindsT1T2T3T4Packets;
222 str += ", BlindsT0 (433.92) packets = " + enableBlindsT0Packets;
223 str += ", ProGuard (868.35 FSK) packets = " + enableProGuardPackets;
224 str += ", FS20/Legrand CAD (868.35/433.92) packets = " + enableFS20Packets;
225 str += ", La Crosse (433.92/868.30) packets = " + enableLaCrossePackets;
226 str += ", Hideki/UPM (433.92) packets = " + enableHidekiUPMPackets;
227 str += ", AD LightwaveRF (433.92) packets = " + enableADPackets;
228 str += ", Mertik (433.92) packets = " + enableMertikPackets;
230 str += ", Visonic (315/868.95) packets = " + enableVisonicPackets;
231 str += ", ATI (433.92) packets = " + enableATIPackets;
232 str += ", Oregon Scientific (433.92) packets = " + enableOregonPackets;
233 str += ", Meiantech (433.92) packets = " + enableMeiantechPackets;
234 str += ", HomeEasy EU (433.92) packets = " + enableHomeEasyPackets;
235 str += ", AC (433.92) packets = " + enableACPackets;
236 str += ", ARC (433.92) packets = " + enableARCPackets;
237 str += ", X10 (310/433.92) packets = " + enableX10Packets;
239 str += ", HomeConfort (433.92) packets = " + enableHomeConfortPackets;
240 str += ", KEELOQ (433.92/868.95) packets = " + enableKEELOQPackets;
241 } else if (subType == SubType.START_RECEIVER) {
242 str += ", Text = " + text;
249 public void encodeMessage(byte[] data) throws RFXComException {
250 super.encodeMessage(data);
252 subType = fromByte(SubType.class, super.subType);
254 if (subType == SubType.RESPONSE) {
255 encodeResponseMessage(data);
256 } else if (subType == SubType.START_RECEIVER) {
257 encodeStartReceiverMessage(data);
259 // We don't handle the other subTypes but to avoid null pointer
260 // exceptions we set command to something. It doesn't really
261 // matter what but it may be printed in log messages so...
262 command = Commands.UNSUPPORTED_COMMAND;
266 private void encodeResponseMessage(byte[] data) throws RFXComException {
267 command = fromByte(Commands.class, data[4]);
269 transceiverType = fromByte(TransceiverType.class, data[5]);
270 } catch (RFXComUnsupportedValueException e) {
271 transceiverType = TransceiverType._UNKNOWN;
273 "The transceiver type reported ({}) isn't known to the RFXCom binding. Please raise an issue at https://github.com/openhab/openhab-addons/ to have it included.",
274 Byte.toUnsignedInt(data[5]));
277 hardwareVersion1 = data[11];
278 hardwareVersion2 = data[12];
280 outputPower = data[13] - 18;
283 * Firmware versions before 1000 did not include a firmware
284 * type in their response. Instead, versions 0-99 were for
285 * Type 1, versions 100-199 were for Type 2, and versions
286 * above 200 were for Ext.
288 * From version 1000, the response includes a longer message
289 * which adds a byte for firmware type. The version is calculated
290 * from the single byte, to which 1000 is added.
292 * Discovered through hints in the release notes and experimentation
293 * with RFXmngr. See RESPONSES.md for data.
295 if (data.length > 14) {
296 firmwareVersion = Byte.toUnsignedInt(data[6]) + 1000;
298 firmwareType = fromByte(FirmwareType.class, data[14]);
299 } catch (RFXComUnsupportedValueException e) {
300 firmwareType = FirmwareType.UNKNOWN;
302 "The firmware type reported ({}) isn't known to the RFXCom binding. Please raise an issue at https://github.com/openhab/openhab-addons/ to have it included.",
306 firmwareVersion = Byte.toUnsignedInt(data[6]);
308 if (firmwareVersion < 100) {
309 firmwareType = FirmwareType.TYPE1;
310 } else if (firmwareVersion < 200) {
311 firmwareType = FirmwareType.TYPE2;
313 firmwareType = FirmwareType.EXT;
318 * These are actually dependent on the type of device and
319 * firmware, this list is mainly for RFXtrx443 at 433.92MHz,
320 * which most of our users use.
322 * TODO: At some point, we should reconcile this with the SDK
323 * and accommodate for other devices and protocols. This is
324 * probably not worth doing until someone needs it and has
325 * suitable devices to test with!
327 enableUndecodedPackets = (data[7] & 0x80) != 0;
328 enableImagintronixOpusPackets = (data[7] & 0x40) != 0;
329 enableByronSXPackets = (data[7] & 0x20) != 0;
330 enableRSLPackets = (data[7] & 0x10) != 0;
331 enableLighting4Packets = (data[7] & 0x08) != 0;
332 enableFineOffsetPackets = (data[7] & 0x04) != 0;
333 enableRubicsonPackets = (data[7] & 0x02) != 0;
334 enableAEPackets = (data[7] & 0x01) != 0;
336 enableBlindsT1T2T3T4Packets = (data[8] & 0x80) != 0;
337 enableBlindsT0Packets = (data[8] & 0x40) != 0;
338 enableProGuardPackets = (data[8] & 0x20) != 0;
339 enableFS20Packets = (data[8] & 0x10) != 0;
340 enableLaCrossePackets = (data[8] & 0x08) != 0;
341 enableHidekiUPMPackets = (data[8] & 0x04) != 0;
342 enableADPackets = (data[8] & 0x02) != 0;
343 enableMertikPackets = (data[8] & 0x01) != 0;
345 enableVisonicPackets = (data[9] & 0x80) != 0;
346 enableATIPackets = (data[9] & 0x40) != 0;
347 enableOregonPackets = (data[9] & 0x20) != 0;
348 enableMeiantechPackets = (data[9] & 0x10) != 0;
349 enableHomeEasyPackets = (data[9] & 0x08) != 0;
350 enableACPackets = (data[9] & 0x04) != 0;
351 enableARCPackets = (data[9] & 0x02) != 0;
352 enableX10Packets = (data[9] & 0x01) != 0;
354 enableHomeConfortPackets = (data[10] & 0x02) != 0;
355 enableKEELOQPackets = (data[10] & 0x01) != 0;
360 private void encodeStartReceiverMessage(byte[] data) throws RFXComException {
361 command = fromByte(Commands.class, data[4]);
363 ByteBuffer text_bytes = ByteBuffer.wrap(data, 5, data.length - 5);
364 text = StandardCharsets.US_ASCII.decode(text_bytes).toString();
368 public byte[] decodeMessage() {
369 throw new UnsupportedOperationException();
373 public void convertFromState(String channelId, Type type) {
374 throw new UnsupportedOperationException();
378 * Command to reset RFXCOM controller.
381 public static final byte[] CMD_RESET = new byte[] { 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382 0x00, 0x00, 0x00, 0x00 };
385 * Command to get RFXCOM controller status.
388 public static final byte[] CMD_GET_STATUS = new byte[] { 0x0D, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
389 0x00, 0x00, 0x00, 0x00 };
392 * Command to save RFXCOM controller configuration.
395 public static final byte[] CMD_SAVE = new byte[] { 0x0D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399 * Command to start RFXCOM receiver.
402 public static final byte[] CMD_START_RECEIVER = new byte[] { 0x0D, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00,
403 0x00, 0x00, 0x00, 0x00, 0x00 };