]> git.basschouten.com Git - openhab-addons.git/blob
f52a0daa8243ffb4bb09cc93c9ddaae016dbf4ec
[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.serialbutton.internal.handler;
14
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.util.TooManyListenersException;
18
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;
36
37 /**
38  * The {@link SerialButtonHandler} is responsible for handling commands, which are
39  * sent to one of the channels.
40  *
41  * @author Kai Kreuzer - Initial contribution
42  */
43 public class SerialButtonHandler extends BaseThingHandler implements SerialPortEventListener {
44
45     private final Logger logger = LoggerFactory.getLogger(SerialButtonHandler.class);
46     private final SerialPortManager serialPortManager;
47
48     private SerialPortIdentifier portId;
49     private SerialPort serialPort;
50
51     private InputStream inputStream;
52
53     public SerialButtonHandler(Thing thing, final SerialPortManager serialPortManager) {
54         super(thing);
55         this.serialPortManager = serialPortManager;
56     }
57
58     @Override
59     public void initialize() {
60         String port = (String) getConfig().get(SerialButtonBindingConstants.PARAMETER_CONFIG);
61         if (port == null) {
62             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, "Port must be set!");
63             return;
64         }
65
66         // parse ports and if the port is found, initialize the reader
67         portId = serialPortManager.getIdentifier(port);
68         if (portId == null) {
69             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, "Port is not known!");
70             return;
71         }
72
73         // initialize serial port
74         try {
75             serialPort = portId.open(getThing().getUID().toString(), 2000);
76             serialPort.addEventListener(this);
77
78             // activate the DATA_AVAILABLE notifier
79             serialPort.notifyOnDataAvailable(true);
80             inputStream = serialPort.getInputStream();
81
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!");
90         }
91     }
92
93     @Override
94     public void dispose() {
95         if (serialPort != null) {
96             serialPort.removeEventListener();
97         }
98         if (inputStream != null) {
99             try {
100                 inputStream.close();
101             } catch (IOException e) {
102                 logger.debug("Error while closing the input stream: {}", e.getMessage());
103             }
104         }
105         if (serialPort != null) {
106             serialPort.close();
107         }
108         inputStream = null;
109         serialPort = null;
110     }
111
112     @Override
113     public void serialEvent(SerialPortEvent event) {
114         switch (event.getEventType()) {
115             case SerialPortEvent.DATA_AVAILABLE:
116                 // we get here if data has been received
117                 try {
118                     do {
119                         // read data from serial device
120                         byte[] readBuffer = new byte[20];
121                         while (inputStream.available() > 0) {
122                             inputStream.read(readBuffer);
123                         }
124                         try {
125                             // add wait states around reading the stream, so that interrupted transmissions are merged
126                             Thread.sleep(100);
127                         } catch (InterruptedException e) {
128                             // ignore interruption
129                         }
130                     } while (inputStream.available() > 0);
131
132                     triggerChannel(SerialButtonBindingConstants.TRIGGER_CHANNEL, CommonTriggerEvents.PRESSED);
133                 } catch (IOException e1) {
134                     logger.debug("Error reading from serial port: {}", e1.getMessage(), e1);
135                 }
136                 break;
137             default:
138                 break;
139         }
140     }
141
142     @Override
143     public void handleCommand(@NonNull ChannelUID channelUID, @NonNull Command command) {
144         // we do not have any state channels, so nothing to do here
145     }
146 }