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.lgtvserial.internal.protocol.serial;
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.io.OutputStream;
18 import java.util.Arrays;
19 import java.util.HashMap;
22 import org.openhab.core.io.transport.serial.PortInUseException;
23 import org.openhab.core.io.transport.serial.SerialPort;
24 import org.openhab.core.io.transport.serial.SerialPortIdentifier;
25 import org.openhab.core.io.transport.serial.UnsupportedCommOperationException;
26 import org.openhab.core.thing.ChannelUID;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
31 * This class handles the communication (read/writes) between the COM port and the things.
33 * @author Richard Lavoie - Initial contribution
36 public class LGSerialCommunicator {
38 private OutputStream output;
39 private InputStream input;
40 private SerialPort port;
42 private Map<Integer, LGSerialResponseListener> handlers = new HashMap<>();
43 private RegistrationCallback callback;
45 private byte[] buffer = new byte[1024];
50 private final Logger logger = LoggerFactory.getLogger(LGSerialCommunicator.class);
52 private static final int BAUD_RATE = 9600;
54 public LGSerialCommunicator(SerialPortIdentifier serialPortIdentifier, RegistrationCallback callback)
55 throws IOException, PortInUseException, UnsupportedCommOperationException {
56 SerialPort port = serialPortIdentifier.open(LGSerialCommunicator.class.getCanonicalName(), 2000);
57 port.setSerialPortParams(BAUD_RATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
60 this.output = port.getOutputStream();
61 this.input = port.getInputStream();
62 this.callback = callback;
65 public synchronized void write(LGSerialCommand command, String rawCommand, ChannelUID channel) throws IOException {
66 logger.debug("Sending command : {}", rawCommand);
67 output.write(rawCommand.getBytes());
71 // Let's wait not to spam the TV too much
74 } catch (InterruptedException e) {
75 Thread.currentThread().interrupt();
76 throw new IOException(e);
82 while (input.available() > 0 && (data = input.read()) > -1) {
84 String result = new String(buffer, offset, len);
85 if (logger.isDebugEnabled()) {
86 logger.debug("Buffer : {} offset={} len={}", Arrays.toString(buffer), offset, len);
87 logger.debug("Received response : {}", result);
89 LGSerialResponse response = command.parseResponse(result);
90 updateHandler(response, channel);
95 if (offset + len == buffer.length) {
96 byte[] newBuffer = new byte[1024];
97 System.arraycopy(buffer, offset, newBuffer, 0, len);
100 buffer[offset + len++] = (byte) data;
106 * Forward the response to the proper response handler, if a response was given.
108 * @param response Serial response
109 * @param channel Channel to update
111 private void updateHandler(LGSerialResponse response, ChannelUID channel) {
112 if (response != null) {
113 LGSerialResponseListener listener = handlers.get(response.getSetID());
114 if (listener != null) {
115 if (response.isSuccess()) {
116 listener.onSuccess(channel, response);
118 listener.onFailure(channel, response);
124 public synchronized void register(LGSerialResponseListener listener) {
125 handlers.put(listener.getSetID(), listener);
128 public synchronized void unregister(LGSerialResponseListener listener) {
129 handlers.remove(listener.getSetID());
130 if (handlers.isEmpty()) {
131 callback.onUnregister();
135 public void close() {
138 } catch (IOException e) {
139 logger.debug("An error occured while closing the serial input stream", e);
143 } catch (IOException e) {
144 logger.debug("An error occured while closing the serial output stream", e);
147 // For some reason, there needs some delay after close so we don't fail to open back the serial device
148 // TODO : investigate if this is still a real issue with the serial transport
151 } catch (InterruptedException e) {
152 Thread.currentThread().interrupt();
153 logger.debug("Thread interrupted while closing the communicator");