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.serialbutton.internal.handler;
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.util.TooManyListenersException;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.openhab.binding.serialbutton.internal.SerialButtonBindingConstants;
21 import org.openhab.core.io.transport.serial.PortInUseException;
22 import org.openhab.core.io.transport.serial.SerialPort;
23 import org.openhab.core.io.transport.serial.SerialPortEvent;
24 import org.openhab.core.io.transport.serial.SerialPortEventListener;
25 import org.openhab.core.io.transport.serial.SerialPortIdentifier;
26 import org.openhab.core.io.transport.serial.SerialPortManager;
27 import org.openhab.core.thing.ChannelUID;
28 import org.openhab.core.thing.CommonTriggerEvents;
29 import org.openhab.core.thing.Thing;
30 import org.openhab.core.thing.ThingStatus;
31 import org.openhab.core.thing.ThingStatusDetail;
32 import org.openhab.core.thing.binding.BaseThingHandler;
33 import org.openhab.core.types.Command;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 * The {@link SerialButtonHandler} is responsible for handling commands, which are
39 * sent to one of the channels.
41 * @author Kai Kreuzer - Initial contribution
43 public class SerialButtonHandler extends BaseThingHandler implements SerialPortEventListener {
45 private final Logger logger = LoggerFactory.getLogger(SerialButtonHandler.class);
46 private final SerialPortManager serialPortManager;
48 private SerialPortIdentifier portId;
49 private SerialPort serialPort;
51 private InputStream inputStream;
53 public SerialButtonHandler(Thing thing, final SerialPortManager serialPortManager) {
55 this.serialPortManager = serialPortManager;
59 public void initialize() {
60 String port = (String) getConfig().get(SerialButtonBindingConstants.PARAMETER_CONFIG);
62 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, "Port must be set!");
66 // parse ports and if the port is found, initialize the reader
67 portId = serialPortManager.getIdentifier(port);
69 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, "Port is not known!");
73 // initialize serial port
75 serialPort = portId.open(getThing().getUID().toString(), 2000);
76 serialPort.addEventListener(this);
78 // activate the DATA_AVAILABLE notifier
79 serialPort.notifyOnDataAvailable(true);
80 inputStream = serialPort.getInputStream();
82 updateStatus(ThingStatus.ONLINE);
83 } catch (final IOException ex) {
84 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, "I/O error!");
85 } catch (PortInUseException e) {
86 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, "Port is in use!");
87 } catch (TooManyListenersException e) {
88 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
89 "Cannot attach listener to port!");
94 public void dispose() {
95 if (serialPort != null) {
96 serialPort.removeEventListener();
98 if (inputStream != null) {
101 } catch (IOException e) {
102 logger.debug("Error while closing the input stream: {}", e.getMessage());
105 if (serialPort != null) {
113 public void serialEvent(SerialPortEvent event) {
114 switch (event.getEventType()) {
115 case SerialPortEvent.DATA_AVAILABLE:
116 // we get here if data has been received
119 // read data from serial device
120 byte[] readBuffer = new byte[20];
121 while (inputStream.available() > 0) {
122 inputStream.read(readBuffer);
125 // add wait states around reading the stream, so that interrupted transmissions are merged
127 } catch (InterruptedException e) {
128 // ignore interruption
130 } while (inputStream.available() > 0);
132 triggerChannel(SerialButtonBindingConstants.TRIGGER_CHANNEL, CommonTriggerEvents.PRESSED);
133 } catch (IOException e1) {
134 logger.debug("Error reading from serial port: {}", e1.getMessage(), e1);
143 public void handleCommand(@NonNull ChannelUID channelUID, @NonNull Command command) {
144 // we do not have any state channels, so nothing to do here