diff --git a/bom/openhab-core/pom.xml b/bom/openhab-core/pom.xml index 1bea7c150d..df656f34fe 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.purejavacomm + ${project.version} + compile + org.openhab.core.bundles org.openhab.core.io.transport.serial.rxtx diff --git a/bundles/org.openhab.core.io.transport.serial.purejavacomm/.classpath b/bundles/org.openhab.core.io.transport.serial.purejavacomm/.classpath new file mode 100644 index 0000000000..af4894f181 --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.purejavacomm/.classpath @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.core.io.transport.serial.purejavacomm/.project b/bundles/org.openhab.core.io.transport.serial.purejavacomm/.project new file mode 100644 index 0000000000..0efc39652e --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.purejavacomm/.project @@ -0,0 +1,34 @@ + + + org.openhab.core.io.transport.serial.javacomm + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + + + 1684860371393 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + + diff --git a/bundles/org.openhab.core.io.transport.serial.purejavacomm/NOTICE b/bundles/org.openhab.core.io.transport.serial.purejavacomm/NOTICE new file mode 100644 index 0000000000..6c17d0d8a4 --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.purejavacomm/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.purejavacomm/pom.xml b/bundles/org.openhab.core.io.transport.serial.purejavacomm/pom.xml new file mode 100644 index 0000000000..125325fe89 --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.purejavacomm/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + + org.openhab.core.bundles + org.openhab.core.reactor.bundles + 4.0.0-SNAPSHOT + + + org.openhab.core.io.transport.serial.purejavacomm + + openHAB Core :: Bundles :: Serial Transport for Pure Java Communications API + + + + org.openhab.core.bundles + org.openhab.core.io.transport.serial + ${project.version} + + + org.opensmarthouse + purejavacomm + 1.0.5 + + + diff --git a/bundles/org.openhab.core.io.transport.serial.purejavacomm/src/main/java/org/openhab/core/io/transport/serial/internal/PureJavaCommPortProvider.java b/bundles/org.openhab.core.io.transport.serial.purejavacomm/src/main/java/org/openhab/core/io/transport/serial/internal/PureJavaCommPortProvider.java new file mode 100644 index 0000000000..c4514c199e --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.purejavacomm/src/main/java/org/openhab/core/io/transport/serial/internal/PureJavaCommPortProvider.java @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2010-2023 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.internal; + +import java.net.URI; +import java.util.Enumeration; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.function.Consumer; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +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 purejavacomm.CommPortIdentifier; +import purejavacomm.NoSuchPortException; + +/** + * + * @author Łukasz Dywicki - Initial contribution + * @author Karel Goderis - added further methods + */ +@NonNullByDefault +@Component(service = SerialPortProvider.class) +public class PureJavaCommPortProvider implements SerialPortProvider { + + private final Logger logger = LoggerFactory.getLogger(PureJavaCommPortProvider.class); + + @Override + public @Nullable SerialPortIdentifier getPortIdentifier(URI port) { + CommPortIdentifier ident = null; + try { + ident = CommPortIdentifier.getPortIdentifier(port.getPath()); + } catch (NoSuchPortException e) { + logger.debug("No SerialPortIdentifier found for: {}", port.getPath()); + return null; + } + return new SerialPortIdentifierImpl(ident); + } + + @Override + public Stream getAcceptedProtocols() { + return Stream.of(new ProtocolType(PathType.LOCAL, "purejavacomm")); + } + + @Override + public Stream getSerialPortIdentifiers() { + @SuppressWarnings("unchecked") + final Enumeration ids = CommPortIdentifier.getPortIdentifiers(); + return StreamSupport.stream(new SplitIteratorForEnumeration<>(ids), false) + .filter(id -> id.getPortType() == CommPortIdentifier.PORT_SERIAL) + .map(sid -> new SerialPortIdentifierImpl(sid)); + } + + private static class SplitIteratorForEnumeration extends Spliterators.AbstractSpliterator { + private final Enumeration e; + + public SplitIteratorForEnumeration(final Enumeration e) { + super(Long.MAX_VALUE, Spliterator.ORDERED); + this.e = e; + } + + @Override + @NonNullByDefault({}) + public boolean tryAdvance(Consumer action) { + if (e.hasMoreElements()) { + action.accept(e.nextElement()); + return true; + } + return false; + } + + @Override + @NonNullByDefault({}) + public void forEachRemaining(Consumer action) { + while (e.hasMoreElements()) { + action.accept(e.nextElement()); + } + } + } +} diff --git a/bundles/org.openhab.core.io.transport.serial.purejavacomm/src/main/java/org/openhab/core/io/transport/serial/internal/SerialPortEventImpl.java b/bundles/org.openhab.core.io.transport.serial.purejavacomm/src/main/java/org/openhab/core/io/transport/serial/internal/SerialPortEventImpl.java new file mode 100644 index 0000000000..e2c6ad6dd2 --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.purejavacomm/src/main/java/org/openhab/core/io/transport/serial/internal/SerialPortEventImpl.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2010-2023 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.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.io.transport.serial.SerialPortEvent; + +/** + * Specific serial port event implementation. + * + * @author Łukasz Dywicki - Initial contribution + * @author Karel Goderis - added further methods + */ +@NonNullByDefault +public class SerialPortEventImpl implements SerialPortEvent { + + private final purejavacomm.SerialPortEvent event; + + /** + * Constructor. + * + * @param event the underlying event implementation + */ + public SerialPortEventImpl(final purejavacomm.SerialPortEvent event) { + this.event = event; + } + + @Override + public int getEventType() { + return event.getEventType(); + } + + @Override + public boolean getNewValue() { + return event.getNewValue(); + } +} diff --git a/bundles/org.openhab.core.io.transport.serial.purejavacomm/src/main/java/org/openhab/core/io/transport/serial/internal/SerialPortIdentifierImpl.java b/bundles/org.openhab.core.io.transport.serial.purejavacomm/src/main/java/org/openhab/core/io/transport/serial/internal/SerialPortIdentifierImpl.java new file mode 100644 index 0000000000..45f024ab42 --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.purejavacomm/src/main/java/org/openhab/core/io/transport/serial/internal/SerialPortIdentifierImpl.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2010-2023 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.internal; + +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 purejavacomm.CommPortIdentifier; + +/** + * Specific serial port identifier implementation. + * + * @author Łukasz Dywicki - Initial contribution + * @author Karel Goderis - added further methods + */ +@NonNullByDefault +public class SerialPortIdentifierImpl implements SerialPortIdentifier { + + final CommPortIdentifier id; + + /** + * Constructor. + * + * @param id the underlying comm port identifier implementation + */ + public SerialPortIdentifierImpl(final CommPortIdentifier id) { + this.id = id; + } + + @Override + public String getName() { + final String name = id.getName(); + return name != null ? name : ""; + } + + @Override + public SerialPort open(String owner, int timeout) throws PortInUseException { + + try { + return new SerialPortImpl((purejavacomm.SerialPort) id.open(owner, timeout)); + } catch (purejavacomm.PortInUseException e) { + String message = e.getMessage(); + if (message != null) { + throw new PortInUseException(message, e); + } else { + throw new PortInUseException(e); + } + } + } + + @Override + public boolean isCurrentlyOwned() { + return id.isCurrentlyOwned(); + } + + @Override + public @Nullable String getCurrentOwner() { + return id.getCurrentOwner(); + } + + public String toString() { + return getName() + " (pure java comm)"; + } +} diff --git a/bundles/org.openhab.core.io.transport.serial.purejavacomm/src/main/java/org/openhab/core/io/transport/serial/internal/SerialPortImpl.java b/bundles/org.openhab.core.io.transport.serial.purejavacomm/src/main/java/org/openhab/core/io/transport/serial/internal/SerialPortImpl.java new file mode 100644 index 0000000000..bbdff194ee --- /dev/null +++ b/bundles/org.openhab.core.io.transport.serial.purejavacomm/src/main/java/org/openhab/core/io/transport/serial/internal/SerialPortImpl.java @@ -0,0 +1,260 @@ +/** + * Copyright (c) 2010-2023 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.internal; + +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 purejavacomm.SerialPortEvent; + +/** + * Specific serial port implementation. + * + * @author Łukasz Dywicki - Initial contribution + * @author Karel Goderis - added further methods + */ +@NonNullByDefault +public class SerialPortImpl implements SerialPort { + + private final purejavacomm.SerialPort sp; + + /** + * Constructor. + * + * @param sp the underlying serial port implementation + */ + public SerialPortImpl(final purejavacomm.SerialPort sp) { + this.sp = sp; + } + + @Override + public void close() { + sp.close(); + } + + @Override + public void setSerialPortParams(int baudrate, int dataBits, int stopBits, int parity) + throws UnsupportedCommOperationException { + try { + sp.setSerialPortParams(baudrate, dataBits, stopBits, parity); + } catch (purejavacomm.UnsupportedCommOperationException ex) { + throw new UnsupportedCommOperationException(ex); + } + } + + @Override + public @Nullable InputStream getInputStream() throws IOException { + return sp.getInputStream(); + } + + @Override + public @Nullable OutputStream getOutputStream() throws IOException { + return sp.getOutputStream(); + } + + @Override + public void addEventListener(SerialPortEventListener listener) throws TooManyListenersException { + sp.addEventListener(new purejavacomm.SerialPortEventListener() { + @Override + public void serialEvent(final @Nullable SerialPortEvent event) { + if (event == null) { + return; + } + listener.serialEvent(new org.openhab.core.io.transport.serial.SerialPortEvent() { + @Override + public int getEventType() { + return event.getEventType(); + } + + @Override + public boolean getNewValue() { + return event.getNewValue(); + } + }); + } + }); + } + + @Override + public void removeEventListener() { + sp.removeEventListener(); + } + + @Override + public void notifyOnDataAvailable(boolean enable) { + sp.notifyOnDataAvailable(enable); + } + + @Override + public void notifyOnBreakInterrupt(boolean enable) { + sp.notifyOnBreakInterrupt(enable); + } + + @Override + public void notifyOnFramingError(boolean enable) { + sp.notifyOnFramingError(enable); + } + + @Override + public void notifyOnOverrunError(boolean enable) { + sp.notifyOnOverrunError(enable); + } + + @Override + public void notifyOnParityError(boolean enable) { + sp.notifyOnParityError(enable); + } + + @Override + public void enableReceiveTimeout(int timeout) throws UnsupportedCommOperationException { + if (timeout < 0) { + throw new IllegalArgumentException(String.format("timeout must be non negative (is: %d)", timeout)); + } + try { + sp.enableReceiveTimeout(timeout); + } catch (purejavacomm.UnsupportedCommOperationException ex) { + throw new UnsupportedCommOperationException(ex); + } + } + + @Override + public void disableReceiveTimeout() { + sp.disableReceiveTimeout(); + } + + @Override + public String getName() { + return sp.getName(); + } + + @Override + public void setFlowControlMode(int flowcontrolRtsctsOut) throws UnsupportedCommOperationException { + try { + sp.setFlowControlMode(flowcontrolRtsctsOut); + } catch (purejavacomm.UnsupportedCommOperationException e) { + throw new UnsupportedCommOperationException(e); + } + } + + @Override + public void enableReceiveThreshold(int i) throws UnsupportedCommOperationException { + try { + sp.enableReceiveThreshold(i); + } catch (purejavacomm.UnsupportedCommOperationException e) { + throw new UnsupportedCommOperationException(e); + } + } + + @Override + public int getBaudRate() { + return sp.getBaudRate(); + } + + @Override + public int getDataBits() { + return sp.getDataBits(); + } + + @Override + public int getStopBits() { + return sp.getStopBits(); + } + + @Override + public int getParity() { + return sp.getParity(); + } + + @Override + public void notifyOnOutputEmpty(boolean enable) { + sp.notifyOnOutputEmpty(enable); + } + + @Override + public void notifyOnCTS(boolean enable) { + sp.notifyOnCTS(enable); + } + + @Override + public void notifyOnDSR(boolean enable) { + sp.notifyOnDSR(enable); + } + + @Override + public void notifyOnRingIndicator(boolean enable) { + sp.notifyOnRingIndicator(enable); + } + + @Override + public void notifyOnCarrierDetect(boolean enable) { + sp.notifyOnCarrierDetect(enable); + } + + @Override + public int getFlowControlMode() { + return getFlowControlMode(); + } + + @Override + public void setRTS(boolean enable) { + sp.setRTS(enable); + } + + @Override + public boolean isRTS() { + return sp.isRTS(); + } + + @Override + public void setDTR(boolean state) { + sp.setDTR(state); + } + + @Override + public boolean isDTR() { + return sp.isDTR(); + } + + @Override + public boolean isCTS() { + return sp.isCTS(); + } + + @Override + public boolean isDSR() { + return sp.isDSR(); + } + + @Override + public boolean isCD() { + return sp.isCD(); + } + + @Override + public boolean isRI() { + return sp.isRI(); + } + + @Override + public void sendBreak(int duration) { + sp.sendBreak(duration); + } +} diff --git a/bundles/pom.xml b/bundles/pom.xml index c0fac698fa..8f269564e5 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -73,6 +73,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.purejavacomm org.openhab.core.io.transport.serial.rxtx org.openhab.core.io.transport.serial.rxtx.rfc2217 org.openhab.core.io.transport.upnp diff --git a/features/karaf/openhab-core/src/main/feature/feature.xml b/features/karaf/openhab-core/src/main/feature/feature.xml index 5fe065535e..84fd38b89f 100644 --- a/features/karaf/openhab-core/src/main/feature/feature.xml +++ b/features/karaf/openhab-core/src/main/feature/feature.xml @@ -237,6 +237,19 @@ mvn:org.openhab.core.bundles/org.openhab.core.io.transport.serial.javacomm/${project.version} + + req:osgi.native;filter:="(&(osgi.native.osname=MacOSX)(osgi.native.processor=AArch64))" + + openhab-core-base + + openhab.tp;filter:="(&(feature=serial)(impl=purejavacomm))" + openhab.tp-serial-purejavacomm + + mvn:org.openhab.core.bundles/org.openhab.core.io.transport.serial/${project.version} + mvn:org.openhab.core.bundles/org.openhab.core.io.transport.serial.purejavacomm/${project.version} + + + openhab-core-base diff --git a/features/karaf/openhab-tp/src/main/feature/feature.xml b/features/karaf/openhab-tp/src/main/feature/feature.xml index 96bfdbc5a4..7e6efc90c0 100644 --- a/features/karaf/openhab-tp/src/main/feature/feature.xml +++ b/features/karaf/openhab-tp/src/main/feature/feature.xml @@ -232,6 +232,15 @@ mvn:org.eclipse.kura/org.eclipse.soda.dk.comm.x86_64/1.2.201 + + req:osgi.native;filter:="(&(osgi.native.osname=MacOSX)(osgi.native.processor=AArch64))" + + openhab.tp;feature=serial;impl=purejavacomm + openhab.tp-jna + mvn:org.opensmarthouse/purejavacomm/1.0.5 + + + openhab.tp;feature=serial;impl=rxtx mvn:com.neuronrobotics/nrjavaserial/5.2.1.OH1