]> git.basschouten.com Git - openhab-addons.git/blob
a8713e7ec56284a76424966f442f08610121786b
[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.util.Arrays;
17 import java.util.concurrent.ScheduledExecutorService;
18
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;
26
27 /**
28  *
29  * @author Daniel Weber - Initial contribution
30  */
31 public class EnOceanESP3Transceiver extends EnOceanTransceiver {
32
33     public EnOceanESP3Transceiver(String path, TransceiverErrorListener errorListener,
34             ScheduledExecutorService scheduler, SerialPortManager serialPortManager) {
35         super(path, errorListener, scheduler, serialPortManager);
36     }
37
38     enum ReadingState {
39         WaitingForSyncByte,
40         ReadingHeader,
41         ReadingData
42     }
43
44     byte[] dataBuffer = new byte[ENOCEAN_MAX_DATA];
45     ReadingState state = ReadingState.WaitingForSyncByte;
46     int currentPosition = 0;
47     int dataLength = -1;
48     int optionalLength = -1;
49     byte packetType = -1;
50
51     @Override
52     protected void processMessage(byte firstByte) {
53         byte[] readingBuffer = new byte[ENOCEAN_MAX_DATA];
54         int bytesRead = -1;
55         byte _byte;
56
57         try {
58             readingBuffer[0] = firstByte;
59
60             bytesRead = this.inputStream.read(readingBuffer, 1, inputStream.available());
61             if (bytesRead == -1) {
62                 throw new IOException("could not read from inputstream");
63             }
64
65             if (readingTask == null || readingTask.isCancelled()) {
66                 return;
67             }
68
69             bytesRead++;
70             for (int p = 0; p < bytesRead; p++) {
71                 _byte = readingBuffer[p];
72
73                 switch (state) {
74                     case WaitingForSyncByte:
75                         if (_byte == ESP3Packet.ESP3_SYNC_BYTE) {
76                             state = ReadingState.ReadingHeader;
77                             logger.trace("Received Sync Byte");
78                         }
79                         break;
80                     case ReadingHeader:
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;
86
87                                 dataLength = ((dataBuffer[0] & 0xFF << 8) | (dataBuffer[1] & 0xFF));
88                                 optionalLength = dataBuffer[2] & 0xFF;
89                                 packetType = dataBuffer[3];
90                                 currentPosition = 0;
91
92                                 if (packetType == 3) {
93                                     logger.trace("Received sub_msg");
94                                 }
95
96                                 logger.trace(">> Received header, data length {} optional length {} packet type {}",
97                                         dataLength, optionalLength, packetType);
98                             } else {
99                                 // check if we find a sync byte in current buffer
100                                 int copyFrom = -1;
101                                 for (int i = 0; i < ESP3Packet.ESP3_HEADER_LENGTH; i++) {
102                                     if (dataBuffer[i] == ESP3Packet.ESP3_SYNC_BYTE) {
103                                         copyFrom = i + 1;
104                                         break;
105                                     }
106                                 }
107
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;
114                                 } else {
115                                     currentPosition = 0;
116                                     state = _byte == ESP3Packet.ESP3_SYNC_BYTE ? ReadingState.ReadingHeader
117                                             : ReadingState.WaitingForSyncByte;
118                                 }
119                                 logger.trace("CrC8 header check not successful");
120                             }
121                         } else {
122                             dataBuffer[currentPosition++] = _byte;
123                         }
124                         break;
125                     case ReadingData:
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);
131
132                                 if (packet != null) {
133                                     switch (packet.getPacketType()) {
134                                         case COMMON_COMMAND:
135                                             logger.debug("Common command: {}",
136                                                     HexUtils.bytesToHex(packet.getPayload()));
137                                             break;
138                                         case EVENT:
139                                         case RADIO_ERP1:
140                                             informListeners(packet);
141                                             break;
142                                         case RADIO_ERP2:
143                                             break;
144                                         case RADIO_MESSAGE:
145                                             break;
146                                         case RADIO_SUB_TEL:
147                                             break;
148                                         case REMOTE_MAN_COMMAND:
149                                             break;
150                                         case RESPONSE: {
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
155                                                                                                // optional data
156                                             handleResponse(response);
157                                         }
158                                             break;
159                                         case SMART_ACK_COMMAND:
160                                             break;
161                                         default:
162                                             break;
163                                     }
164                                 } else {
165                                     logger.trace("Unknown ESP3Packet: {}", HexUtils
166                                             .bytesToHex(Arrays.copyOf(dataBuffer, dataLength + optionalLength)));
167                                 }
168                             } else {
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)));
173                             }
174
175                             currentPosition = 0;
176                             dataLength = optionalLength = packetType = -1;
177                         } else {
178                             dataBuffer[currentPosition++] = _byte;
179                         }
180                         break;
181                 }
182             }
183         } catch (IOException ioexception) {
184             errorListener.ErrorOccured(ioexception);
185             return;
186         }
187     }
188
189     @Override
190     protected byte[] serializePacket(BasePacket packet) throws EnOceanException {
191         return new ESP3Packet(packet).serialize();
192     }
193 }