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.ERP1Message;
22 import org.openhab.binding.enocean.internal.messages.ERP1Message.RORG;
23 import org.openhab.binding.enocean.internal.messages.ESP2Packet;
24 import org.openhab.binding.enocean.internal.messages.ESP2PacketConverter;
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 EnOceanESP2Transceiver extends EnOceanTransceiver {
35 public EnOceanESP2Transceiver(String path, TransceiverErrorListener errorListener,
36 ScheduledExecutorService scheduler, SerialPortManager serialPortManager) {
37 super(path, errorListener, scheduler, serialPortManager);
41 WaitingForFirstSyncByte,
42 WaitingForSecondSyncByte,
47 byte[] dataBuffer = new byte[ESP2Packet.ESP_PACKET_LENGTH];
48 ReadingState state = ReadingState.WaitingForFirstSyncByte;
49 int currentPosition = 0;
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 WaitingForFirstSyncByte:
77 if (_byte == ESP2Packet.ENOCEAN_ESP2_FIRSTSYNC_BYTE) {
78 state = ReadingState.WaitingForSecondSyncByte;
79 logger.trace("Received First Sync Byte");
82 case WaitingForSecondSyncByte:
83 if (_byte == ESP2Packet.ENOCEAN_ESP2_SECONDSYNC_BYTE) {
84 state = ReadingState.ReadingHeader;
85 logger.trace("Received Second Sync Byte");
89 state = ReadingState.ReadingData;
92 dataBuffer[currentPosition++] = _byte;
93 dataLength = ((dataBuffer[0] & 0xFF) & 0b11111);
94 packetType = (byte) ((dataBuffer[0] & 0xFF) >> 5);
96 logger.trace(">> Received header, data length {} packet type {}", dataLength, packetType);
100 if (currentPosition == dataLength) {
101 if (ESP2Packet.validateCheckSum(dataBuffer, dataLength, _byte)) {
102 BasePacket packet = ESP2PacketConverter.BuildPacket(dataLength, packetType, dataBuffer);
103 if (packet != null) {
104 switch (packet.getPacketType()) {
106 ERP1Message msg = (ERP1Message) packet;
107 logger.debug("Converted to: {} with RORG {} for {}",
108 packet.getPacketType().name(), msg.getRORG().name(),
109 HexUtils.bytesToHex(msg.getSenderId()));
111 if (msg.getRORG() != RORG.Unknown) {
112 informListeners(msg);
114 logger.debug("Received unknown RORG");
119 Response response = (Response) packet;
120 logger.debug("Converted to: {} with code {}", packet.getPacketType().name(),
121 response.getResponseType().name());
123 handleResponse(response);
130 if (dataBuffer[1] != (byte) 0xFC) {
131 logger.debug("Unknown/unsupported ESP2Packet: {}",
132 HexUtils.bytesToHex(Arrays.copyOf(dataBuffer, dataLength)));
136 logger.debug("ESP2Packet malformed: {}", HexUtils.bytesToHex(dataBuffer));
139 state = _byte == ESP2Packet.ENOCEAN_ESP2_FIRSTSYNC_BYTE
140 ? ReadingState.WaitingForSecondSyncByte
141 : ReadingState.WaitingForFirstSyncByte;
144 dataLength = packetType = -1;
146 dataBuffer[currentPosition++] = _byte;
153 IOException ioexception) {
154 errorListener.ErrorOccured(ioexception);
160 protected byte[] serializePacket(BasePacket packet) throws EnOceanException {
161 return new ESP2Packet(packet).serialize();