/**
* 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.satel.internal.protocol;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.TooManyListenersException;
import org.osgi.service.cm.ConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
/**
* Represents Satel INT-RS module. Implements methods required to connect and
* communicate with that module over serial protocol.
*
* @author Krzysztof Goworek
* @since 1.7.0
*/
public class IntRSModule extends SatelModule {
private static final Logger logger = LoggerFactory.getLogger(IntRSModule.class);
private String port;
/**
* Creates new instance with port and timeout set to specified values.
*
* @param port
* serial port the module is connected to
* @param timeout
* timeout value in milliseconds for connect/read/write
* operations
* @throws ConfigurationException
* unconditionally throws this exception as it is not
* implemented yet
*/
public IntRSModule(String port, int timeout) throws ConfigurationException {
super(timeout);
this.port = port;
}
@Override
protected CommunicationChannel connect() {
logger.info("Connecting to INT-RS module at {}", this.port);
try {
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(this.port);
SerialPort serialPort = portIdentifier.open("org.openhab.binding.satel", 2000);
serialPort.setSerialPortParams(19200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
serialPort.enableReceiveTimeout(this.getTimeout());
// RXTX serial port library causes high CPU load
// Start event listener, which will just sleep and slow down event
// loop
serialPort.addEventListener(new SerialPortEventListener() {
@Override
public void serialEvent(SerialPortEvent ev) {
try {
logger.trace("RXTX library CPU load workaround, sleep forever");
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException e) {
}
}
});
serialPort.notifyOnDataAvailable(true);
logger.info("INT-RS module connected successfuly");
return new SerialCommunicationChannel(serialPort);
} catch (NoSuchPortException e) {
logger.error("Port {} does not exist", this.port);
} catch (PortInUseException e) {
logger.error("Port {} in use.", this.port);
} catch (UnsupportedCommOperationException e) {
logger.error("Unsupported comm operation on port {}.", this.port);
} catch (TooManyListenersException e) {
logger.error("Too many listeners on port {}.", this.port);
}
return null;
}
private class SerialCommunicationChannel implements CommunicationChannel {
private SerialPort serialPort;
public SerialCommunicationChannel(SerialPort serialPort) {
this.serialPort = serialPort;
}
@Override
public InputStream getInputStream() throws IOException {
return this.serialPort.getInputStream();
}
@Override
public OutputStream getOutputStream() throws IOException {
return this.serialPort.getOutputStream();
}
@Override
public void disconnect() {
logger.debug("Closing connection to INT-RS module");
try {
this.serialPort.close();
logger.info("Connection to INT-RS module has been closed");
} catch (Exception e) {
logger.error("An error occurred during closing serial port", e);
}
}
}
}