]> git.basschouten.com Git - openhab-addons.git/blob
e9e350976c373f3284b13f05b98286bae6129dd4
[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.ESP3Packet;
26 import org.openhab.binding.enocean.internal.messages.ESP3PacketFactory;
27 import org.openhab.binding.enocean.internal.messages.Response;
28 import org.openhab.core.io.transport.serial.SerialPortManager;
29 import org.openhab.core.util.HexUtils;
30
31 /**
32  *
33  * @author Daniel Weber - Initial contribution
34  */
35 @NonNullByDefault
36 public class EnOceanESP3Transceiver extends EnOceanTransceiver {
37
38     public EnOceanESP3Transceiver(String path, TransceiverErrorListener errorListener,
39             ScheduledExecutorService scheduler, @Nullable SerialPortManager serialPortManager) {
40         super(path, errorListener, scheduler, serialPortManager);
41     }
42
43     enum ReadingState {
44         WaitingForSyncByte,
45         ReadingHeader,
46         ReadingData
47     }
48
49     byte[] dataBuffer = new byte[ENOCEAN_MAX_DATA];
50     ReadingState state = ReadingState.WaitingForSyncByte;
51     int currentPosition = 0;
52     int dataLength = -1;
53     int optionalLength = -1;
54     byte packetType = -1;
55
56     @Override
57     protected void processMessage(byte firstByte) {
58         byte[] readingBuffer = new byte[ENOCEAN_MAX_DATA];
59         int bytesRead = -1;
60         byte byteBuffer;
61
62         try {
63             readingBuffer[0] = firstByte;
64             InputStream localInPutStream = this.inputStream;
65             if (localInPutStream == null) {
66                 throw new IOException("could not read from inputstream");
67             }
68             bytesRead = localInPutStream.read(readingBuffer, 1, localInPutStream.available());
69             if (bytesRead == -1) {
70                 throw new IOException("could not read from inputstream");
71             }
72
73             Future<?> localReadingTask = readingTask;
74             if (localReadingTask == null || localReadingTask.isCancelled()) {
75                 return;
76             }
77
78             bytesRead++;
79             for (int p = 0; p < bytesRead; p++) {
80                 byteBuffer = readingBuffer[p];
81
82                 switch (state) {
83                     case WaitingForSyncByte:
84                         if (byteBuffer == ESP3Packet.ESP3_SYNC_BYTE) {
85                             state = ReadingState.ReadingHeader;
86                             logger.trace("Received Sync Byte");
87                         }
88                         break;
89                     case ReadingHeader:
90                         if (currentPosition == ESP3Packet.ESP3_HEADER_LENGTH) {
91                             if (ESP3Packet.checkCRC8(dataBuffer, ESP3Packet.ESP3_HEADER_LENGTH, byteBuffer)
92                                     && ((dataBuffer[0] & 0xFF) << 8) + (dataBuffer[1] & 0xFF)
93                                             + (dataBuffer[2] & 0xFF) > 0) {
94                                 state = ReadingState.ReadingData;
95
96                                 dataLength = ((dataBuffer[0] & 0xFF << 8) | (dataBuffer[1] & 0xFF));
97                                 optionalLength = dataBuffer[2] & 0xFF;
98                                 packetType = dataBuffer[3];
99                                 currentPosition = 0;
100
101                                 if (packetType == 3) {
102                                     logger.trace("Received sub_msg");
103                                 }
104
105                                 logger.trace(">> Received header, data length {} optional length {} packet type {}",
106                                         dataLength, optionalLength, packetType);
107                             } else {
108                                 // check if we find a sync byte in current buffer
109                                 int copyFrom = -1;
110                                 for (int i = 0; i < ESP3Packet.ESP3_HEADER_LENGTH; i++) {
111                                     if (dataBuffer[i] == ESP3Packet.ESP3_SYNC_BYTE) {
112                                         copyFrom = i + 1;
113                                         break;
114                                     }
115                                 }
116
117                                 if (copyFrom != -1) {
118                                     System.arraycopy(dataBuffer, copyFrom, dataBuffer, 0,
119                                             ESP3Packet.ESP3_HEADER_LENGTH - copyFrom);
120                                     state = ReadingState.ReadingHeader;
121                                     currentPosition = ESP3Packet.ESP3_HEADER_LENGTH - copyFrom;
122                                     dataBuffer[currentPosition++] = byteBuffer;
123                                 } else {
124                                     currentPosition = 0;
125                                     state = byteBuffer == ESP3Packet.ESP3_SYNC_BYTE ? ReadingState.ReadingHeader
126                                             : ReadingState.WaitingForSyncByte;
127                                 }
128                                 logger.trace("CrC8 header check not successful");
129                             }
130                         } else {
131                             dataBuffer[currentPosition++] = byteBuffer;
132                         }
133                         break;
134                     case ReadingData:
135                         if (currentPosition == dataLength + optionalLength) {
136                             if (ESP3Packet.checkCRC8(dataBuffer, dataLength + optionalLength, byteBuffer)) {
137                                 state = ReadingState.WaitingForSyncByte;
138                                 BasePacket packet = ESP3PacketFactory.buildPacket(dataLength, optionalLength,
139                                         packetType, dataBuffer);
140
141                                 if (packet != null) {
142                                     switch (packet.getPacketType()) {
143                                         case COMMON_COMMAND:
144                                             logger.debug("Common command: {}",
145                                                     HexUtils.bytesToHex(packet.getPayload()));
146                                             break;
147                                         case EVENT:
148                                         case RADIO_ERP1:
149                                             informListeners(packet);
150                                             break;
151                                         case RADIO_ERP2:
152                                             break;
153                                         case RADIO_MESSAGE:
154                                             break;
155                                         case RADIO_SUB_TEL:
156                                             break;
157                                         case REMOTE_MAN_COMMAND:
158                                             break;
159                                         case RESPONSE: {
160                                             Response response = (Response) packet;
161                                             logger.debug("{} with code {} payload {} received",
162                                                     packet.getPacketType().name(), response.getResponseType().name(),
163                                                     HexUtils.bytesToHex(packet.getPayload())); // Responses do not have
164                                                                                                // optional data
165                                             handleResponse(response);
166                                         }
167                                             break;
168                                         case SMART_ACK_COMMAND:
169                                             break;
170                                         default:
171                                             break;
172                                     }
173                                 } else {
174                                     logger.trace("Unknown ESP3Packet: {}", HexUtils
175                                             .bytesToHex(Arrays.copyOf(dataBuffer, dataLength + optionalLength)));
176                                 }
177                             } else {
178                                 state = byteBuffer == ESP3Packet.ESP3_SYNC_BYTE ? ReadingState.ReadingHeader
179                                         : ReadingState.WaitingForSyncByte;
180                                 logger.trace("ESP3Packet malformed: {}",
181                                         HexUtils.bytesToHex(Arrays.copyOf(dataBuffer, dataLength + optionalLength)));
182                             }
183
184                             currentPosition = 0;
185                             dataLength = optionalLength = packetType = -1;
186                         } else {
187                             dataBuffer[currentPosition++] = byteBuffer;
188                         }
189                         break;
190                 }
191             }
192         } catch (IOException ioexception) {
193             logger.trace("Unable to process message", ioexception);
194             TransceiverErrorListener localListener = errorListener;
195             if (localListener != null) {
196                 localListener.errorOccured(ioexception);
197             }
198             return;
199         }
200     }
201
202     @Override
203     protected byte[] serializePacket(BasePacket packet) throws EnOceanException {
204         return new ESP3Packet(packet).serialize();
205     }
206 }