]> git.basschouten.com Git - openhab-addons.git/blob
c4f1ed56129c131d086c5e40d9b26cc0edcd4c9d
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.RFXComBindingConstants.*;
16 import static org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType.RAW;
17
18 import java.nio.ByteBuffer;
19
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;
29
30 /**
31  * RFXCOM data class for raw messages.
32  *
33  * @author James Hewitt-Thomas - New addition to the PRO RFXCom firmware
34  */
35 public class RFXComRawMessage extends RFXComDeviceMessageImpl<RFXComRawMessage.SubType> {
36
37     public enum SubType implements ByteEnumWrapper {
38         RAW_PACKET1(0x00),
39         RAW_PACKET2(0x01),
40         RAW_PACKET3(0x02),
41         RAW_PACKET4(0x03),
42
43         UNKNOWN(0xFF);
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         public static SubType fromByte(int input) {
57             for (SubType c : SubType.values()) {
58                 if (c.subType == input) {
59                     return c;
60                 }
61             }
62
63             return SubType.UNKNOWN;
64         }
65     }
66
67     public SubType subType;
68     public byte repeat;
69     public short[] pulses;
70
71     public RFXComRawMessage() {
72         super(RAW);
73         pulses = new short[0];
74     }
75
76     public RFXComRawMessage(byte[] message) throws RFXComException {
77         encodeMessage(message);
78     }
79
80     @Override
81     public String toString() {
82         String str = super.toString();
83
84         str += ", Sub type = " + subType;
85
86         return str;
87     }
88
89     @Override
90     public void encodeMessage(byte[] message) throws RFXComException {
91         super.encodeMessage(message);
92
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");
96         }
97
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);
102     }
103
104     @Override
105     public byte[] decodeMessage() throws RFXComException {
106         if (pulses.length > 124) {
107             throw new RFXComMessageTooLongException("Longest payload according to RFXtrx SDK is 124 shorts.");
108         }
109
110         final int pulsesByteLen = pulses.length * 2;
111         byte[] data = new byte[5 + pulsesByteLen];
112
113         data[0] = (byte) (data.length - 1);
114         data[1] = RAW.toByte();
115         data[2] = subType.toByte();
116         data[3] = seqNbr;
117         data[4] = repeat;
118
119         ByteBuffer.wrap(data, 5, pulsesByteLen).asShortBuffer().put(pulses);
120
121         return data;
122     }
123
124     @Override
125     public String getDeviceId() {
126         return "RAW";
127     }
128
129     @Override
130     public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException {
131         switch (channelId) {
132             case CHANNEL_RAW_MESSAGE:
133                 return new StringType(HexUtils.bytesToHex(rawMessage));
134
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));
139
140             default:
141                 throw new RFXComUnsupportedChannelException("Nothing relevant for " + channelId);
142         }
143     }
144
145     @Override
146     public void setSubType(SubType subType) {
147         throw new UnsupportedOperationException();
148     }
149
150     @Override
151     public void setDeviceId(String deviceId) {
152         throw new UnsupportedOperationException();
153     }
154
155     @Override
156     public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException {
157         switch (channelId) {
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
161                     // payload)
162                     throw new RFXComUnsupportedChannelException("Channel " + channelId + " inot yet implemented");
163                 } else {
164                     throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
165                 }
166
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");
171                 } else {
172                     throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type);
173                 }
174
175             default:
176                 throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here");
177         }
178     }
179
180     @Override
181     public SubType convertSubType(String subType) throws RFXComUnsupportedValueException {
182         return ByteEnumUtil.convertSubType(SubType.class, subType);
183     }
184 }