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.transceiver;
15 import java.io.IOException;
16 import java.util.Arrays;
17 import java.util.concurrent.ScheduledExecutorService;
19 import org.openhab.binding.enocean.internal.EnOceanException;
20 import org.openhab.binding.enocean.internal.messages.BasePacket;
21 import org.openhab.binding.enocean.internal.messages.ESP3Packet;
22 import org.openhab.binding.enocean.internal.messages.ESP3PacketFactory;
23 import org.openhab.binding.enocean.internal.messages.Response;
24 import org.openhab.core.io.transport.serial.SerialPortManager;
25 import org.openhab.core.util.HexUtils;
29 * @author Daniel Weber - Initial contribution
31 public class EnOceanESP3Transceiver extends EnOceanTransceiver {
33 public EnOceanESP3Transceiver(String path, TransceiverErrorListener errorListener,
34 ScheduledExecutorService scheduler, SerialPortManager serialPortManager) {
35 super(path, errorListener, scheduler, serialPortManager);
44 byte[] dataBuffer = new byte[ENOCEAN_MAX_DATA];
45 ReadingState state = ReadingState.WaitingForSyncByte;
46 int currentPosition = 0;
48 int optionalLength = -1;
52 protected void processMessage(byte firstByte) {
53 byte[] readingBuffer = new byte[ENOCEAN_MAX_DATA];
58 readingBuffer[0] = firstByte;
60 bytesRead = this.inputStream.read(readingBuffer, 1, inputStream.available());
61 if (bytesRead == -1) {
62 throw new IOException("could not read from inputstream");
65 if (readingTask == null || readingTask.isCancelled()) {
70 for (int p = 0; p < bytesRead; p++) {
71 _byte = readingBuffer[p];
74 case WaitingForSyncByte:
75 if (_byte == ESP3Packet.ESP3_SYNC_BYTE) {
76 state = ReadingState.ReadingHeader;
77 logger.trace("Received Sync Byte");
81 if (currentPosition == ESP3Packet.ESP3_HEADER_LENGTH) {
82 if (ESP3Packet.checkCRC8(dataBuffer, ESP3Packet.ESP3_HEADER_LENGTH, _byte)
83 && ((dataBuffer[0] & 0xFF) << 8) + (dataBuffer[1] & 0xFF)
84 + (dataBuffer[2] & 0xFF) > 0) {
85 state = ReadingState.ReadingData;
87 dataLength = ((dataBuffer[0] & 0xFF << 8) | (dataBuffer[1] & 0xFF));
88 optionalLength = dataBuffer[2] & 0xFF;
89 packetType = dataBuffer[3];
92 if (packetType == 3) {
93 logger.trace("Received sub_msg");
96 logger.trace(">> Received header, data length {} optional length {} packet type {}",
97 dataLength, optionalLength, packetType);
99 // check if we find a sync byte in current buffer
101 for (int i = 0; i < ESP3Packet.ESP3_HEADER_LENGTH; i++) {
102 if (dataBuffer[i] == ESP3Packet.ESP3_SYNC_BYTE) {
108 if (copyFrom != -1) {
109 System.arraycopy(dataBuffer, copyFrom, dataBuffer, 0,
110 ESP3Packet.ESP3_HEADER_LENGTH - copyFrom);
111 state = ReadingState.ReadingHeader;
112 currentPosition = ESP3Packet.ESP3_HEADER_LENGTH - copyFrom;
113 dataBuffer[currentPosition++] = _byte;
116 state = _byte == ESP3Packet.ESP3_SYNC_BYTE ? ReadingState.ReadingHeader
117 : ReadingState.WaitingForSyncByte;
119 logger.trace("CrC8 header check not successful");
122 dataBuffer[currentPosition++] = _byte;
126 if (currentPosition == dataLength + optionalLength) {
127 if (ESP3Packet.checkCRC8(dataBuffer, dataLength + optionalLength, _byte)) {
128 state = ReadingState.WaitingForSyncByte;
129 BasePacket packet = ESP3PacketFactory.BuildPacket(dataLength, optionalLength,
130 packetType, dataBuffer);
132 if (packet != null) {
133 switch (packet.getPacketType()) {
135 logger.debug("Common command: {}",
136 HexUtils.bytesToHex(packet.getPayload()));
140 informListeners(packet);
148 case REMOTE_MAN_COMMAND:
151 Response response = (Response) packet;
152 logger.debug("{} with code {} payload {} received",
153 packet.getPacketType().name(), response.getResponseType().name(),
154 HexUtils.bytesToHex(packet.getPayload())); // Responses do not have
156 handleResponse(response);
159 case SMART_ACK_COMMAND:
165 logger.trace("Unknown ESP3Packet: {}", HexUtils
166 .bytesToHex(Arrays.copyOf(dataBuffer, dataLength + optionalLength)));
169 state = _byte == ESP3Packet.ESP3_SYNC_BYTE ? ReadingState.ReadingHeader
170 : ReadingState.WaitingForSyncByte;
171 logger.trace("ESP3Packet malformed: {}",
172 HexUtils.bytesToHex(Arrays.copyOf(dataBuffer, dataLength + optionalLength)));
176 dataLength = optionalLength = packetType = -1;
178 dataBuffer[currentPosition++] = _byte;
183 } catch (IOException ioexception) {
184 errorListener.ErrorOccured(ioexception);
190 protected byte[] serializePacket(BasePacket packet) throws EnOceanException {
191 return new ESP3Packet(packet).serialize();