2 * Copyright (c) 2010-2023 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.enocean.internal.messages;
15 import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.ZERO;
17 import java.security.InvalidParameterException;
18 import java.util.Arrays;
20 import org.openhab.binding.enocean.internal.EnOceanException;
21 import org.openhab.binding.enocean.internal.messages.BasePacket.ESPPacketType;
22 import org.openhab.binding.enocean.internal.messages.ERP1Message.RORG;
26 * @author Daniel Weber - Initial contribution
28 public class ESP2Packet {
30 public static final byte ENOCEAN_ESP2_FIRSTSYNC_BYTE = (byte) 0xA5;
31 public static final byte ENOCEAN_ESP2_SECONDSYNC_BYTE = 0x5A;
33 private static final int ESP2_SYNC_BYTE_LENGTH = 2;
34 private static final int ESP2_HEADER_LENGTH = 1;
35 private static final int ESP2_DATA_LENGTH = 4;
36 private static final int ESP2_SENDERID_LENGTH = 4;
37 private static final int ESP2_STATUS_LENGTH = 1;
38 private static final int ESP2_CHECKSUM_LENGTH = 1;
40 public static final int ESP2_ORG_LENGTH = 1;
42 public static final int ESP_PACKET_LENGTH = ESP2_ORG_LENGTH + ESP2_DATA_LENGTH + ESP2_SENDERID_LENGTH
43 + ESP2_STATUS_LENGTH + ESP2_CHECKSUM_LENGTH;
53 private ORG(byte value) {
57 public static ORG getORG(byte org) {
58 for (ORG o : ORG.values()) {
68 public enum ESP2Response {
73 INF_IDBase((byte) 0x98),
74 INF_RX_SENSITIVITY((byte) 0x88),
75 INF_MODEM_STATUS((byte) 0xA8),
76 INF_SW_VERSION((byte) 0x8C),
77 ERR_MODEM_NOTWANTEDACK((byte) 0x28),
78 ERR_MODEM_NOTACK((byte) 0x29),
79 ERR_MODEM_DUP_ID((byte) 0x0C),
80 ERR_SYNTAX_HSEQ((byte) 0x08),
81 ERR_SYNTAX_LENGTH((byte) 0x09),
82 ERR_SYNTAX_CHECKSUM((byte) 0x0A),
83 ERR_SYNTAX_ORG((byte) 0x0B),
84 ERR_TX_IDRANGE((byte) 0x22),
85 ERR_IDRANGE((byte) 0x1A);
89 private ESP2Response(byte value) {
93 public static ESP2Response getResponse(byte response) {
94 for (ESP2Response p : ESP2Response.values()) {
95 if (p.value == response) {
104 public enum ESP2PacketType {
105 Receive_Radio_Telegram((byte) 0x00),
106 Transmit_Radio_Telegram((byte) 0x03),
107 Receive_Message_Telegram((byte) 0x04),
108 Transmit_Command_Telegram((byte) 0x05);
112 private ESP2PacketType(byte value) {
116 public static ESP2PacketType getPacketType(byte packetType) {
117 for (ESP2PacketType p : ESP2PacketType.values()) {
118 if (p.value == packetType) {
123 throw new InvalidParameterException("Unknown ESP2 PacketType value");
127 protected BasePacket basePacket;
129 public ESP2Packet(BasePacket basePacket) {
130 this.basePacket = basePacket;
133 private ESP2PacketType convertToESP2PacketType(ESPPacketType espPacketType) {
134 switch (espPacketType) {
136 return ESP2PacketType.Transmit_Command_Telegram;
139 return ESP2PacketType.Transmit_Radio_Telegram;
140 case RESPONSE: // Response is not intended for outbound data (at least for ESP2)
142 throw new IllegalArgumentException("ESPPacketType not supported");
146 private byte convertToESP2ORG(RORG esp3RORG) {
149 return ORG._RPS.value;
151 return ORG._1BS.value;
153 return ORG._4BS.value;
155 throw new InvalidParameterException("RORG is not supported by ESP2");
159 private byte[] getOrgAndDataBytes(BasePacket basePacket) {
160 byte[] data = new byte[ESP2_ORG_LENGTH + ESP2_DATA_LENGTH];
161 Arrays.fill(data, ZERO);
163 if (basePacket.getPacketType() == ESPPacketType.RADIO_ERP1) {
164 ERP1Message message = (ERP1Message) basePacket;
165 data[0] = convertToESP2ORG(message.getRORG());
166 System.arraycopy(message.getPayload(ESP2_ORG_LENGTH, message.getRORG().getDataLength()), 0, data,
167 ESP2_ORG_LENGTH, message.getRORG().getDataLength());
168 } else if (basePacket.getPacketType() == ESPPacketType.COMMON_COMMAND) {
169 CCMessage message = (CCMessage) basePacket;
170 switch (message.getCCMessageType()) {
179 System.arraycopy(message.getPayload(ESP2_ORG_LENGTH, 4), 0, data, ESP2_ORG_LENGTH, 4);
182 throw new InvalidParameterException("CCMessage is not supported by ESP2");
189 private byte[] getSenderId(BasePacket basePacket) {
190 byte[] data = new byte[4];
191 Arrays.fill(data, ZERO);
193 if (basePacket.getPacketType() == ESPPacketType.RADIO_ERP1) {
194 ERP1Message message = (ERP1Message) basePacket;
195 data = message.getSenderId();
201 private byte getStatus(BasePacket basePacket) {
202 if (basePacket.getPacketType() == ESPPacketType.RADIO_ERP1) {
203 ERP1Message message = (ERP1Message) basePacket;
204 return message.getPayload(ESP2_ORG_LENGTH + message.getRORG().getDataLength() + ESP2_SENDERID_LENGTH,
205 ESP2_STATUS_LENGTH)[0];
211 private byte calcCheckSum(byte data[], int offset, int length) {
213 for (int i = 0; i < length; i++) {
214 checkSum += (data[offset + i] & 0xff);
217 return (byte) (checkSum & 0xff);
220 public byte[] serialize() throws EnOceanException {
222 byte[] result = new byte[ESP2_SYNC_BYTE_LENGTH + ESP2_HEADER_LENGTH + ESP2_ORG_LENGTH + ESP2_DATA_LENGTH
223 + ESP2_SENDERID_LENGTH + ESP2_STATUS_LENGTH + ESP2_CHECKSUM_LENGTH];
224 Arrays.fill(result, ZERO);
226 result[0] = ENOCEAN_ESP2_FIRSTSYNC_BYTE;
227 result[1] = ENOCEAN_ESP2_SECONDSYNC_BYTE;
228 result[2] = (byte) (((convertToESP2PacketType(basePacket.getPacketType()).value << 5) + (ESP_PACKET_LENGTH))
231 System.arraycopy(getOrgAndDataBytes(basePacket), 0, result, ESP2_SYNC_BYTE_LENGTH + ESP2_HEADER_LENGTH,
232 ESP2_ORG_LENGTH + ESP2_DATA_LENGTH);
234 System.arraycopy(getSenderId(basePacket), 0, result,
235 ESP2_SYNC_BYTE_LENGTH + ESP2_HEADER_LENGTH + ESP2_ORG_LENGTH + ESP2_DATA_LENGTH,
236 ESP2_SENDERID_LENGTH);
238 result[ESP2_SYNC_BYTE_LENGTH + ESP2_HEADER_LENGTH + ESP2_ORG_LENGTH + ESP2_DATA_LENGTH
239 + ESP2_SENDERID_LENGTH] = getStatus(basePacket);
241 result[ESP2_SYNC_BYTE_LENGTH + ESP2_HEADER_LENGTH + ESP2_ORG_LENGTH + ESP2_DATA_LENGTH
242 + ESP2_SENDERID_LENGTH + ESP2_STATUS_LENGTH] = calcCheckSum(result, ESP2_SYNC_BYTE_LENGTH,
243 ESP2_HEADER_LENGTH + ESP2_ORG_LENGTH + ESP2_DATA_LENGTH + ESP2_SENDERID_LENGTH
244 + ESP2_STATUS_LENGTH);
247 } catch (Exception e) {
248 throw new EnOceanException(e.getMessage());
252 public static boolean validateCheckSum(byte data[], int length, byte checkSum) {
254 for (int i = 0; i < length; i++) {
255 sum += (data[i] & 0xff);
258 return (sum & 0xff) == (checkSum & 0xff);