Hi,
I am in the process of developing my own binding and use a USB stick which is accessed via the serial port with the standard libraries (org.eclipse.smarthome.io.transport.serial).
Unfortunately, the connection or initialization of this USB stick does not work properly with [transport.serial] . By this I mean that no data is sent or received until an additional trigger is given by another lib (e.g. jssc.jar).
This can be triggered externally (a separate java script) or by a function call within the binding. And this trigger only needs to be done once.
Here is my actual class:
package org.openhab.binding.openwms.connector;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.TooManyListenersException;
import org.apache.commons.io.IOUtils;
import org.eclipse.smarthome.core.util.HexUtils;
import org.eclipse.smarthome.io.transport.serial.PortInUseException;
import org.eclipse.smarthome.io.transport.serial.SerialPort;
import org.eclipse.smarthome.io.transport.serial.SerialPortEvent;
import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener;
import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier;
import org.eclipse.smarthome.io.transport.serial.SerialPortManager;
import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException;
import org.openhab.binding.openwms.config.OpenWMSBindingConstants;
import org.openhab.binding.openwms.config.OpenWMSBridgeConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OpenWMSSerialConnector extends OpenWMSBaseConnector implements SerialPortEventListener {
private final Logger logger = LoggerFactory.getLogger(OpenWMSSerialConnector.class);
private OutputStream out;
private SerialPort serialPort;
private Thread readerThread;
private SerialPortManager serialPortManager;
public OpenWMSSerialConnector(SerialPortManager serialPortManager) {
super();
this.serialPortManager = serialPortManager;
}
@Override
public void connect(OpenWMSBridgeConfiguration device)
throws PortInUseException, UnsupportedCommOperationException, IOException {
SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(device.serialPort.toString());
if (portIdentifier == null) {
logger.debug("No serial port {}", device.serialPort);
throw new IOException("Could not find a gateway on given path '" + device.serialPort + "', "
+ serialPortManager.getIdentifiers().count() + " ports available.");
}
serialPort = portIdentifier.open(OpenWMSBindingConstants.BINDING_ID, 2000);
serialPort.setSerialPortParams(230400, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
serialPort.enableReceiveThreshold(1);
serialPort.enableReceiveTimeout(100);
in = serialPort.getInputStream();
out = serialPort.getOutputStream();
out.flush();
if (in.markSupported()) {
in.reset();
}
try {
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
logger.debug("Serial port event listener started");
} catch (TooManyListenersException e) {
}
readerThread = new OpenWMSStreamReader(this);
readerThread.start();
}
@Override
public void disconnect() {
logger.debug("Disconnecting");
if (serialPort != null) {
serialPort.removeEventListener();
logger.debug("Serial port event listener stopped");
}
if (readerThread != null) {
logger.debug("Interrupt serial listener");
readerThread.interrupt();
try {
readerThread.join();
} catch (InterruptedException e) {
}
}
if (out != null) {
logger.debug("Close serial out stream");
IOUtils.closeQuietly(out);
}
if (in != null) {
logger.debug("Close serial in stream");
IOUtils.closeQuietly(in);
}
if (serialPort != null) {
logger.debug("Close serial port");
serialPort.close();
}
readerThread = null;
serialPort = null;
out = null;
in = null;
logger.debug("Closed");
}
@Override
public void sendMessage(byte[] data) throws IOException {
String str = new String(data, StandardCharsets.UTF_8);
if (out == null) {
throw new IOException("Not connected sending messages is not possible");
}
}
out.write(data);
out.flush();
}
@Override
public void serialEvent(SerialPortEvent arg0) {
try {
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException ignore) {
}
}
}
Running this function once initializes the stick and establishes a permanent connection:
package org.openhab.binding.openwms.connector;
import jssc.SerialPort;
import jssc.SerialPortException;
public class OpenWMSSerialWorkaround {
private static SerialPort serialPort = null;
public static void TestSerial(String port) throws SerialPortException {
serialPort = new SerialPort(port);
final int MAX_CONNECTION = 2;
int reconnections = 0;
boolean scanning = true;
while (scanning && reconnections < MAX_CONNECTION) {
{
reconnections++;
try {
serialPort.openPort();
serialPort.setParams(SerialPort.BAUDRATE_128000, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
scanning = false;
} catch (Exception e) {
e.printStackTrace();
try {
Thread.sleep(2000);// 2 seconds
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}
serialPort = null;
}
}
Does anyone have an idea how I can achieve the same result with the [transport.serial] ?
Any help or hint where I can look for a solution is welcome - thanks in advance.