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.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.ERP1Message;
22 import org.openhab.binding.enocean.internal.messages.ERP1Message.RORG;
23 import org.openhab.binding.enocean.internal.messages.ESP3Packet;
24 import org.openhab.binding.enocean.internal.messages.ESP3PacketFactory;
25 import org.openhab.binding.enocean.internal.messages.Response;
26 import org.openhab.core.io.transport.serial.SerialPortManager;
27 import org.openhab.core.util.HexUtils;
31 * @author Daniel Weber - Initial contribution
33 public class EnOceanESP3Transceiver extends EnOceanTransceiver {
35 public EnOceanESP3Transceiver(String path, TransceiverErrorListener errorListener,
36 ScheduledExecutorService scheduler, SerialPortManager serialPortManager) {
37 super(path, errorListener, scheduler, serialPortManager);
46 byte[] dataBuffer = new byte[ENOCEAN_MAX_DATA];
47 ReadingState state = ReadingState.WaitingForSyncByte;
48 int currentPosition = 0;
50 int optionalLength = -1;
54 protected void processMessage(byte firstByte) {
55 byte[] readingBuffer = new byte[ENOCEAN_MAX_DATA];
60 readingBuffer[0] = firstByte;
62 bytesRead = this.inputStream.read(readingBuffer, 1, inputStream.available());
63 if (bytesRead == -1) {
64 throw new IOException("could not read from inputstream");
67 if (readingTask == null || readingTask.isCancelled()) {
72 for (int p = 0; p < bytesRead; p++) {
73 _byte = readingBuffer[p];
76 case WaitingForSyncByte:
77 if (_byte == ESP3Packet.ESP3_SYNC_BYTE) {
78 state = ReadingState.ReadingHeader;
79 logger.trace("Received Sync Byte");
83 if (currentPosition == ESP3Packet.ESP3_HEADER_LENGTH) {
84 if (ESP3Packet.checkCRC8(dataBuffer, ESP3Packet.ESP3_HEADER_LENGTH, _byte)
85 && ((dataBuffer[0] & 0xFF) << 8) + (dataBuffer[1] & 0xFF)
86 + (dataBuffer[2] & 0xFF) > 0) {
87 state = ReadingState.ReadingData;
89 dataLength = ((dataBuffer[0] & 0xFF << 8) | (dataBuffer[1] & 0xFF));
90 optionalLength = dataBuffer[2] & 0xFF;
91 packetType = dataBuffer[3];
94 if (packetType == 3) {
95 logger.trace("Received sub_msg");
98 logger.trace(">> Received header, data length {} optional length {} packet type {}",
99 dataLength, optionalLength, packetType);
101 // check if we find a sync byte in current buffer
103 for (int i = 0; i < ESP3Packet.ESP3_HEADER_LENGTH; i++) {
104 if (dataBuffer[i] == ESP3Packet.ESP3_SYNC_BYTE) {
110 if (copyFrom != -1) {
111 System.arraycopy(dataBuffer, copyFrom, dataBuffer, 0,
112 ESP3Packet.ESP3_HEADER_LENGTH - copyFrom);
113 state = ReadingState.ReadingHeader;
114 currentPosition = ESP3Packet.ESP3_HEADER_LENGTH - copyFrom;
115 dataBuffer[currentPosition++] = _byte;
118 state = _byte == ESP3Packet.ESP3_SYNC_BYTE ? ReadingState.ReadingHeader
119 : ReadingState.WaitingForSyncByte;
121 logger.trace("CrC8 header check not successful");
124 dataBuffer[currentPosition++] = _byte;
128 if (currentPosition == dataLength + optionalLength) {
129 if (ESP3Packet.checkCRC8(dataBuffer, dataLength + optionalLength, _byte)) {
130 state = ReadingState.WaitingForSyncByte;
131 BasePacket packet = ESP3PacketFactory.BuildPacket(dataLength, optionalLength,
132 packetType, dataBuffer);
134 if (packet != null) {
135 switch (packet.getPacketType()) {
137 logger.debug("Common command: {}",
138 HexUtils.bytesToHex(packet.getPayload()));
141 logger.debug("Event occured: {}", HexUtils.bytesToHex(packet.getPayload()));
144 ERP1Message msg = (ERP1Message) packet;
145 logger.debug("{} with RORG {} for {} payload {} received",
146 packet.getPacketType().name(), msg.getRORG().name(),
147 HexUtils.bytesToHex(msg.getSenderId()), HexUtils.bytesToHex(
148 Arrays.copyOf(dataBuffer, dataLength + optionalLength)));
150 if (msg.getRORG() != RORG.Unknown) {
151 informListeners(msg);
153 logger.debug("Received unknown RORG");
163 case REMOTE_MAN_COMMAND:
166 Response response = (Response) packet;
167 logger.debug("{} with code {} payload {} received",
168 packet.getPacketType().name(), response.getResponseType().name(),
169 HexUtils.bytesToHex(packet.getPayload())); // Responses do not have
171 handleResponse(response);
174 case SMART_ACK_COMMAND:
180 logger.trace("Unknown ESP3Packet: {}", HexUtils
181 .bytesToHex(Arrays.copyOf(dataBuffer, dataLength + optionalLength)));
184 state = _byte == ESP3Packet.ESP3_SYNC_BYTE ? ReadingState.ReadingHeader
185 : ReadingState.WaitingForSyncByte;
186 logger.trace("ESP3Packet malformed: {}",
187 HexUtils.bytesToHex(Arrays.copyOf(dataBuffer, dataLength + optionalLength)));
191 dataLength = optionalLength = packetType = -1;
193 dataBuffer[currentPosition++] = _byte;
198 } catch (IOException ioexception) {
199 errorListener.ErrorOccured(ioexception);
205 protected byte[] serializePacket(BasePacket packet) throws EnOceanException {
206 return new ESP3Packet(packet).serialize();