diff --git a/bom/compile/pom.xml b/bom/compile/pom.xml index bea2b608278..9a1554bc90b 100644 --- a/bom/compile/pom.xml +++ b/bom/compile/pom.xml @@ -294,6 +294,12 @@ + + com.fazecast + jSerialComm + 2.10.4 + compile + com.neuronrobotics nrjavaserial diff --git a/bom/openhab-core/pom.xml b/bom/openhab-core/pom.xml index 905bfb7e0fd..ffaed9e53b3 100644 --- a/bom/openhab-core/pom.xml +++ b/bom/openhab-core/pom.xml @@ -262,6 +262,12 @@ ${project.version} compile + + org.openhab.core.bundles + org.openhab.core.io.transport.serial.jserialcomm + ${project.version} + compile + org.openhab.core.bundles org.openhab.core.io.transport.serial.rxtx diff --git a/bundles/org.openhab.core.io.transport.serial.jserialcomm/.classpath b/bundles/org.openhab.core.io.transport.serial.jserialcomm/.classpath new file mode 100644 index 00000000000..e9d63b05acb --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.jserialcomm/.classpath @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.core.io.transport.serial.jserialcomm/.project b/bundles/org.openhab.core.io.transport.serial.jserialcomm/.project new file mode 100644 index 00000000000..2d76f85d947 --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.jserialcomm/.project @@ -0,0 +1,23 @@ + + + org.openhab.core.io.transport.serial.rxtx + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/bundles/org.openhab.core.io.transport.serial.jserialcomm/NOTICE b/bundles/org.openhab.core.io.transport.serial.jserialcomm/NOTICE new file mode 100644 index 00000000000..6c17d0d8a45 --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.jserialcomm/NOTICE @@ -0,0 +1,14 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab-core + diff --git a/bundles/org.openhab.core.io.transport.serial.jserialcomm/bnd.bnd b/bundles/org.openhab.core.io.transport.serial.jserialcomm/bnd.bnd new file mode 100644 index 00000000000..4fc04c311a5 --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.jserialcomm/bnd.bnd @@ -0,0 +1,4 @@ +Bundle-SymbolicName: ${project.artifactId} +Import-Package: \ + com.fazecast.jSerialComm;version="[2.11,3)",\ + * diff --git a/bundles/org.openhab.core.io.transport.serial.jserialcomm/pom.xml b/bundles/org.openhab.core.io.transport.serial.jserialcomm/pom.xml new file mode 100644 index 00000000000..0caab1f56bb --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.jserialcomm/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + + org.openhab.core.bundles + org.openhab.core.reactor.bundles + 4.2.0-SNAPSHOT + + + org.openhab.core.io.transport.serial.jserialcomm + + openHAB Core :: Bundles :: Serial Transport for jSerialComm + + + + org.openhab.core.bundles + org.openhab.core.io.transport.serial + ${project.version} + + + + com.fazecast + jSerialComm + [2.11.0,3.0.0) + + + + + diff --git a/bundles/org.openhab.core.io.transport.serial.jserialcomm/src/main/java/org/openhab/core/io/transport/serial/jserialcomm/JSerialCommSerialPort.java b/bundles/org.openhab.core.io.transport.serial.jserialcomm/src/main/java/org/openhab/core/io/transport/serial/jserialcomm/JSerialCommSerialPort.java new file mode 100644 index 00000000000..5247bd7cb58 --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.jserialcomm/src/main/java/org/openhab/core/io/transport/serial/jserialcomm/JSerialCommSerialPort.java @@ -0,0 +1,400 @@ +/** + * Copyright (c) 2010-2024 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.core.io.transport.serial.jserialcomm; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.TooManyListenersException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.io.transport.serial.SerialPort; +import org.openhab.core.io.transport.serial.SerialPortEventListener; +import org.openhab.core.io.transport.serial.UnsupportedCommOperationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Specific OH serial transport SerialPort implementation using com.fazecast.jSerialComm.SerialPort. + * + * @author Massimo Valla - Initial contribution + */ +@NonNullByDefault +public class JSerialCommSerialPort implements SerialPort { + + private final Logger logger = LoggerFactory.getLogger(JSerialCommSerialPort.class); + + private final com.fazecast.jSerialComm.SerialPort sp; + + private boolean notifyOnDataAvailable = false; + private boolean notifyOnBreakInterrupt = false; + private boolean notifyOnFramingError = false; + private boolean notifyOnOverrunError = false; + private boolean notifyOnParityError = false; + private boolean notifyOnOutputEmpty = false; + private boolean notifyOnCTS = false; + private boolean notifyOnDSR = false; + private boolean notifyOnRingIndicator = false; + private boolean notifyOnCarrierDetect = false; + + private @Nullable SerialPortEventListener eventListener; + + /** + * Constructor. + * + * @param sp the underlying serial port implementation + */ + public JSerialCommSerialPort(final com.fazecast.jSerialComm.SerialPort sp) { + this.sp = sp; + } + + @Override + public void close() { + sp.closePort(); + } + + @Override + public void setSerialPortParams(int baudrate, int dataBits, int stopBits, int parity) + throws UnsupportedCommOperationException { + if (!sp.setComPortParameters(baudrate, dataBits, stopBits, parity)) { + throw new UnsupportedCommOperationException(); + } + } + + @Override + public @Nullable InputStream getInputStream() throws IOException { + return sp.getInputStream(); + } + + @Override + public @Nullable OutputStream getOutputStream() throws IOException { + return sp.getOutputStream(); + } + + private int combineListeningEvents() { + // FIXME just use compact version below + int combined = 0; + if (notifyOnDataAvailable) { + combined = combined | com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_DATA_AVAILABLE; + logger.debug("--------TRANSPORT-jSerialComm--- subscribed notifyOnDataAvailable({}) - combined now is: {}", + com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_DATA_AVAILABLE, combined); + } + if (notifyOnBreakInterrupt) { + combined = combined | com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_BREAK_INTERRUPT; + logger.debug("--------TRANSPORT-jSerialComm--- subscribed notifyOnBreakInterrupt({}) - combined now is: {}", + com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_BREAK_INTERRUPT, combined); + } + if (notifyOnFramingError) { + combined = combined | com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_FRAMING_ERROR; + logger.debug("--------TRANSPORT-jSerialComm--- subscribed notifyOnFramingError({}) - combined now is: {}", + com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_FRAMING_ERROR, combined); + } + if (notifyOnOverrunError) { + combined = combined | com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_FIRMWARE_OVERRUN_ERROR; + logger.debug("--------TRANSPORT-jSerialComm--- subscribed notifyOnOverrunError({}) - combined now is: {}", + com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_FIRMWARE_OVERRUN_ERROR, combined); + } + if (notifyOnParityError) { + combined = combined | com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_PARITY_ERROR; + logger.debug("--------TRANSPORT-jSerialComm--- subscribed notifyOnParityError({}) - combined now is: {}", + com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_PARITY_ERROR, combined); + } + if (notifyOnOutputEmpty) { + combined = combined | com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_DATA_WRITTEN; + logger.debug("--------TRANSPORT-jSerialComm--- subscribed notifyOnOutputEmpty({}) - combined now is: {}", + com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_DATA_WRITTEN, combined); + } + if (notifyOnCTS) { + combined = combined | com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_CTS; + logger.debug("--------TRANSPORT-jSerialComm--- subscribed notifyOnCTS({}) - combined now is: {}", + com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_CTS, combined); + } + if (notifyOnDSR) { + combined = combined | com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_DSR; + logger.debug("--------TRANSPORT-jSerialComm--- subscribed notifyOnDSR({}) - combined now is: {}", + com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_DSR, combined); + } + if (notifyOnRingIndicator) { + combined = combined | com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_RING_INDICATOR; + logger.debug("--------TRANSPORT-jSerialComm--- subscribed notifyOnRingIndicator({}) - combined now is: {}", + com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_RING_INDICATOR, combined); + } + if (notifyOnCarrierDetect) { + combined = combined | com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_CARRIER_DETECT; + logger.debug("--------TRANSPORT-jSerialComm--- subscribed notifyOnCarrierDetect({}) - combined now is: {}", + com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_CARRIER_DETECT, combined); + } + + combined = combined | com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_PORT_DISCONNECTED; + logger.debug( + "--------TRANSPORT-jSerialComm--- subscribed LISTENING_EVENT_PORT_DISCONNECTED({}) - combined now is: {}", + com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_PORT_DISCONNECTED, combined); + + logger.debug("--------TRANSPORT-jSerialComm--- FINAL combined is: {}", combined); + + return combined; + + /* + * return com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_PORT_DISCONNECTED + * | (notifyOnDataAvailable ? com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_DATA_AVAILABLE : 0) + * | (notifyOnBreakInterrupt ? com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_BREAK_INTERRUPT : 0) + * | (notifyOnFramingError ? com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_FRAMING_ERROR : 0) + * | (notifyOnOverrunError ? com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_FIRMWARE_OVERRUN_ERROR + * : 0) + * | (notifyOnParityError ? com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_PARITY_ERROR : 0) + * | (notifyOnOutputEmpty ? com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_DATA_WRITTEN : 0) + * | (notifyOnCTS ? com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_CTS : 0) + * | (notifyOnDSR ? com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_DSR : 0) + * | (notifyOnRingIndicator ? com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_RING_INDICATOR : 0) + * | (notifyOnCarrierDetect ? com.fazecast.jSerialComm.SerialPort.LISTENING_EVENT_CARRIER_DETECT : 0); + */ + } + + @Override + public void addEventListener(SerialPortEventListener listener) throws TooManyListenersException { + boolean success = sp.addDataListener(new com.fazecast.jSerialComm.SerialPortDataListener() { + @Override + public void serialEvent(final com.fazecast.jSerialComm.@Nullable SerialPortEvent event) { + if (event == null) { + return; + } + listener.serialEvent(new JSerialCommSerialPortEvent(event)); + } + + @Override + public int getListeningEvents() { + int subscribedEvents = combineListeningEvents(); + logger.debug("--------TRANSPORT-jSerialComm--- {} is subscribed to events: {}", this.toString(), + subscribedEvents); + return subscribedEvents; + } + }); + if (!success) { + logger.error("--------TRANSPORT-jSerialComm--- Could not add SerialPortDataListener to SerialPort {}", + sp.getSystemPortName()); + throw new TooManyListenersException( + ("Could not add SerialPortDataListener to SerialPort " + sp.getSystemPortName())); + } + eventListener = listener; + } + + // private method to refresh listener (if exists) in order to refresh subscriptions to lib + private synchronized void refreshListener() { + SerialPortEventListener eL = eventListener; + if (eL != null) { + sp.removeDataListener(); + try { + this.addEventListener(eL); + logger.debug("--------TRANSPORT-jSerialComm--- LISTENER REFRESHED!"); + + } catch (TooManyListenersException e) { + logger.error("--------TRANSPORT-jSerialComm--- Could not add SerialPortDataListener to SerialPort {}", + sp.getSystemPortName()); + } + } + } + + @Override + public void removeEventListener() { + sp.removeDataListener(); + } + + @Override + public void notifyOnDataAvailable(boolean enable) { + this.notifyOnDataAvailable = enable; + refreshListener(); + } + + @Override + public void notifyOnBreakInterrupt(boolean enable) { + this.notifyOnBreakInterrupt = enable; + refreshListener(); + } + + @Override + public void notifyOnFramingError(boolean enable) { + this.notifyOnFramingError = enable; + refreshListener(); + } + + @Override + public void notifyOnOverrunError(boolean enable) { + this.notifyOnOverrunError = enable; + refreshListener(); + } + + @Override + public void notifyOnParityError(boolean enable) { + this.notifyOnParityError = enable; + refreshListener(); + } + + @Override + public void setRTS(boolean enable) { + if (enable) { + sp.setRTS(); + } else { + sp.clearRTS(); + } + } + + @Override + public void enableReceiveTimeout(int timeout) throws UnsupportedCommOperationException { + if (timeout < 0) { + throw new IllegalArgumentException(String.format("timeout must be non negative (is: %d)", timeout)); + } + // FIXME !!!!! placeholder implementation + boolean success = sp.setComPortTimeouts(com.fazecast.jSerialComm.SerialPort.TIMEOUT_READ_BLOCKING, timeout, 0); + if (!success) { + throw new UnsupportedCommOperationException(); + } + } + + @Override + public void disableReceiveTimeout() { + // FIXME !!!!! placeholder implementation + sp.setComPortTimeouts(com.fazecast.jSerialComm.SerialPort.TIMEOUT_NONBLOCKING, 0, 0); + } + + @Override + public String getName() { + String sysPortName = sp.getSystemPortName(); + if (sysPortName != null && sysPortName.startsWith("COM")) { + return sysPortName; + } else { + return sp.getSystemPortPath(); + } + } + + @Override + public void setFlowControlMode(int flowcontrolRtsctsOut) throws UnsupportedCommOperationException { + // FIXME check mapping + if (!sp.setFlowControl(flowcontrolRtsctsOut)) { + throw new UnsupportedCommOperationException(); + } + } + + @Override + public void enableReceiveThreshold(int i) throws UnsupportedCommOperationException { + // FIXME !!!!! placeholder implementation + /* + * try { + * sp.enableReceiveThreshold(i); + * } catch (gnu.io.UnsupportedCommOperationException e) { + * throw new UnsupportedCommOperationException(e); + * } + */ + } + + @Override + public int getBaudRate() { + return sp.getBaudRate(); + } + + @Override + public int getDataBits() { + return sp.getNumDataBits(); + } + + @Override + public int getStopBits() { + return sp.getNumStopBits(); + } + + @Override + public int getParity() { + return sp.getParity(); + } + + @Override + public void notifyOnOutputEmpty(boolean enable) { + this.notifyOnOutputEmpty = enable; + refreshListener(); + } + + @Override + public void notifyOnCTS(boolean enable) { + this.notifyOnCTS = enable; + refreshListener(); + } + + @Override + public void notifyOnDSR(boolean enable) { + this.notifyOnDSR = enable; + refreshListener(); + } + + @Override + public void notifyOnRingIndicator(boolean enable) { + this.notifyOnRingIndicator = enable; + } + + @Override + public void notifyOnCarrierDetect(boolean enable) { + this.notifyOnCarrierDetect = enable; + refreshListener(); + } + + @Override + public int getFlowControlMode() { + // FIXME check mapping + return sp.getFlowControlSettings(); + } + + @Override + public boolean isRTS() { + return sp.getRTS(); + } + + @Override + public void setDTR(boolean state) { + if (state) { + sp.setDTR(); + } else { + sp.clearDTR(); + } + } + + @Override + public boolean isDTR() { + return sp.getDTR(); + } + + @Override + public boolean isCTS() { + return sp.getCTS(); + } + + @Override + public boolean isDSR() { + return sp.getDSR(); + } + + @Override + public boolean isCD() { + return sp.getDCD(); + } + + @Override + public boolean isRI() { + return sp.getRI(); + } + + @Override + public void sendBreak(int duration) { + // FIXME !!!!! placeholder implementation. Remove from OH serial transport since it's not used by any binding?? + sp.setBreak(); + // sp.sendBreak(duration); + } +} diff --git a/bundles/org.openhab.core.io.transport.serial.jserialcomm/src/main/java/org/openhab/core/io/transport/serial/jserialcomm/JSerialCommSerialPortEvent.java b/bundles/org.openhab.core.io.transport.serial.jserialcomm/src/main/java/org/openhab/core/io/transport/serial/jserialcomm/JSerialCommSerialPortEvent.java new file mode 100644 index 00000000000..fb9ec1434ba --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.jserialcomm/src/main/java/org/openhab/core/io/transport/serial/jserialcomm/JSerialCommSerialPortEvent.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2010-2024 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.core.io.transport.serial.jserialcomm; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.io.transport.serial.SerialPortEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Specific OH serial transport SerialPortEvent implementation using com.fazecast.jSerialComm.SerialPortEvent + * + * @author Massimo Valla - Initial contribution + */ +@NonNullByDefault +public class JSerialCommSerialPortEvent implements SerialPortEvent { + + private final Logger logger = LoggerFactory.getLogger(JSerialCommSerialPortEvent.class); + + private final com.fazecast.jSerialComm.SerialPortEvent event; + + /** + * Constructor. + * + * @param event the underlying event implementation + */ + public JSerialCommSerialPortEvent(final com.fazecast.jSerialComm.SerialPortEvent event) { + logger.debug("--------TRANSPORT-jSerialComm--- New event of type: {}", event.getEventType()); + this.event = event; + } + + @Override + public int getEventType() { + // FIXME check event id mapping + return event.getEventType(); + } + + @Override + public boolean getNewValue() { + // FIXME !!!!! placeholder implementation + return false; + // return event.getNewValue(); + } +} diff --git a/bundles/org.openhab.core.io.transport.serial.jserialcomm/src/main/java/org/openhab/core/io/transport/serial/jserialcomm/JSerialCommSerialPortIdentifier.java b/bundles/org.openhab.core.io.transport.serial.jserialcomm/src/main/java/org/openhab/core/io/transport/serial/jserialcomm/JSerialCommSerialPortIdentifier.java new file mode 100644 index 00000000000..3178ebbaaff --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.jserialcomm/src/main/java/org/openhab/core/io/transport/serial/jserialcomm/JSerialCommSerialPortIdentifier.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2010-2024 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.core.io.transport.serial.jserialcomm; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.io.transport.serial.PortInUseException; +import org.openhab.core.io.transport.serial.SerialPort; +import org.openhab.core.io.transport.serial.SerialPortIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Specific OH serial transport SerialPortIdentifier implementation using com.fazecast.jSerialComm.SerialPort + * + * @author Massimo Valla - Initial contribution + */ +@NonNullByDefault +public class JSerialCommSerialPortIdentifier implements SerialPortIdentifier { + + private final Logger logger = LoggerFactory.getLogger(JSerialCommSerialPortIdentifier.class); + + final com.fazecast.jSerialComm.SerialPort sp; + + private @Nullable String owner; + + /** + * Constructor. + * + * @param sp + */ + public JSerialCommSerialPortIdentifier(final com.fazecast.jSerialComm.SerialPort sp) { + this.sp = sp; + } + + @Override + public String getName() { + final String sysPortName = sp.getSystemPortName(); + if (sysPortName != null && sysPortName.startsWith("COM")) { + return sysPortName; + } else { + return sp.getSystemPortPath(); + } + // return name != null ? name : ""; + } + + @Override + public SerialPort open(String owner, int timeout) throws PortInUseException { + logger.debug("--------TRANSPORT-jSerialComm--- SerialPort.getReadTimeout() = {}", sp.getReadTimeout()); + logger.debug("--------TRANSPORT-jSerialComm--- SerialPort.getPortDescription() = {}", sp.getPortDescription()); + boolean success = sp.openPort(); + if (success) { + this.owner = owner; + return new JSerialCommSerialPort(sp); + } else { + logger.error("--------TRANSPORT-jSerialComm--- Could not open port: {}", getName()); + throw new PortInUseException(new Exception("Could not open port: " + getName())); + } + } + + @Override + public boolean isCurrentlyOwned() { + return (owner != null); + } + + @Override + public @Nullable String getCurrentOwner() { + return owner; + } +} diff --git a/bundles/org.openhab.core.io.transport.serial.jserialcomm/src/main/java/org/openhab/core/io/transport/serial/jserialcomm/JSerialCommSerialPortProvider.java b/bundles/org.openhab.core.io.transport.serial.jserialcomm/src/main/java/org/openhab/core/io/transport/serial/jserialcomm/JSerialCommSerialPortProvider.java new file mode 100644 index 00000000000..e50f06444fe --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.jserialcomm/src/main/java/org/openhab/core/io/transport/serial/jserialcomm/JSerialCommSerialPortProvider.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2010-2024 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.core.io.transport.serial.jserialcomm; + +import java.net.URI; +import java.util.Arrays; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.io.transport.serial.ProtocolType; +import org.openhab.core.io.transport.serial.ProtocolType.PathType; +import org.openhab.core.io.transport.serial.SerialPortIdentifier; +import org.openhab.core.io.transport.serial.SerialPortProvider; +import org.osgi.service.component.annotations.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fazecast.jSerialComm.SerialPort; +import com.fazecast.jSerialComm.SerialPortInvalidPortException; + +/** + * Specific OH serial transport SerialPortProvider implementation using com.fazecast.jSerialComm.SerialPort + * + * @author Massimo Valla - Initial contribution + */ +@NonNullByDefault +@Component(service = SerialPortProvider.class) +public class JSerialCommSerialPortProvider implements SerialPortProvider { + + private final Logger logger = LoggerFactory.getLogger(JSerialCommSerialPortProvider.class); + + @Override + public @Nullable SerialPortIdentifier getPortIdentifier(URI port) { + String portPathAsString = port.getPath(); + try { + SerialPort spFound = SerialPort.getCommPort(portPathAsString); + return new JSerialCommSerialPortIdentifier(spFound); + } catch (SerialPortInvalidPortException e) { + logger.debug( + "--------TRANSPORT-jSerialComm--- No SerialPort found for: {} (SerialPortInvalidPortException: {})", + portPathAsString, e.getMessage()); + return null; + } + } + + @Override + public Stream getAcceptedProtocols() { + return Stream.of(new ProtocolType(PathType.LOCAL, "jserialcomm")); + } + + @Override + public Stream getSerialPortIdentifiers() { + com.fazecast.jSerialComm.SerialPort[] portsArray = com.fazecast.jSerialComm.SerialPort.getCommPorts(); + logger.debug("--------TRANSPORT-jSerialComm--- getSerialPortIdentifiers() :: Listing found ports:"); + for (com.fazecast.jSerialComm.SerialPort port : portsArray) { + logger.debug("--------TRANSPORT-jSerialComm--- port: {} ({} - {})", port.getSystemPortName(), + port.getSystemPortPath(), port.getPortDescription()); + } + logger.debug("--------TRANSPORT-jSerialComm--- ...finished listing found ports."); + + Stream ports = Arrays.stream(portsArray); + + return ports.map(sid -> new JSerialCommSerialPortIdentifier(sid)); + } +} diff --git a/bundles/pom.xml b/bundles/pom.xml index 59da5879650..fa91d3aeb50 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -81,6 +81,7 @@ org.openhab.core.io.transport.mqtt org.openhab.core.io.transport.serial org.openhab.core.io.transport.serial.javacomm + org.openhab.core.io.transport.serial.jserialcomm org.openhab.core.io.transport.serial.rxtx org.openhab.core.io.transport.serial.rxtx.rfc2217 org.openhab.core.io.transport.upnp