]> git.basschouten.com Git - openhab-addons.git/commitdiff
[rfxcom] Add support for receiving RAW messages (#10833)
authorJames Hewitt <james.hewitt@gmail.com>
Mon, 14 Jun 2021 07:05:03 +0000 (08:05 +0100)
committerGitHub <noreply@github.com>
Mon, 14 Jun 2021 07:05:03 +0000 (09:05 +0200)
This is a new feature in the Pro firmwares that provides the real raw RF
pulse lengths as shorts. Good for being able to parrot switches that aren't
otherwise supported, once we add the tx support as well.

Signed-off-by: James Hewitt <james.hewitt@uk.ibm.com>
bundles/org.openhab.binding.rfxcom/README.md
bundles/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/RFXComBindingConstants.java
bundles/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComBaseMessage.java
bundles/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComMessageFactory.java
bundles/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComRawMessage.java [new file with mode: 0644]
bundles/org.openhab.binding.rfxcom/src/main/resources/OH-INF/thing/channels.xml
bundles/org.openhab.binding.rfxcom/src/main/resources/OH-INF/thing/raw.xml [new file with mode: 0644]
bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComRawMessageTest.java [new file with mode: 0644]

index 62f89fe0d3db5bdc00bc0162ef8fdf193e704675..b82ae0dc82c917d7baf34d63b9f9055500327362 100644 (file)
@@ -174,7 +174,7 @@ This binding currently supports following channel types:
 | rainrate        | Number        | Rain fall rate in millimeters per hour.                                            |
 | raintotal       | Number        | Total rain in millimeters.                                                         |
 | rawmessage      | String        | Hexadecimal representation of the raw RFXCOM msg incl. header and payload          |
-| rawpayload      | String        | Hexadecimal representation of payload RFXCOM messages                              |
+| rawpayload      | String        | Hexadecimal representation of the payload of RFXCOM messages                       |
 | setpoint        | Number        | Requested temperature.                                                             |
 | shutter         | Rollershutter | Shutter/blind channel.                                                             |
 | status          | String        | Status channel.                                                                    |
@@ -229,6 +229,7 @@ This binding currently supports the following things / message types:
 *   [lighting5 - RFXCOM Lighting5 Actuator](#lighting5---rfxcom-lighting5-actuator)
 *   [lighting6 - RFXCOM Lighting6 Actuator](#lighting6---rfxcom-lighting6-actuator)
 *   [rain - RFXCOM Rain Sensor](#rain---rfxcom-rain-sensor)
+*   [raw - RFXCOM Raw Messages](#raw---rfxcom-raw-messages)
 *   [rfxsensor - RFXCOM rfxsensor](#rfxsensor)
 *   [rfy - RFXCOM Rfy Actuator](#rfy---rfxcom-rfy-actuator)
 *   [security1 - RFXCOM Security1 Sensor](#security1---rfxcom-security1-sensor)
@@ -884,6 +885,31 @@ A Rain device
         *   RAIN6 - La Crosse TX5
         *   RAIN9 - TFA 30.3233.1
 
+### raw - RFXCOM Raw Messages
+
+Raw messages.
+
+#### Channels
+
+| Name       | Channel Type              | Item Type | Remarks     |
+|------------|---------------------------|-----------|-------------|
+| rawMessage | [rawmessage](#channels)   | String    |             |
+| rawPayload | [rawpayload](#channels)   | String    |             |
+
+#### Configuration Options
+
+*   deviceId - Device Id
+    *   Raw items cannot provide a device ID, so this value is always RAW.
+
+*   subType - Sub Type
+    *   Specifies message sub type.
+
+        *   RAW_PACKET1
+        *   RAW_PACKET2
+        *   RAW_PACKET3
+        *   RAW_PACKET4
+
+
 ### rfxsensor - RFXCOM RFXSensor 
 
 A RFXSensor sensor
index c558cdc223f256898ea6a933fd818be1ed102888..d300abab5a2587c008ea08de135270f403fbe69f 100644 (file)
@@ -147,6 +147,7 @@ public class RFXComBindingConstants {
     private static final ThingTypeUID THING_TYPE_POWER = new ThingTypeUID(BINDING_ID, "power");
     private static final ThingTypeUID THING_TYPE_RADIATOR1 = new ThingTypeUID(BINDING_ID, "radiator1");
     private static final ThingTypeUID THING_TYPE_RAIN = new ThingTypeUID(BINDING_ID, "rain");
+    private static final ThingTypeUID THING_TYPE_RAW = new ThingTypeUID(BINDING_ID, "raw");
     private static final ThingTypeUID THING_TYPE_REMOTE_CONTROL = new ThingTypeUID(BINDING_ID, "remotecontrol");
     private static final ThingTypeUID THING_TYPE_RFX_METER = new ThingTypeUID(BINDING_ID, "rfxmeter");
     private static final ThingTypeUID THING_TYPE_RFX_SENSOR = new ThingTypeUID(BINDING_ID, "rfxsensor");
@@ -171,19 +172,20 @@ public class RFXComBindingConstants {
     /**
      * Presents all supported Thing types by RFXCOM binding.
      */
-    public static final Set<ThingTypeUID> SUPPORTED_DEVICE_THING_TYPES_UIDS = Collections.unmodifiableSet(Stream.of(
-            THING_TYPE_BAROMETRIC, THING_TYPE_BBQ_TEMPERATURE, THING_TYPE_BLINDS1, THING_TYPE_CAMERA1, THING_TYPE_CHIME,
-            THING_TYPE_CURRENT, THING_TYPE_CURRENT_ENERGY, THING_TYPE_CURTAIN1, THING_TYPE_DATE_TIME, THING_TYPE_ENERGY,
-            THING_TYPE_FAN, THING_TYPE_FAN_SF01, THING_TYPE_FAN_ITHO, THING_TYPE_FAN_SEAV, THING_TYPE_FAN_LUCCI_DC,
-            THING_TYPE_FAN_FT1211R, THING_TYPE_FAN_FALMEC, THING_TYPE_FAN_LUCCI_DC_II, THING_TYPE_GAS_USAGE,
-            THING_TYPE_HOME_CONFORT, THING_TYPE_HUMIDITY, THING_TYPE_IO_LINES, THING_TYPE_LIGHTNING1,
-            THING_TYPE_LIGHTNING2, THING_TYPE_LIGHTNING3, THING_TYPE_LIGHTNING4, THING_TYPE_LIGHTNING5,
-            THING_TYPE_LIGHTNING6, THING_TYPE_POWER, THING_TYPE_RADIATOR1, THING_TYPE_RAIN, THING_TYPE_REMOTE_CONTROL,
-            THING_TYPE_RFX_METER, THING_TYPE_RFX_SENSOR, THING_TYPE_RFY, THING_TYPE_SECURITY1, THING_TYPE_SECURITY2,
-            THING_TYPE_TEMPERATURE, THING_TYPE_TEMPERATURE_HUMIDITY, THING_TYPE_TEMPERATURE_HUMIDITY_BAROMETRIC,
-            THING_TYPE_TEMPERATURE_RAIN, THING_TYPE_THERMOSTAT1, THING_TYPE_THERMOSTAT2, THING_TYPE_THERMOSTAT3,
-            THING_TYPE_UNDECODED, THING_TYPE_UV, THING_TYPE_WATER_USAGE, THING_TYPE_WEIGHTING_SCALE, THING_TYPE_WIND)
-            .collect(Collectors.toSet()));
+    public static final Set<ThingTypeUID> SUPPORTED_DEVICE_THING_TYPES_UIDS = Collections
+            .unmodifiableSet(Stream.of(THING_TYPE_BAROMETRIC, THING_TYPE_BBQ_TEMPERATURE, THING_TYPE_BLINDS1,
+                    THING_TYPE_CAMERA1, THING_TYPE_CHIME, THING_TYPE_CURRENT, THING_TYPE_CURRENT_ENERGY,
+                    THING_TYPE_CURTAIN1, THING_TYPE_DATE_TIME, THING_TYPE_ENERGY, THING_TYPE_FAN, THING_TYPE_FAN_SF01,
+                    THING_TYPE_FAN_ITHO, THING_TYPE_FAN_SEAV, THING_TYPE_FAN_LUCCI_DC, THING_TYPE_FAN_FT1211R,
+                    THING_TYPE_FAN_FALMEC, THING_TYPE_FAN_LUCCI_DC_II, THING_TYPE_GAS_USAGE, THING_TYPE_HOME_CONFORT,
+                    THING_TYPE_HUMIDITY, THING_TYPE_IO_LINES, THING_TYPE_LIGHTNING1, THING_TYPE_LIGHTNING2,
+                    THING_TYPE_LIGHTNING3, THING_TYPE_LIGHTNING4, THING_TYPE_LIGHTNING5, THING_TYPE_LIGHTNING6,
+                    THING_TYPE_POWER, THING_TYPE_RADIATOR1, THING_TYPE_RAIN, THING_TYPE_RAW, THING_TYPE_REMOTE_CONTROL,
+                    THING_TYPE_RFX_METER, THING_TYPE_RFX_SENSOR, THING_TYPE_RFY, THING_TYPE_SECURITY1,
+                    THING_TYPE_SECURITY2, THING_TYPE_TEMPERATURE, THING_TYPE_TEMPERATURE_HUMIDITY,
+                    THING_TYPE_TEMPERATURE_HUMIDITY_BAROMETRIC, THING_TYPE_TEMPERATURE_RAIN, THING_TYPE_THERMOSTAT1,
+                    THING_TYPE_THERMOSTAT2, THING_TYPE_THERMOSTAT3, THING_TYPE_UNDECODED, THING_TYPE_UV,
+                    THING_TYPE_WATER_USAGE, THING_TYPE_WEIGHTING_SCALE, THING_TYPE_WIND).collect(Collectors.toSet()));
 
     /**
      * Map RFXCOM packet types to RFXCOM Thing types and vice versa.
@@ -223,6 +225,7 @@ public class RFXComBindingConstants {
                     put(PacketType.POWER, RFXComBindingConstants.THING_TYPE_POWER);
                     put(PacketType.RADIATOR1, RFXComBindingConstants.THING_TYPE_RADIATOR1);
                     put(PacketType.RAIN, RFXComBindingConstants.THING_TYPE_RAIN);
+                    put(PacketType.RAW, RFXComBindingConstants.THING_TYPE_RAW);
                     put(PacketType.REMOTE_CONTROL, RFXComBindingConstants.THING_TYPE_REMOTE_CONTROL);
                     put(PacketType.RFXMETER, RFXComBindingConstants.THING_TYPE_RFX_METER);
                     put(PacketType.RFXSENSOR, RFXComBindingConstants.THING_TYPE_RFX_SENSOR);
index dd54535c552a5597fda87a980c904c20741ea768..1f49b97f339b93ddad5f12db77857035d8ff1102 100644 (file)
@@ -83,6 +83,7 @@ public abstract class RFXComBaseMessage implements RFXComMessage {
         RFXSENSOR(112),
         RFXMETER(113),
         FS20(114),
+        RAW(127),
         IO_LINES(128);
 
         private final int packetType;
@@ -163,7 +164,7 @@ public abstract class RFXComBaseMessage implements RFXComMessage {
         }
 
         str += ", Packet type = " + packetType;
-        str += ", Seq number = " + (short) (seqNbr & 0xFF);
+        str += ", Seq number = " + Byte.toUnsignedInt(seqNbr);
 
         return str;
     }
index 4c759a17166e849a06a57b4230d721cccfae4999..0a3ec7d47bea66bc5828d57a09c0794341d108f2 100644 (file)
@@ -84,6 +84,7 @@ public class RFXComMessageFactory {
                     put(PacketType.RFXSENSOR, RFXComRFXSensorMessage.class);
                     // put(PacketType.RFXMETER, RFXComRFXMeterMessage.class);
                     // put(PacketType.FS20, RFXComFS20Message.class);
+                    put(PacketType.RAW, RFXComRawMessage.class);
                     // put(PacketType.IO_LINES, RFXComIOLinesMessage.class);
                 }
             });
diff --git a/bundles/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComRawMessage.java b/bundles/org.openhab.binding.rfxcom/src/main/java/org/openhab/binding/rfxcom/internal/messages/RFXComRawMessage.java
new file mode 100644 (file)
index 0000000..c4f1ed5
--- /dev/null
@@ -0,0 +1,184 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.rfxcom.internal.messages;
+
+import static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*;
+import static org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType.RAW;
+
+import java.nio.ByteBuffer;
+
+import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
+import org.openhab.binding.rfxcom.internal.exceptions.RFXComMessageTooLongException;
+import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
+import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
+import org.openhab.binding.rfxcom.internal.handler.DeviceState;
+import org.openhab.core.library.types.StringType;
+import org.openhab.core.types.State;
+import org.openhab.core.types.Type;
+import org.openhab.core.util.HexUtils;
+
+/**
+ * RFXCOM data class for raw messages.
+ *
+ * @author James Hewitt-Thomas - New addition to the PRO RFXCom firmware
+ */
+public class RFXComRawMessage extends RFXComDeviceMessageImpl<RFXComRawMessage.SubType> {
+
+    public enum SubType implements ByteEnumWrapper {
+        RAW_PACKET1(0x00),
+        RAW_PACKET2(0x01),
+        RAW_PACKET3(0x02),
+        RAW_PACKET4(0x03),
+
+        UNKNOWN(0xFF);
+
+        private final int subType;
+
+        SubType(int subType) {
+            this.subType = subType;
+        }
+
+        @Override
+        public byte toByte() {
+            return (byte) subType;
+        }
+
+        public static SubType fromByte(int input) {
+            for (SubType c : SubType.values()) {
+                if (c.subType == input) {
+                    return c;
+                }
+            }
+
+            return SubType.UNKNOWN;
+        }
+    }
+
+    public SubType subType;
+    public byte repeat;
+    public short[] pulses;
+
+    public RFXComRawMessage() {
+        super(RAW);
+        pulses = new short[0];
+    }
+
+    public RFXComRawMessage(byte[] message) throws RFXComException {
+        encodeMessage(message);
+    }
+
+    @Override
+    public String toString() {
+        String str = super.toString();
+
+        str += ", Sub type = " + subType;
+
+        return str;
+    }
+
+    @Override
+    public void encodeMessage(byte[] message) throws RFXComException {
+        super.encodeMessage(message);
+
+        final int pulsesByteLen = rawMessage.length - 5;
+        if (pulsesByteLen % 4 != 0) {
+            throw new RFXComException("Incorrect byte length for pulses - must be divisible by 4");
+        }
+
+        subType = SubType.fromByte(super.subType);
+        repeat = rawMessage[4];
+        pulses = new short[pulsesByteLen / 2];
+        ByteBuffer.wrap(rawMessage, 5, rawMessage.length - 5).asShortBuffer().get(pulses);
+    }
+
+    @Override
+    public byte[] decodeMessage() throws RFXComException {
+        if (pulses.length > 124) {
+            throw new RFXComMessageTooLongException("Longest payload according to RFXtrx SDK is 124 shorts.");
+        }
+
+        final int pulsesByteLen = pulses.length * 2;
+        byte[] data = new byte[5 + pulsesByteLen];
+
+        data[0] = (byte) (data.length - 1);
+        data[1] = RAW.toByte();
+        data[2] = subType.toByte();
+        data[3] = seqNbr;
+        data[4] = repeat;
+
+        ByteBuffer.wrap(data, 5, pulsesByteLen).asShortBuffer().put(pulses);
+
+        return data;
+    }
+
+    @Override
+    public String getDeviceId() {
+        return "RAW";
+    }
+
+    @Override
+    public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
+        switch (channelId) {
+            case CHANNEL_RAW_MESSAGE:
+                return new StringType(HexUtils.bytesToHex(rawMessage));
+
+            case CHANNEL_RAW_PAYLOAD:
+                byte[] payload = new byte[pulses.length * 2];
+                ByteBuffer.wrap(payload).asShortBuffer().put(pulses);
+                return new StringType(HexUtils.bytesToHex(payload));
+
+            default:
+                throw new RFXComUnsupportedChannelException("Nothing relevant for " + channelId);
+        }
+    }
+
+    @Override
+    public void setSubType(SubType subType) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void setDeviceId(String deviceId) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
+        switch (channelId) {
+            case CHANNEL_RAW_MESSAGE:
+                if (type instanceof StringType) {
+                    // TODO: Check the raw message for validity (length, no more than 124 shorts, multiple of 4 bytes in
+                    // payload)
+                    throw new RFXComUnsupportedChannelException("Channel " + channelId + " inot yet implemented");
+                } else {
+                    throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
+                }
+
+            case CHANNEL_RAW_PAYLOAD:
+                if (type instanceof StringType) {
+                    // TODO: Check the payload for validity (no more than 124 shorts, multiple of 4 bytes
+                    throw new RFXComUnsupportedChannelException("Channel " + channelId + " not yet implemented");
+                } else {
+                    throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
+                }
+
+            default:
+                throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
+        }
+    }
+
+    @Override
+    public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
+        return ByteEnumUtil.convertSubType(SubType.class, subType);
+    }
+}
index 30af6f83af3013a4028df021d30a388c61f20877..3707b8d7f50790d2cbe5e70dcf25ee3ade86612a 100644 (file)
@@ -9,13 +9,13 @@
        <channel-type id="rawmessage">
                <item-type>String</item-type>
                <label>Raw Message</label>
-               <description>Hexadecimal representation of undecoded RFXCOM messages including header and payload</description>
+               <description>Hexadecimal representation of RFXCOM messages including header and payload</description>
        </channel-type>
 
        <channel-type id="rawpayload">
                <item-type>String</item-type>
                <label>Raw Payload</label>
-               <description>Hexadecimal representation of payload of undecoded RFXCOM messages</description>
+               <description>Hexadecimal representation of payload of raw and undecoded RFXCOM messages</description>
        </channel-type>
 
        <channel-type id="command">
diff --git a/bundles/org.openhab.binding.rfxcom/src/main/resources/OH-INF/thing/raw.xml b/bundles/org.openhab.binding.rfxcom/src/main/resources/OH-INF/thing/raw.xml
new file mode 100644 (file)
index 0000000..52618f3
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="rfxcom"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
+
+       <thing-type id="raw">
+               <supported-bridge-type-refs>
+                       <bridge-type-ref id="bridge"/>
+                       <bridge-type-ref id="tcpbridge"/>
+                       <bridge-type-ref id="RFXtrx433"/>
+                       <bridge-type-ref id="RFXrec433"/>
+               </supported-bridge-type-refs>
+
+               <label>RFXCOM Raw Messages</label>
+               <description>Raw messages.</description>
+
+               <channels>
+                       <channel id="rawMessage" typeId="rawmessage"/>
+                       <channel id="rawPayload" typeId="rawpayload"/>
+               </channels>
+
+               <config-description>
+                       <parameter name="deviceId" type="text" required="true">
+                               <label>Device Id</label>
+                               <description>Raw items cannot provide a device ID, so this value is always RAW.</description>
+                       </parameter>
+                       <parameter name="subType" type="text" required="true">
+                               <label>Sub Type</label>
+                               <description>Specifies device sub type.</description>
+                               <options>
+                                       <option value="RAW_PACKET1">RAW_PACKET1</option>
+                                       <option value="RAW_PACKET2">RAW_PACKET2</option>
+                                       <option value="RAW_PACKET3">RAW_PACKET3</option>
+                                       <option value="RAW_PACKET4">RAW_PACKET4</option>
+                               </options>
+                       </parameter>
+               </config-description>
+       </thing-type>
+
+</thing:thing-descriptions>
diff --git a/bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComRawMessageTest.java b/bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComRawMessageTest.java
new file mode 100644 (file)
index 0000000..f3baebb
--- /dev/null
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.rfxcom.internal.messages;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.nio.ByteBuffer;
+
+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.exceptions.RFXComMessageTooLongException;
+import org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType;
+import org.openhab.core.util.HexUtils;
+
+/**
+ * Test for RFXCom-binding
+ *
+ * @author James Hewitt-Thomas - New addition to the PRO RFXCom firmware
+ */
+@NonNullByDefault
+public class RFXComRawMessageTest {
+
+    private void testMessage(String hexMsg, RFXComRawMessage.SubType subType, int seqNbr, int repeat, String pulses)
+            throws RFXComException {
+        final RFXComRawMessage msg = (RFXComRawMessage) RFXComMessageFactory.createMessage(HexUtils.hexToBytes(hexMsg));
+        assertEquals(subType, msg.subType, "SubType");
+        assertEquals(seqNbr, (short) (msg.seqNbr & 0xFF), "Seq Number");
+        assertEquals("RAW", msg.getDeviceId(), "Device Id");
+        assertEquals(repeat, msg.repeat, "Repeat");
+        byte[] payload = new byte[msg.pulses.length * 2];
+        ByteBuffer.wrap(payload).asShortBuffer().put(msg.pulses);
+        assertEquals(pulses, HexUtils.bytesToHex(payload), "Pulses");
+
+        byte[] decoded = msg.decodeMessage();
+
+        assertEquals(hexMsg, HexUtils.bytesToHex(decoded), "Message converted back");
+    }
+
+    @Test
+    public void testSomeMessages() throws RFXComException {
+        testMessage("087F0027051356ECC0", RFXComRawMessage.SubType.RAW_PACKET1, 0x27, 5, "1356ECC0");
+    }
+
+    @Test
+    public void testLongMessage() throws RFXComException {
+        RFXComRawMessage msg = (RFXComRawMessage) RFXComMessageFactory.createMessage(PacketType.RAW);
+        msg.subType = RFXComRawMessage.SubType.RAW_PACKET1;
+        msg.seqNbr = 1;
+        msg.repeat = 5;
+        msg.pulses = new short[125];
+
+        assertThrows(RFXComMessageTooLongException.class, () -> msg.decodeMessage());
+    }
+}