]> git.basschouten.com Git - openhab-addons.git/blob
179d7aa2937b0918de0959e691a6d005f03cb14e
[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.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;
28
29 /**
30  *
31  * @author Daniel Weber - Initial contribution
32  */
33 public class EnOceanESP2Transceiver extends EnOceanTransceiver {
34
35     public EnOceanESP2Transceiver(String path, TransceiverErrorListener errorListener,
36             ScheduledExecutorService scheduler, SerialPortManager serialPortManager) {
37         super(path, errorListener, scheduler, serialPortManager);
38     }
39
40     enum ReadingState {
41         WaitingForFirstSyncByte,
42         WaitingForSecondSyncByte,
43         ReadingHeader,
44         ReadingData
45     }
46
47     byte[] dataBuffer = new byte[ESP2Packet.ESP_PACKET_LENGTH];
48     ReadingState state = ReadingState.WaitingForFirstSyncByte;
49     int currentPosition = 0;
50     int dataLength = -1;
51     byte packetType = -1;
52
53     @Override
54     protected void processMessage(byte firstByte) {
55         byte[] readingBuffer = new byte[ENOCEAN_MAX_DATA];
56         int bytesRead = -1;
57         byte _byte;
58
59         try {
60             readingBuffer[0] = firstByte;
61
62             bytesRead = this.inputStream.read(readingBuffer, 1, inputStream.available());
63             if (bytesRead == -1) {
64                 throw new IOException("could not read from inputstream");
65             }
66
67             if (readingTask == null || readingTask.isCancelled()) {
68                 return;
69             }
70
71             bytesRead++;
72             for (int p = 0; p < bytesRead; p++) {
73                 _byte = readingBuffer[p];
74
75                 switch (state) {
76                     case WaitingForFirstSyncByte:
77                         if (_byte == ESP2Packet.ENOCEAN_ESP2_FIRSTSYNC_BYTE) {
78                             state = ReadingState.WaitingForSecondSyncByte;
79                             logger.trace("Received First Sync Byte");
80                         }
81                         break;
82                     case WaitingForSecondSyncByte:
83                         if (_byte == ESP2Packet.ENOCEAN_ESP2_SECONDSYNC_BYTE) {
84                             state = ReadingState.ReadingHeader;
85                             logger.trace("Received Second Sync Byte");
86                         }
87                         break;
88                     case ReadingHeader: {
89                         state = ReadingState.ReadingData;
90
91                         currentPosition = 0;
92                         dataBuffer[currentPosition++] = _byte;
93                         dataLength = ((dataBuffer[0] & 0xFF) & 0b11111);
94                         packetType = (byte) ((dataBuffer[0] & 0xFF) >> 5);
95
96                         logger.trace(">> Received header, data length {} packet type {}", dataLength, packetType);
97                     }
98                         break;
99                     case ReadingData:
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()) {
105                                         case RADIO_ERP1: {
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()));
110
111                                             if (msg.getRORG() != RORG.Unknown) {
112                                                 informListeners(msg);
113                                             } else {
114                                                 logger.debug("Received unknown RORG");
115                                             }
116                                         }
117                                             break;
118                                         case RESPONSE: {
119                                             Response response = (Response) packet;
120                                             logger.debug("Converted to: {} with code {}", packet.getPacketType().name(),
121                                                     response.getResponseType().name());
122
123                                             handleResponse(response);
124                                         }
125                                             break;
126                                         default:
127                                             break;
128                                     }
129                                 } else {
130                                     if (dataBuffer[1] != (byte) 0xFC) {
131                                         logger.debug("Unknown/unsupported ESP2Packet: {}",
132                                                 HexUtils.bytesToHex(Arrays.copyOf(dataBuffer, dataLength)));
133                                     }
134                                 }
135                             } else {
136                                 logger.debug("ESP2Packet malformed: {}", HexUtils.bytesToHex(dataBuffer));
137                             }
138
139                             state = _byte == ESP2Packet.ENOCEAN_ESP2_FIRSTSYNC_BYTE
140                                     ? ReadingState.WaitingForSecondSyncByte
141                                     : ReadingState.WaitingForFirstSyncByte;
142
143                             currentPosition = 0;
144                             dataLength = packetType = -1;
145                         } else {
146                             dataBuffer[currentPosition++] = _byte;
147                         }
148                         break;
149                 }
150             }
151         } catch (
152
153         IOException ioexception) {
154             errorListener.ErrorOccured(ioexception);
155             return;
156         }
157     }
158
159     @Override
160     protected byte[] serializePacket(BasePacket packet) throws EnOceanException {
161         return new ESP2Packet(packet).serialize();
162     }
163 }