/** * Copyright (c) 2010-2016 by the respective copyright holders. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.openhab.binding.ehealth.protocol; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.TooManyListenersException; import org.apache.commons.io.IOUtils; import org.openhab.binding.ehealth.internal.EHealthException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import gnu.io.CommPortIdentifier; import gnu.io.PortInUseException; import gnu.io.SerialPort; import gnu.io.SerialPortEvent; import gnu.io.SerialPortEventListener; import gnu.io.UnsupportedCommOperationException; /** * Provides access to the serial port. Interested parties should * add themselves as {@link SerialEventProcessor}. * * @author Thomas Eichstaedt-Engelen * @since 1.6.0 */ public class SerialConnector implements SerialPortEventListener { private static final Logger logger = LoggerFactory.getLogger(SerialConnector.class); private String portName; private final static int BAUD = 9600; private CommPortIdentifier portId; private SerialPort serialPort; private InputStream inputStream; private OutputStream outputStream; private BufferedReader bReader; private BufferedWriter bWriter; private List<SerialEventProcessor> processors; public SerialConnector(String portName) { this.portName = portName; this.processors = new ArrayList<SerialEventProcessor>(); } public void addSerialEventProcessor(SerialEventProcessor processor) { this.processors.add(processor); } public void removeSerialEventProcessor(SerialEventProcessor processor) { this.processors.remove(processor); } public void connect() throws EHealthException { logger.debug("Going to open Serial connection on port '{}'", portName); // parse ports and if the default port is found, initialized the reader Enumeration<?> portList = CommPortIdentifier.getPortIdentifiers(); while (portList.hasMoreElements()) { CommPortIdentifier id = (CommPortIdentifier) portList.nextElement(); if (id.getPortType() == CommPortIdentifier.PORT_SERIAL) { if (id.getName().equals(portName)) { logger.debug("Serial port '{}' has been found.", portName); portId = id; } } } if (portId != null) { // initialize serial port try { serialPort = portId.open("openHAB", 2000); inputStream = serialPort.getInputStream(); outputStream = serialPort.getOutputStream(); bReader = new BufferedReader(new InputStreamReader(inputStream)); bWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); serialPort.addEventListener(this); serialPort.notifyOnDataAvailable(true); serialPort.setSerialPortParams(BAUD, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); } catch (IOException e) { throw new EHealthException(e); } catch (PortInUseException e) { throw new EHealthException(e); } catch (UnsupportedCommOperationException e) { throw new EHealthException(e); } catch (TooManyListenersException e) { throw new EHealthException(e); } } else { StringBuilder sb = new StringBuilder(); portList = CommPortIdentifier.getPortIdentifiers(); while (portList.hasMoreElements()) { CommPortIdentifier id = (CommPortIdentifier) portList.nextElement(); if (id.getPortType() == CommPortIdentifier.PORT_SERIAL) { sb.append(id.getName() + "\n"); } } throw new EHealthException( "Serial port '" + portName + "' could not be found. Available ports are:\n" + sb.toString()); } } public void disconnect() { logger.debug("Disconnecting from serial port '{}'", portName); if (serialPort != null) { serialPort.removeEventListener(); } IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(outputStream); if (serialPort != null) { serialPort.close(); } logger.debug("Serial port '{}' closed", portName); } @Override public void serialEvent(SerialPortEvent event) { if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) { try { String data = bReader.readLine(); logger.trace("Received raw message to process: '{}'", data); notifyEventProcessors(data); } catch (IOException e) { logger.error("Exception while reading from serial port", e); } } } private void notifyEventProcessors(String data) { for (SerialEventProcessor processor : processors) { processor.processSerialData(data); } } /** * Writes the given {@code message} to the serial port. * * @param message the message to write to the serial port. */ public void writeMessage(String message) { logger.debug("Sending raw message to serial port: " + message); if (bWriter == null) { logger.error("Can't write message, BufferedWriter is NULL"); } synchronized (bWriter) { try { bWriter.write(message); bWriter.flush(); } catch (IOException e) { logger.error("Can't write to serial port", e); } } } }