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.RFXComBindingConstants.*;
16 import static org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType.RAW;
18 import java.nio.ByteBuffer;
20 import org.openhab.binding.rfxcom.internal.exceptions.RFXComException;
21 import org.openhab.binding.rfxcom.internal.exceptions.RFXComMessageTooLongException;
22 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException;
23 import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException;
24 import org.openhab.binding.rfxcom.internal.handler.DeviceState;
25 import org.openhab.core.library.types.StringType;
26 import org.openhab.core.types.State;
27 import org.openhab.core.types.Type;
28 import org.openhab.core.util.HexUtils;
31 * RFXCOM data class for raw messages.
33 * @author James Hewitt-Thomas - New addition to the PRO RFXCom firmware
35 public class RFXComRawMessage extends RFXComDeviceMessageImpl<RFXComRawMessage.SubType> {
37 public enum SubType implements ByteEnumWrapper {
45 private final int subType;
47 SubType(int subType) {
48 this.subType = subType;
52 public byte toByte() {
53 return (byte) subType;
56 public static SubType fromByte(int input) {
57 for (SubType c : SubType.values()) {
58 if (c.subType == input) {
63 return SubType.UNKNOWN;
67 public SubType subType;
69 public short[] pulses;
71 public RFXComRawMessage() {
73 pulses = new short[0];
76 public RFXComRawMessage(byte[] message) throws RFXComException {
77 encodeMessage(message);
81 public String toString() {
82 String str = super.toString();
84 str += ", Sub type = " + subType;
90 public void encodeMessage(byte[] message) throws RFXComException {
91 super.encodeMessage(message);
93 final int pulsesByteLen = rawMessage.length - 5;
94 if (pulsesByteLen % 4 != 0) {
95 throw new RFXComException("Incorrect byte length for pulses - must be divisible by 4");
98 subType = SubType.fromByte(super.subType);
99 repeat = rawMessage[4];
100 pulses = new short[pulsesByteLen / 2];
101 ByteBuffer.wrap(rawMessage, 5, rawMessage.length - 5).asShortBuffer().get(pulses);
105 public byte[] decodeMessage() throws RFXComException {
106 if (pulses.length > 124) {
107 throw new RFXComMessageTooLongException("Longest payload according to RFXtrx SDK is 124 shorts.");
110 final int pulsesByteLen = pulses.length * 2;
111 byte[] data = new byte[5 + pulsesByteLen];
113 data[0] = (byte) (data.length - 1);
114 data[1] = RAW.toByte();
115 data[2] = subType.toByte();
119 ByteBuffer.wrap(data, 5, pulsesByteLen).asShortBuffer().put(pulses);
125 public String getDeviceId() {
130 public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
132 case CHANNEL_RAW_MESSAGE:
133 return new StringType(HexUtils.bytesToHex(rawMessage));
135 case CHANNEL_RAW_PAYLOAD:
136 byte[] payload = new byte[pulses.length * 2];
137 ByteBuffer.wrap(payload).asShortBuffer().put(pulses);
138 return new StringType(HexUtils.bytesToHex(payload));
141 throw new RFXComUnsupportedChannelException("Nothing relevant for " + channelId);
146 public void setSubType(SubType subType) {
147 throw new UnsupportedOperationException();
151 public void setDeviceId(String deviceId) {
152 throw new UnsupportedOperationException();
156 public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
158 case CHANNEL_RAW_MESSAGE:
159 if (type instanceof StringType) {
160 // TODO: Check the raw message for validity (length, no more than 124 shorts, multiple of 4 bytes in
162 throw new RFXComUnsupportedChannelException("Channel " + channelId + " inot yet implemented");
164 throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
167 case CHANNEL_RAW_PAYLOAD:
168 if (type instanceof StringType) {
169 // TODO: Check the payload for validity (no more than 124 shorts, multiple of 4 bytes
170 throw new RFXComUnsupportedChannelException("Channel " + channelId + " not yet implemented");
172 throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
176 throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
181 public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
182 return ByteEnumUtil.convertSubType(SubType.class, subType);