/** * 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.powermax.internal.connector; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.TooManyListenersException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import gnu.io.CommPort; import gnu.io.CommPortIdentifier; import gnu.io.NoSuchPortException; import gnu.io.PortInUseException; import gnu.io.SerialPort; import gnu.io.SerialPortEvent; import gnu.io.SerialPortEventListener; import gnu.io.UnsupportedCommOperationException; /** * A class for the communication with the Visonic alarm panel through a serial connection * * @author Laurent Garnier * @since 1.9.0 */ public class PowerMaxSerialConnector extends PowerMaxConnector { private static final Logger logger = LoggerFactory.getLogger(PowerMaxSerialConnector.class); private final String serialPortName; private final int baudRate; private SerialPort serialPort; /** * Constructor * * @param serialPortName * the serial port name * @param baudRate * the baud rate to be used */ public PowerMaxSerialConnector(String serialPortName, int baudRate) { this.serialPortName = serialPortName; this.baudRate = baudRate; this.serialPort = null; } /** * {@inheritDoc} **/ @Override public void open() { logger.debug("open(): Opening Serial Connection"); try { CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(serialPortName); CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000); serialPort = (SerialPort) commPort; serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); serialPort.enableReceiveThreshold(1); serialPort.disableReceiveTimeout(); setInput(serialPort.getInputStream()); setOutput(serialPort.getOutputStream()); getOutput().flush(); if (getInput().markSupported()) { getInput().reset(); } setReaderThread(new SerialReaderThread(getInput(), this)); getReaderThread().start(); setConnected(true); } catch (NoSuchPortException noSuchPortException) { logger.debug("open(): No Such Port Exception: {}", noSuchPortException.getMessage()); setConnected(false); } catch (PortInUseException portInUseException) { logger.debug("open(): Port in Use Exception: {}", portInUseException.getMessage()); setConnected(false); } catch (UnsupportedCommOperationException unsupportedCommOperationException) { logger.debug("open(): Unsupported Comm Operation Exception: {}", unsupportedCommOperationException.getMessage()); setConnected(false); } catch (UnsupportedEncodingException unsupportedEncodingException) { logger.debug("open(): Unsupported Encoding Exception: {}", unsupportedEncodingException.getMessage()); setConnected(false); } catch (IOException ioException) { logger.debug("open(): IO Exception: ", ioException.getMessage()); setConnected(false); } } /** * {@inheritDoc} **/ @Override public void close() { logger.debug("close(): Closing Serial Connection"); super.cleanup(); if (serialPort != null) { serialPort.close(); } serialPort = null; setConnected(false); } /** * A class that handles the reading of messages through the serial connection * It is an extend of the common class PowerMaxReaderThread */ public class SerialReaderThread extends PowerMaxReaderThread implements SerialPortEventListener { public SerialReaderThread(InputStream in, PowerMaxConnector connector) { super(in, connector); } @Override public void run() { logger.debug("Data listener started"); // RXTX serial port library causes high CPU load // Start event listener, which will just sleep and slow down event // loop try { serialPort.addEventListener(this); serialPort.notifyOnDataAvailable(true); } catch (TooManyListenersException e) { logger.debug("Too Many Listeners Exception: {}", e.getMessage()); } super.run(); serialPort.removeEventListener(); logger.debug("Data listener stopped"); } @Override public void serialEvent(SerialPortEvent serialPortEvent) { try { logger.trace("RXTX library CPU load workaround, sleep forever"); sleep(Long.MAX_VALUE); } catch (InterruptedException e) { } } } }