]> git.basschouten.com Git - openhab-addons.git/commitdiff
[rfxcom] Update interface message support (#10844)
authorJames Hewitt <james.hewitt@gmail.com>
Tue, 15 Jun 2021 17:37:07 +0000 (18:37 +0100)
committerGitHub <noreply@github.com>
Tue, 15 Jun 2021 17:37:07 +0000 (19:37 +0200)
Based on both the SDK and experimentation, this commit correctly identifies the
firmware and hardware version. A warning has been added for people with really
old firmware that may be different, but we didn't handle those different cases
well anyway.

Also includes updated firmware types and device types and support for pretty-
printing of the device and firmware type.

Signed-off-by: James Hewitt <james.hewitt@uk.ibm.com>
bundles/org.openhab.binding.rfxcom/RESPONSES.md [new file with mode: 0644]
bundles/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/handler/RFXComBridgeHandler.java
bundles/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComInterfaceControlMessage.java
bundles/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComInterfaceMessage.java
bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComInterfaceMessageTest.java

diff --git a/bundles/org.openhab.binding.rfxcom/RESPONSES.md b/bundles/org.openhab.binding.rfxcom/RESPONSES.md
new file mode 100644 (file)
index 0000000..f91e8b8
--- /dev/null
@@ -0,0 +1,57 @@
+# Responses
+
+Record of responses to some commands for working out how things work.
+
+## Interface Message - Status Response
+
+These messages were received when testing different firmwares.
+
+```
+Ext    250   0D0100010253FA0400070001031C
+Ext    251   0D0100010253FB0400070001031C
+Ext    1001  140100010253010400070001031C03000000000000
+Pro1   1044  1401000102532C04000700010300055D0000000000
+Type1  1024  140100010253180000270001031C01000000000000
+Type1  95    0D01000102535F0000270001031C
+Type2  195   0D0100010253C30080270001031C
+Type2  1022  140100010253160080270001031C02000000000000
+```
+
+## RFXMngr mode setting
+
+These messages were sent by RFXMngr when enabling single modes.
+
+On Pro1 firmware 1044 RFXtrx443 at 433.92MHZ
+```
+enableUndecodedPackets        0D 00 00 03 03 53 00 80 00 00 00 00 00 00
+enableImagintronixOpusPackets 0D 00 00 04 03 53 00 40 00 00 00 00 00 00
+enableByronSXPackets          0D 00 00 05 03 53 00 20 00 00 00 00 00 00
+enableRSLPackets              0D 00 00 06 03 53 00 10 00 00 00 00 00 00
+enableLighting4Packets        0D 00 00 07 03 53 00 08 00 00 00 00 00 00
+enableFineOffsetPackets       0D 00 00 08 03 53 00 04 00 00 00 00 00 00
+enableRubicsonPackets         0D 00 00 09 03 53 00 02 00 00 00 00 00 00
+enableAEPackets               0D 00 00 0A 03 53 00 01 00 00 00 00 00 00
+
+enableBlindsT1T2T3T4Packets   0D 00 00 0B 03 53 00 00 80 00 00 00 00 00
+enableBlindsT0Packets         0D 00 00 0C 03 53 00 00 40 00 00 00 00 00
+? Blank in RFXmngr            0D 00 00 0C 03 53 00 00 20 00 00 00 00 00
+Legrand CAD                   0D 00 00 0E 03 53 00 00 10 00 00 00 00 00
+enableProGuardPackets         Not in RFXmngr
+enableFS20Packets             Not in RFXmngr
+enableLaCrossePackets         0D 00 00 0F 03 53 00 00 08 00 00 00 00 00
+enableHidekiUPMPackets        0D 00 00 10 03 53 00 00 04 00 00 00 00 00
+enableADPackets               0D 00 00 11 03 53 00 00 02 00 00 00 00 00
+enableMertikPackets           0D 00 00 12 03 53 00 00 01 00 00 00 00 00
+
+enableVisonicPackets          0D 00 00 13 03 53 00 00 00 80 00 00 00 00
+enableATIPackets              0D 00 00 14 03 53 00 00 00 40 00 00 00 00
+enableOregonPackets           0D 00 00 14 03 53 00 00 00 20 00 00 00 00
+enableMeiantechPackets        0D 00 00 14 03 53 00 00 00 10 00 00 00 00
+enableHomeEasyPackets         0D 00 00 14 03 53 00 00 00 08 00 00 00 00
+enableACPackets               0D 00 00 14 03 53 00 00 00 04 00 00 00 00
+enableARCPackets              0D 00 00 14 03 53 00 00 00 02 00 00 00 00
+enableX10Packets              0D 00 00 14 03 53 00 00 00 01 00 00 00 00
+
+enableHomeConfortPackets      0D 00 00 14 03 53 00 00 00 00 02 00 00 00
+enableKEELOQPackets           0D 00 00 14 03 53 00 00 00 00 01 00 00 00
+```
\ No newline at end of file
index cc33c8e3534fbcb962eaa444e146d49cb3f490dc..5ea7f9a9c62e6a0c6da0791bf8a9d0f9c7ccdaf9 100644 (file)
@@ -253,6 +253,15 @@ public class RFXComBridgeHandler extends BaseBridgeHandler {
                             logger.debug("RFXCOM transceiver/receiver type: {}, hw version: {}.{}, fw version: {}",
                                     msg.transceiverType, msg.hardwareVersion1, msg.hardwareVersion2,
                                     msg.firmwareVersion);
+                            if (msg.firmwareVersion < 1000) {
+                                /**
+                                 * Versions before 1000 had some different behaviour, so lets encourage upgrading.
+                                 * 1001 was released in Feb 2016!
+                                 */
+                                logger.warn(
+                                        "RFXCOM device using outdated firmware (version {}), consider flashing with more a more recent version",
+                                        msg.firmwareVersion);
+                            }
                             thing.setProperty(Thing.PROPERTY_HARDWARE_VERSION,
                                     msg.hardwareVersion1 + "." + msg.hardwareVersion2);
                             thing.setProperty(Thing.PROPERTY_FIRMWARE_VERSION, Integer.toString(msg.firmwareVersion));
index 1d7716f99ab28701b720e73099633b88b0dc2dca..1ffe4d6b4f24c06960b3fa5c8ea406356042c208 100644 (file)
@@ -34,6 +34,17 @@ public class RFXComInterfaceControlMessage extends RFXComBaseMessage {
         data[5] = transceiverType.toByte();
         data[6] = (byte) (configuration.transmitPower + 18);
 
+        /*
+         * These are actually dependent on the type of device and
+         * firmware, this list is mainly for RFXtrx443 at 433.92MHz,
+         * which most of our users use.
+         *
+         * TODO: At some point, we should reconcile this with the SDK
+         * and accommodate for other devices and protocols. This is
+         * probably not worth doing until someone needs it and has
+         * suitable devices to test with!
+         */
+
         //@formatter:off
         data[7] = (byte) (
                   (configuration.enableUndecoded        ? 0x80 : 0x00)
index fa70cc85287626f20cbd6a04e47829f74d37bbe5..bf09db4bff2821b10cfa270cfae12073fe8ad267 100644 (file)
@@ -14,6 +14,7 @@ package org.openhab.binding.rfxcom.internal.messages;
 
 import static org.openhab.binding.rfxcom.internal.messages.ByteEnumUtil.fromByte;
 
+import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 
 import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
@@ -74,47 +75,68 @@ public class RFXComInterfaceMessage extends RFXComBaseMessage {
     }
 
     public enum TransceiverType implements ByteEnumWrapper {
-        _310MHZ(80),
-        _315MHZ(81),
-        _433_92MHZ_RECEIVER_ONLY(82),
-        _433_92MHZ_TRANSCEIVER(83),
-        _868_00MHZ(85),
-        _868_00MHZ_FSK(86),
-        _868_30MHZ(87),
-        _868_30MHZ_FSK(88),
-        _868_35MHZ(89),
-        _868_35MHZ_FSK(90),
-        _868_95MHZ_FSK(91);
+        _310MHZ(0x50, "RFXtrx315 operating at 310MHz"),
+        _315MHZ(0x51, "RFXtrx315 operating at 315MHz"),
+        _433_92MHZ_RECEIVER_ONLY(0x52, "RFXrec433 operating at 433.92MHz (receiver only)"),
+        _433_92MHZ_TRANSCEIVER(0x53, "RFXtrx433 operating at 433.92MHz"),
+        _433_42MHZ(0x54, "RFXtrx433 operating at 433.42MHz"),
+        _868_00MHZ(0x55, "RFXtrx868X operating at 868MHz"),
+        _868_00MHZ_FSK(0x56, "RFXtrx868X operating at 868.00MHz FSK"),
+        _868_30MHZ(0x57, "RFXtrx868X operating at 868.30MHz"),
+        _868_30MHZ_FSK(0x58, "RFXtrx868X operating at 868.30MHz FSK"),
+        _868_35MHZ(0x59, "RFXtrx868X operating at 868.35MHz"),
+        _868_35MHZ_FSK(0x5A, "RFXtrx868X operating at 868.35MHz FSK"),
+        _868_95MHZ_FSK(0x5B, "RFXtrx868X operating at 868.95MHz"),
+        _433_92MHZ_IOT(0x5C, "RFXtrxIOT operating at 433.92MHz"),
+        _868_00MHZ_IOT(0x5D, "RFXtrxIOT operating at 868MHz"),
+        _434_50MHZ(0x5F, "RFXtrx433 operating at 434.50MHz");
 
         private final int type;
+        private final String name;
 
-        TransceiverType(int type) {
+        TransceiverType(int type, String name) {
             this.type = type;
+            this.name = name;
         }
 
         @Override
         public byte toByte() {
             return (byte) type;
         }
+
+        @Override
+        public String toString() {
+            return name;
+        }
     }
 
     public enum FirmwareType implements ByteEnumWrapper {
-        TYPE1_RX_ONLY(0),
-        TYPE1(1),
-        TYPE2(2),
-        EXT(3),
-        EXT2(4);
+        TYPE1_RX_ONLY(0x00, "Type1 RFXrec receive only firmware"),
+        TYPE1(0x01, "Type1"),
+        TYPE2(0x02, "Type2"),
+        EXT(0x03, "Ext"),
+        EXT2(0x04, "Ext2"),
+        PRO1(0x05, "Pro1"),
+        PRO2(0x06, "Pro2"),
+        PROXL1(0x10, "ProXL 1");
 
         private final int type;
+        private final String name;
 
-        FirmwareType(int type) {
+        FirmwareType(int type, String name) {
             this.type = type;
+            this.name = name;
         }
 
         @Override
         public byte toByte() {
             return (byte) type;
         }
+
+        @Override
+        public String toString() {
+            return name;
+        }
     }
 
     public SubType subType;
@@ -222,83 +244,104 @@ public class RFXComInterfaceMessage extends RFXComBaseMessage {
         subType = fromByte(SubType.class, super.subType);
 
         if (subType == SubType.RESPONSE) {
-            command = fromByte(Commands.class, data[4]);
-            transceiverType = fromByte(TransceiverType.class, data[5]);
-
-            firmwareVersion = data[6] & 0xFF;
-
-            enableUndecodedPackets = (data[7] & 0x80) != 0;
-            enableImagintronixOpusPackets = (data[7] & 0x40) != 0;
-            enableByronSXPackets = (data[7] & 0x20) != 0;
-            enableRSLPackets = (data[7] & 0x10) != 0;
-            enableLighting4Packets = (data[7] & 0x08) != 0;
-            enableFineOffsetPackets = (data[7] & 0x04) != 0;
-            enableRubicsonPackets = (data[7] & 0x02) != 0;
-            enableAEPackets = (data[7] & 0x01) != 0;
-
-            enableBlindsT1T2T3T4Packets = (data[8] & 0x80) != 0;
-            enableBlindsT0Packets = (data[8] & 0x40) != 0;
-            enableProGuardPackets = (data[8] & 0x20) != 0;
-            enableFS20Packets = (data[8] & 0x10) != 0;
-            enableLaCrossePackets = (data[8] & 0x08) != 0;
-            enableHidekiUPMPackets = (data[8] & 0x04) != 0;
-            enableADPackets = (data[8] & 0x02) != 0;
-            enableMertikPackets = (data[8] & 0x01) != 0;
-
-            enableVisonicPackets = (data[9] & 0x80) != 0;
-            enableATIPackets = (data[9] & 0x40) != 0;
-            enableOregonPackets = (data[9] & 0x20) != 0;
-            enableMeiantechPackets = (data[9] & 0x10) != 0;
-            enableHomeEasyPackets = (data[9] & 0x08) != 0;
-            enableACPackets = (data[9] & 0x04) != 0;
-            enableARCPackets = (data[9] & 0x02) != 0;
-            enableX10Packets = (data[9] & 0x01) != 0;
-
-            /*
-             * Different firmware versions have slightly different message formats.
-             * The firmware version numbering is unique to each hardware version
-             * but the location of the hardware version in the message is one of
-             * those things whose position varies. So we have to just look at the
-             * firmware version and pray. This condition below is taken from the
-             * openhab1-addons binding.
-             */
-            if ((firmwareVersion >= 95 && firmwareVersion <= 100) || (firmwareVersion >= 195 && firmwareVersion <= 200)
-                    || (firmwareVersion >= 251)) {
-                enableHomeConfortPackets = (data[10] & 0x02) != 0;
-                enableKEELOQPackets = (data[10] & 0x01) != 0;
-
-                hardwareVersion1 = data[11];
-                hardwareVersion2 = data[12];
-
-                outputPower = data[13] - 18;
-                firmwareType = fromByte(FirmwareType.class, data[14]);
-            } else {
-                hardwareVersion1 = data[10];
-                hardwareVersion2 = data[11];
-            }
-
-            text = "";
+            encodeResponseMessage(data);
         } else if (subType == SubType.START_RECEIVER) {
-            command = fromByte(Commands.class, data[4]);
-
-            final int len = 16;
-            final int dataOffset = 5;
-
-            byte[] byteArray = new byte[len];
-
-            for (int i = dataOffset; i < (dataOffset + len); i++) {
-                byteArray[i - dataOffset] += data[i];
-            }
-
-            text = new String(byteArray, StandardCharsets.US_ASCII);
+            encodeStartReceiverMessage(data);
         } else {
             // We don't handle the other subTypes but to avoid null pointer
             // exceptions we set command to something. It doesn't really
-            // matter what but it may b printed in log messages so...
+            // matter what but it may be printed in log messages so...
             command = Commands.UNSUPPORTED_COMMAND;
         }
     }
 
+    private void encodeResponseMessage(byte[] data) throws RFXComException {
+        command = fromByte(Commands.class, data[4]);
+        transceiverType = fromByte(TransceiverType.class, data[5]);
+
+        hardwareVersion1 = data[11];
+        hardwareVersion2 = data[12];
+
+        outputPower = data[13] - 18;
+
+        /*
+         * Firmware versions before 1000 did not include a firmware
+         * type in their response. Instead, versions 0-99 were for
+         * Type 1, versions 100-199 were for Type 2, and versions
+         * above 200 were for Ext.
+         *
+         * From version 1000, the response includes a longer message
+         * which adds a byte for firmware type. The version is calculated
+         * from the single byte, to which 1000 is added.
+         *
+         * Discovered through hints in the release notes and experimentation
+         * with RFXmngr. See RESPONSES.md for data.
+         */
+        if (data.length > 14) {
+            firmwareVersion = Byte.toUnsignedInt(data[6]) + 1000;
+            firmwareType = fromByte(FirmwareType.class, data[14]);
+        } else {
+            firmwareVersion = Byte.toUnsignedInt(data[6]);
+
+            if (firmwareVersion < 100) {
+                firmwareType = FirmwareType.TYPE1;
+            } else if (firmwareVersion < 200) {
+                firmwareType = FirmwareType.TYPE2;
+            } else {
+                firmwareType = FirmwareType.EXT;
+            }
+        }
+
+        /*
+         * These are actually dependent on the type of device and
+         * firmware, this list is mainly for RFXtrx443 at 433.92MHz,
+         * which most of our users use.
+         *
+         * TODO: At some point, we should reconcile this with the SDK
+         * and accommodate for other devices and protocols. This is
+         * probably not worth doing until someone needs it and has
+         * suitable devices to test with!
+         */
+        enableUndecodedPackets = (data[7] & 0x80) != 0;
+        enableImagintronixOpusPackets = (data[7] & 0x40) != 0;
+        enableByronSXPackets = (data[7] & 0x20) != 0;
+        enableRSLPackets = (data[7] & 0x10) != 0;
+        enableLighting4Packets = (data[7] & 0x08) != 0;
+        enableFineOffsetPackets = (data[7] & 0x04) != 0;
+        enableRubicsonPackets = (data[7] & 0x02) != 0;
+        enableAEPackets = (data[7] & 0x01) != 0;
+
+        enableBlindsT1T2T3T4Packets = (data[8] & 0x80) != 0;
+        enableBlindsT0Packets = (data[8] & 0x40) != 0;
+        enableProGuardPackets = (data[8] & 0x20) != 0;
+        enableFS20Packets = (data[8] & 0x10) != 0;
+        enableLaCrossePackets = (data[8] & 0x08) != 0;
+        enableHidekiUPMPackets = (data[8] & 0x04) != 0;
+        enableADPackets = (data[8] & 0x02) != 0;
+        enableMertikPackets = (data[8] & 0x01) != 0;
+
+        enableVisonicPackets = (data[9] & 0x80) != 0;
+        enableATIPackets = (data[9] & 0x40) != 0;
+        enableOregonPackets = (data[9] & 0x20) != 0;
+        enableMeiantechPackets = (data[9] & 0x10) != 0;
+        enableHomeEasyPackets = (data[9] & 0x08) != 0;
+        enableACPackets = (data[9] & 0x04) != 0;
+        enableARCPackets = (data[9] & 0x02) != 0;
+        enableX10Packets = (data[9] & 0x01) != 0;
+
+        enableHomeConfortPackets = (data[10] & 0x02) != 0;
+        enableKEELOQPackets = (data[10] & 0x01) != 0;
+
+        text = "";
+    }
+
+    private void encodeStartReceiverMessage(byte[] data) throws RFXComException {
+        command = fromByte(Commands.class, data[4]);
+
+        ByteBuffer text_bytes = ByteBuffer.wrap(data, 5, data.length - 5);
+        text = StandardCharsets.US_ASCII.decode(text_bytes).toString();
+    }
+
     @Override
     public byte[] decodeMessage() {
         throw new UnsupportedOperationException();
index 6771efa0780c093f70cdf84fc00ac0b4fcb1e33b..16a45f9221ba453fa4d6546f1157046cc5e33e8b 100644 (file)
 package org.openhab.binding.rfxcom.internal.messages;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.openhab.binding.rfxcom.internal.messages.RFXComInterfaceMessage.Commands.*;
-import static org.openhab.binding.rfxcom.internal.messages.RFXComInterfaceMessage.SubType.*;
-import static org.openhab.binding.rfxcom.internal.messages.RFXComInterfaceMessage.SubType.START_RECEIVER;
-import static org.openhab.binding.rfxcom.internal.messages.RFXComInterfaceMessage.TransceiverType._433_92MHZ_TRANSCEIVER;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.junit.jupiter.api.Test;
 import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
 import org.openhab.binding.rfxcom.internal.messages.RFXComInterfaceMessage.Commands;
+import org.openhab.binding.rfxcom.internal.messages.RFXComInterfaceMessage.FirmwareType;
 import org.openhab.binding.rfxcom.internal.messages.RFXComInterfaceMessage.SubType;
+import org.openhab.binding.rfxcom.internal.messages.RFXComInterfaceMessage.TransceiverType;
 import org.openhab.core.util.HexUtils;
 
 /**
@@ -45,24 +43,73 @@ public class RFXComInterfaceMessageTest {
 
     @Test
     public void testWelcomeCopyRightMessage() throws RFXComException {
-        RFXComInterfaceMessage msg = testMessage("1401070307436F7079726967687420524658434F4D", START_RECEIVER, 3,
-                Commands.START_RECEIVER);
+        RFXComInterfaceMessage msg = testMessage("1401070307436F7079726967687420524658434F4D", SubType.START_RECEIVER,
+                3, Commands.START_RECEIVER);
 
         assertEquals("Copyright RFXCOM", msg.text, "text");
     }
 
     @Test
     public void testRespondOnUnknownMessage() throws RFXComException {
-        testMessage("0D01FF190053E2000C2701020000", UNKNOWN_COMMAND, 25, UNSUPPORTED_COMMAND);
+        testMessage("0D01FF190053E2000C2701020000", SubType.UNKNOWN_COMMAND, 25, Commands.UNSUPPORTED_COMMAND);
+    }
+
+    private void testStatus(String message, TransceiverType transceiverType, FirmwareType firmwareType,
+            int firewareVersion) throws RFXComException {
+        RFXComInterfaceMessage msg = testMessage(message, SubType.RESPONSE, 1, Commands.GET_STATUS);
+
+        assertEquals(transceiverType, msg.transceiverType, "transceiverType");
+        assertEquals(firmwareType, msg.firmwareType, "firmwareType");
+        assertEquals(firewareVersion, msg.firmwareVersion, "firmwareVersion");
     }
 
     @Test
-    public void testStatusMessage() throws RFXComException {
-        RFXComInterfaceMessage msg = testMessage("1401000102530C0800270001031C04524658434F4D", RESPONSE, 1, GET_STATUS);
+    public void testStatus_Rfxtrx443_Ext_250() throws RFXComException {
+        testStatus("0D0100010253FA0400070001031C", TransceiverType._433_92MHZ_TRANSCEIVER, FirmwareType.EXT, 250);
+    }
 
-        assertEquals(_433_92MHZ_TRANSCEIVER, msg.transceiverType, "Command");
+    @Test
+    public void testStatus_Rfxtrx443_Ext_251() throws RFXComException {
+        testStatus("0D0100010253FB0400070001031C", TransceiverType._433_92MHZ_TRANSCEIVER, FirmwareType.EXT, 251);
+    }
 
-        // TODO this is not correct, improvements for this have been made in the OH1 repo
-        assertEquals(12, msg.firmwareVersion, "firmwareVersion");
+    @Test
+    public void testStatus_Rfxtrx443_Ext_1001() throws RFXComException {
+        testStatus("140100010253010400070001031C03000000000000", TransceiverType._433_92MHZ_TRANSCEIVER,
+                FirmwareType.EXT, 1001);
+    }
+
+    @Test
+    public void testStatus_Rfxtrx443_Pro1_1044() throws RFXComException {
+        testStatus("1401000102532C04000700010300055D0000000000", TransceiverType._433_92MHZ_TRANSCEIVER,
+                FirmwareType.PRO1, 1044);
+    }
+
+    @Test
+    public void testStatus_Rfxtrx443_Type1_95() throws RFXComException {
+        testStatus("0D01000102535F0000270001031C", TransceiverType._433_92MHZ_TRANSCEIVER, FirmwareType.TYPE1, 95);
+    }
+
+    @Test
+    public void testStatus_Rfxtrx443_Type1_1024() throws RFXComException {
+        testStatus("140100010253180000270001031C01000000000000", TransceiverType._433_92MHZ_TRANSCEIVER,
+                FirmwareType.TYPE1, 1024);
+    }
+
+    @Test
+    public void testStatus_Rfxtrx443_Type2_195() throws RFXComException {
+        testStatus("0D0100010253C30080270001031C", TransceiverType._433_92MHZ_TRANSCEIVER, FirmwareType.TYPE2, 195);
+    }
+
+    @Test
+    public void testStatus_Rfxtrx443_Type2_1022() throws RFXComException {
+        testStatus("140100010253160080270001031C02000000000000", TransceiverType._433_92MHZ_TRANSCEIVER,
+                FirmwareType.TYPE2, 1022);
+    }
+
+    @Test
+    public void testStatus_Rfxtrx443_Ext2_1012() throws RFXComException {
+        testStatus("1401000102530C0800270001031C04524658434F4D", TransceiverType._433_92MHZ_TRANSCEIVER,
+                FirmwareType.EXT2, 1012);
     }
 }