]> git.basschouten.com Git - openhab-addons.git/blob
d7e9681f7982a77d7660cc8ecd913a212ae5188e
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.enocean.internal.transceiver;
14
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.util.Arrays;
18 import java.util.concurrent.Future;
19 import java.util.concurrent.ScheduledExecutorService;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.enocean.internal.EnOceanException;
24 import org.openhab.binding.enocean.internal.messages.BasePacket;
25 import org.openhab.binding.enocean.internal.messages.ERP1Message;
26 import org.openhab.binding.enocean.internal.messages.ERP1Message.RORG;
27 import org.openhab.binding.enocean.internal.messages.ESP2Packet;
28 import org.openhab.binding.enocean.internal.messages.ESP2PacketConverter;
29 import org.openhab.binding.enocean.internal.messages.Response;
30 import org.openhab.core.io.transport.serial.SerialPortManager;
31 import org.openhab.core.util.HexUtils;
32
33 /**
34  *
35  * @author Daniel Weber - Initial contribution
36  */
37 @NonNullByDefault
38 public class EnOceanESP2Transceiver extends EnOceanTransceiver {
39
40     public EnOceanESP2Transceiver(String path, TransceiverErrorListener errorListener,
41             ScheduledExecutorService scheduler, @Nullable SerialPortManager serialPortManager) {
42         super(path, errorListener, scheduler, serialPortManager);
43     }
44
45     enum ReadingState {
46         WaitingForFirstSyncByte,
47         WaitingForSecondSyncByte,
48         ReadingHeader,
49         ReadingData
50     }
51
52     byte[] dataBuffer = new byte[ESP2Packet.ESP_PACKET_LENGTH];
53     ReadingState state = ReadingState.WaitingForFirstSyncByte;
54     int currentPosition = 0;
55     int dataLength = -1;
56     byte packetType = -1;
57
58     @Override
59     protected void processMessage(byte firstByte) {
60         byte[] readingBuffer = new byte[ENOCEAN_MAX_DATA];
61         int bytesRead = -1;
62         byte byteBuffer;
63
64         try {
65             readingBuffer[0] = firstByte;
66             InputStream localInputStream = inputStream;
67             if (localInputStream == null) {
68                 throw new IOException("could not read from inputstream, it was null");
69             }
70             bytesRead = localInputStream.read(readingBuffer, 1, localInputStream.available());
71             if (bytesRead == -1) {
72                 throw new IOException("could not read from inputstream");
73             }
74
75             Future<?> localReadingTask = readingTask;
76             if (localReadingTask == null || localReadingTask.isCancelled()) {
77                 return;
78             }
79
80             bytesRead++;
81             for (int p = 0; p < bytesRead; p++) {
82                 byteBuffer = readingBuffer[p];
83
84                 switch (state) {
85                     case WaitingForFirstSyncByte:
86                         if (byteBuffer == ESP2Packet.ENOCEAN_ESP2_FIRSTSYNC_BYTE) {
87                             state = ReadingState.WaitingForSecondSyncByte;
88                             logger.trace("Received First Sync Byte");
89                         }
90                         break;
91                     case WaitingForSecondSyncByte:
92                         if (byteBuffer == ESP2Packet.ENOCEAN_ESP2_SECONDSYNC_BYTE) {
93                             state = ReadingState.ReadingHeader;
94                             logger.trace("Received Second Sync Byte");
95                         }
96                         break;
97                     case ReadingHeader: {
98                         state = ReadingState.ReadingData;
99
100                         currentPosition = 0;
101                         dataBuffer[currentPosition++] = byteBuffer;
102                         dataLength = ((dataBuffer[0] & 0xFF) & 0b11111);
103                         packetType = (byte) ((dataBuffer[0] & 0xFF) >> 5);
104
105                         logger.trace(">> Received header, data length {} packet type {}", dataLength, packetType);
106                     }
107                         break;
108                     case ReadingData:
109                         if (currentPosition == dataLength) {
110                             if (ESP2Packet.validateCheckSum(dataBuffer, dataLength, byteBuffer)) {
111                                 BasePacket packet = ESP2PacketConverter.buildPacket(dataLength, packetType, dataBuffer);
112                                 if (packet != null) {
113                                     switch (packet.getPacketType()) {
114                                         case RADIO_ERP1: {
115                                             ERP1Message msg = (ERP1Message) packet;
116                                             logger.debug("Converted to: {} with RORG {} for {}",
117                                                     packet.getPacketType().name(), msg.getRORG().name(),
118                                                     HexUtils.bytesToHex(msg.getSenderId()));
119
120                                             if (msg.getRORG() != RORG.Unknown) {
121                                                 informListeners(msg);
122                                             } else {
123                                                 logger.debug("Received unknown RORG");
124                                             }
125                                         }
126                                             break;
127                                         case RESPONSE: {
128                                             Response response = (Response) packet;
129                                             logger.debug("Converted to: {} with code {}", packet.getPacketType().name(),
130                                                     response.getResponseType().name());
131
132                                             handleResponse(response);
133                                         }
134                                             break;
135                                         default:
136                                             break;
137                                     }
138                                 } else {
139                                     if (dataBuffer[1] != (byte) 0xFC) {
140                                         byte[] array = Arrays.copyOf(dataBuffer, dataLength);
141                                         String packetString = array != null ? HexUtils.bytesToHex(array) : "";
142                                         logger.debug("Unknown/unsupported ESP2Packet: {}", packetString);
143                                     }
144                                 }
145                             } else {
146                                 logger.debug("ESP2Packet malformed: {}", HexUtils.bytesToHex(dataBuffer));
147                             }
148
149                             state = byteBuffer == ESP2Packet.ENOCEAN_ESP2_FIRSTSYNC_BYTE
150                                     ? ReadingState.WaitingForSecondSyncByte
151                                     : ReadingState.WaitingForFirstSyncByte;
152
153                             currentPosition = 0;
154                             dataLength = packetType = -1;
155                         } else {
156                             dataBuffer[currentPosition++] = byteBuffer;
157                         }
158                         break;
159                 }
160             }
161         } catch (IOException ioexception) {
162             logger.trace("Unable to process message", ioexception);
163             TransceiverErrorListener localListener = errorListener;
164             if (localListener != null) {
165                 localListener.errorOccured(ioexception);
166             }
167             return;
168         }
169     }
170
171     @Override
172     protected byte[] serializePacket(BasePacket packet) throws EnOceanException {
173         return new ESP2Packet(packet).serialize();
174     }
175 }