]> git.basschouten.com Git - openhab-addons.git/blob
2e00670b4eeee88d8ebd342c52e302a099dc26f8
[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.rfxcom.internal.messages;
14
15 import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
16
17 import java.nio.ByteBuffer;
18 import java.nio.charset.StandardCharsets;
19
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;
25
26 /**
27  * RFXCOM data class for interface message.
28  *
29  * @author Pauli Anttila - Initial contribution
30  * @author Ivan Martinez - Older firmware support (OH1)
31  */
32 public class RFXComInterfaceMessage extends RFXComBaseMessage {
33
34     private final Logger logger = LoggerFactory.getLogger(RFXComInterfaceMessage.class);
35
36     public enum SubType implements ByteEnumWrapper {
37         UNKNOWN_COMMAND(-1),
38         RESPONSE(0),
39         UNKNOWN_RTS_REMOTE(1),
40         NO_EXTENDED_HW_PRESENT(2),
41         LIST_RFY_REMOTES(3),
42         LIST_ASA_REMOTES(4),
43         START_RECEIVER(7);
44
45         private final int subType;
46
47         SubType(int subType) {
48             this.subType = subType;
49         }
50
51         @Override
52         public byte toByte() {
53             return (byte) subType;
54         }
55     }
56
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
67
68         UNSUPPORTED_COMMAND(-1); // wrong command received from the application
69
70         private final int command;
71
72         Commands(int command) {
73             this.command = command;
74         }
75
76         @Override
77         public byte toByte() {
78             return (byte) command;
79         }
80     }
81
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");
99
100         private final int type;
101         private final String name;
102
103         TransceiverType(int type, String name) {
104             this.type = type;
105             this.name = name;
106         }
107
108         @Override
109         public byte toByte() {
110             return (byte) type;
111         }
112
113         @Override
114         public String toString() {
115             return name;
116         }
117     }
118
119     public enum FirmwareType implements ByteEnumWrapper {
120         TYPE1_RX_ONLY(0x00, "Type1 RFXrec receive only firmware"),
121         TYPE1(0x01, "Type1"),
122         TYPE2(0x02, "Type2"),
123         EXT(0x03, "Ext"),
124         EXT2(0x04, "Ext2"),
125         PRO1(0x05, "Pro1"),
126         PRO2(0x06, "Pro2"),
127         PROXL1(0x10, "ProXL1"),
128         PROXL2(0x12, "ProXL2"), // Discovered in the wild (not from RFXtrx SDK)
129         UNKNOWN(0xFF, "Unknown");
130
131         private final int type;
132         private final String name;
133
134         FirmwareType(int type, String name) {
135             this.type = type;
136             this.name = name;
137         }
138
139         @Override
140         public byte toByte() {
141             return (byte) type;
142         }
143
144         @Override
145         public String toString() {
146             return name;
147         }
148     }
149
150     public SubType subType;
151     public Commands command;
152     public String text = "";
153
154     public TransceiverType transceiverType;
155     public int firmwareVersion;
156
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)
165
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)
174
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)
183
184     public boolean enableHomeConfortPackets; // 0x02 - HomeConfort (433.92)
185     public boolean enableKEELOQPackets; // 0x01 - KEELOQ (433.92)
186
187     public byte hardwareVersion1;
188     public byte hardwareVersion2;
189
190     public int outputPower; // -18dBm to +13dBm. N.B. maximum allowed is +10dBm
191
192     public FirmwareType firmwareType;
193
194     public RFXComInterfaceMessage(byte[] data) throws RFXComException {
195         encodeMessage(data);
196     }
197
198     @Override
199     public String toString() {
200         String str = "";
201
202         str += super.toString();
203         str += ", Sub type = " + subType;
204         str += ", Command = " + command;
205
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;
220
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;
229
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;
238
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;
243         }
244
245         return str;
246     }
247
248     @Override
249     public void encodeMessage(byte[] data) throws RFXComException {
250         super.encodeMessage(data);
251
252         subType = fromByte(SubType.class, super.subType);
253
254         if (subType == SubType.RESPONSE) {
255             encodeResponseMessage(data);
256         } else if (subType == SubType.START_RECEIVER) {
257             encodeStartReceiverMessage(data);
258         } else {
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;
263         }
264     }
265
266     private void encodeResponseMessage(byte[] data) throws RFXComException {
267         command = fromByte(Commands.class, data[4]);
268         try {
269             transceiverType = fromByte(TransceiverType.class, data[5]);
270         } catch (RFXComUnsupportedValueException e) {
271             transceiverType = TransceiverType._UNKNOWN;
272             logger.warn(
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]));
275         }
276
277         hardwareVersion1 = data[11];
278         hardwareVersion2 = data[12];
279
280         outputPower = data[13] - 18;
281
282         /*
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.
287          *
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.
291          *
292          * Discovered through hints in the release notes and experimentation
293          * with RFXmngr. See RESPONSES.md for data.
294          */
295         if (data.length > 14) {
296             firmwareVersion = Byte.toUnsignedInt(data[6]) + 1000;
297             try {
298                 firmwareType = fromByte(FirmwareType.class, data[14]);
299             } catch (RFXComUnsupportedValueException e) {
300                 firmwareType = FirmwareType.UNKNOWN;
301                 logger.warn(
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.",
303                         data[14]);
304             }
305         } else {
306             firmwareVersion = Byte.toUnsignedInt(data[6]);
307
308             if (firmwareVersion < 100) {
309                 firmwareType = FirmwareType.TYPE1;
310             } else if (firmwareVersion < 200) {
311                 firmwareType = FirmwareType.TYPE2;
312             } else {
313                 firmwareType = FirmwareType.EXT;
314             }
315         }
316
317         /*
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.
321          *
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!
326          */
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;
335
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;
344
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;
353
354         enableHomeConfortPackets = (data[10] & 0x02) != 0;
355         enableKEELOQPackets = (data[10] & 0x01) != 0;
356
357         text = "";
358     }
359
360     private void encodeStartReceiverMessage(byte[] data) throws RFXComException {
361         command = fromByte(Commands.class, data[4]);
362
363         ByteBuffer text_bytes = ByteBuffer.wrap(data, 5, data.length - 5);
364         text = StandardCharsets.US_ASCII.decode(text_bytes).toString();
365     }
366
367     @Override
368     public byte[] decodeMessage() {
369         throw new UnsupportedOperationException();
370     }
371
372     @Override
373     public void convertFromState(String channelId, Type type) {
374         throw new UnsupportedOperationException();
375     }
376
377     /**
378      * Command to reset RFXCOM controller.
379      *
380      */
381     public static final byte[] CMD_RESET = new byte[] { 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382             0x00, 0x00, 0x00, 0x00 };
383
384     /**
385      * Command to get RFXCOM controller status.
386      *
387      */
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 };
390
391     /**
392      * Command to save RFXCOM controller configuration.
393      *
394      */
395     public static final byte[] CMD_SAVE = new byte[] { 0x0D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
396             0x00, 0x00, 0x00 };
397
398     /**
399      * Command to start RFXCOM receiver.
400      *
401      */
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 };
404 }