Skip to content

Commit

Permalink
[openwebnet] Replace gnu.io dependency with serial transport (openhab…
Browse files Browse the repository at this point in the history
…#16376)

Signed-off-by: Massimo Valla <mvcode00@gmail.com>
Signed-off-by: Jørgen Austvik <jaustvik@acm.org>
  • Loading branch information
mvalla authored and austvik committed Mar 27, 2024
1 parent 76018ce commit a097b3d
Show file tree
Hide file tree
Showing 7 changed files with 295 additions and 19 deletions.
6 changes: 1 addition & 5 deletions bundles/org.openhab.binding.openwebnet/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,12 @@

<name>openHAB Add-ons :: Bundles :: OpenWebNet (BTicino/Legrand) Binding</name>

<properties>
<bnd.importpackage>gnu.io;version="[3.12,6)"</bnd.importpackage>
</properties>

<dependencies>

<dependency>
<groupId>io.github.openwebnet4j</groupId>
<artifactId>openwebnet4j</artifactId>
<version>0.10.1</version>
<version>0.12.0</version>
<scope>compile</scope>
</dependency>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants;
import org.openhab.binding.openwebnet.internal.serial.SerialPortProviderAdapter;
import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResult;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
Expand All @@ -44,11 +44,14 @@
import org.slf4j.LoggerFactory;

/**
* The {@link UsbGatewayDiscoveryService} extends {@link AbstractDiscoveryService} to detect Zigbee USB gateways
* connected via serial port. The service will iterate over the available serial ports and open each one to test if a
* OpenWebNet Zigbee USB gateway is connected. On successful connection, a new DiscoveryResult is created.
* The {@link UsbGatewayDiscoveryService} extends
* {@link AbstractDiscoveryService} to detect Zigbee USB gateways connected via
* serial port. The service will iterate over the available serial ports and
* open each one to test if a OpenWebNet Zigbee USB gateway is connected. On
* successful connection, a new DiscoveryResult is created.
*
* @author Massimo Valla - Initial contribution
* @author Massimo Valla - Initial contribution. Inject SerialPortManager to
* openwebnet4j lib.
*/
@NonNullByDefault
@Component(service = DiscoveryService.class, configurationPid = "discovery.openwebnet")
Expand All @@ -64,6 +67,8 @@ public class UsbGatewayDiscoveryService extends AbstractDiscoveryService impleme
private @Nullable ScheduledFuture<?> connectTimeout;

private final SerialPortManager serialPortManager;
private final SerialPortProviderAdapter transportAdapter;

private @Nullable USBGateway zbGateway;

private String currentScannedPortName = "";
Expand All @@ -74,27 +79,35 @@ public class UsbGatewayDiscoveryService extends AbstractDiscoveryService impleme
private boolean scanning;

/**
* Constructs a new UsbGatewayDiscoveryService with the specified Zigbee USB Bridge ThingTypeUID
* Constructs a new UsbGatewayDiscoveryService with the specified Zigbee USB
* Bridge ThingTypeUID
*/
@Activate
public UsbGatewayDiscoveryService(final @Reference SerialPortManager spm) {
super(Set.of(OpenWebNetBindingConstants.THING_TYPE_ZB_GATEWAY), DISCOVERY_TIMEOUT_SECONDS, false);
// Obtain the serial port manager service using an OSGi reference
// Inject the SerialPortManager passed via @Reference into the adapter
serialPortManager = spm;
SerialPortProviderAdapter.setSerialPortManager(spm);
this.transportAdapter = new SerialPortProviderAdapter();
logger.debug("**** -SPI- **** Set SerialPortManager to: {}", SerialPortProviderAdapter.serialPortManager);
}

/**
* Starts a new discovery scan. All available Serial Ports are scanned.
* Starts a new discovery scan. All available SerialPortsIdentifiers returned by
* SerialPortManager are scanned.
*/
@Override
protected void startScan() {
logger.debug("Started OpenWebNet Zigbee USB Gateway discovery scan");
removeOlderResults(getTimestampOfLastScan());
scanning = true;
Stream<SerialPortIdentifier> portEnum = serialPortManager.getIdentifiers();

SerialPortIdentifier[] foundSerialPortIds = serialPortManager.getIdentifiers()
.toArray(SerialPortIdentifier[]::new);

// Check each available serial port
try {
for (SerialPortIdentifier portIdentifier : portEnum.toArray(SerialPortIdentifier[]::new)) {
for (SerialPortIdentifier portIdentifier : foundSerialPortIds) {
if (scanning) {
currentScannedPortName = portIdentifier.getName();
logger.debug("[{}] == checking serial port", currentScannedPortName);
Expand All @@ -104,6 +117,7 @@ protected void startScan() {
} else {
logger.debug("[{}] trying to connect to a Zigbee USB Gateway...", currentScannedPortName);
USBGateway gw = new USBGateway(currentScannedPortName);
gw.setSerialPortProvider(transportAdapter);
zbGateway = gw;
gw.subscribe(this);
portCheckLatch = new CountDownLatch(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.openhab.binding.openwebnet.internal.discovery.OpenWebNetDeviceDiscoveryService;
import org.openhab.binding.openwebnet.internal.handler.config.OpenWebNetBusBridgeConfig;
import org.openhab.binding.openwebnet.internal.handler.config.OpenWebNetZigBeeBridgeConfig;
import org.openhab.binding.openwebnet.internal.serial.SerialPortProviderAdapter;
import org.openhab.core.config.core.status.ConfigStatusMessage;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID;
Expand Down Expand Up @@ -179,7 +180,11 @@ public void initialize() {
"@text/offline.conf-error-no-serial-port");
return null;
} else {
return new USBGateway(serialPort);
USBGateway tmpUSBGateway = new USBGateway(serialPort);
tmpUSBGateway.setSerialPortProvider(new SerialPortProviderAdapter());
logger.debug("**** -SPI- **** OpenWebNetBridgeHandler :: setSerialPortProvider to: {}",
tmpUSBGateway.getSerialPortProvider());
return tmpUSBGateway;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,7 @@ protected Where buildBusWhere(String wStr) throws IllegalArgumentException {
*
* @param channelId the channelId string
**/
@Nullable
private String toWhere(String channelId) {
private String toWhere(String channelId) throws OWNException {
Where w = deviceWhere;
if (w != null) {
OpenWebNetBridgeHandler brH = bridgeHandler;
Expand All @@ -400,6 +399,6 @@ private String toWhere(String channelId) {
}
}
}
return null;
throw new OWNException("Cannot select channel from WHERE " + w);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/**
* 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.binding.openwebnet.internal.serial;

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.PortInUseException;
import org.openhab.core.io.transport.serial.SerialPort;
import org.openhab.core.io.transport.serial.SerialPortEvent;
import org.openhab.core.io.transport.serial.SerialPortEventListener;
import org.openhab.core.io.transport.serial.SerialPortIdentifier;
import org.openhab.core.io.transport.serial.UnsupportedCommOperationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* openwebnet4j SerialPort implementation based on OH serial transport
*
* @author M. Valla - Initial contribution
*/

@NonNullByDefault
public class SerialPortAdapter implements org.openwebnet4j.communication.serial.spi.SerialPort {

private static final Logger logger = LoggerFactory.getLogger(SerialPortAdapter.class);

private static final int OPEN_TIMEOUT_MS = 200;

private final SerialPortIdentifier spid;

private @Nullable SerialPort sp = null;

public SerialPortAdapter(final SerialPortIdentifier spid) {
this.spid = spid;
}

@Override
public boolean setSerialPortParams(int baudrate, int dataBits, int stopBits, int parity) {
@Nullable
SerialPort lsp = sp;
if (lsp != null) {
try {
lsp.setSerialPortParams(baudrate, dataBits, stopBits, parity);
return true;
} catch (UnsupportedCommOperationException e) {
logger.error("UnsupportedCommOperationException while setting port params in setSerialPortParams: {}",
e.getMessage());
return false;
}
}
return false;
}

@Override
public boolean addEventListener(org.openwebnet4j.communication.serial.spi.SerialPortEventListener listener) {
@Nullable
SerialPort lsp = sp;
if (lsp != null) {
try {
lsp.addEventListener(new SerialPortEventListener() {

@Override
public void serialEvent(SerialPortEvent event) {
if (event != null) {
listener.serialEvent(new SerialPortEventAdapter(event));
}
}
});
lsp.notifyOnDataAvailable(true);
return true;
} catch (TooManyListenersException e) {
logger.error("TooManyListenersException while adding event listener: {}", e.getMessage());
}
}
return false;
}

@Override
public boolean open() {
try {
sp = spid.open(this.getClass().getName(), OPEN_TIMEOUT_MS);
} catch (PortInUseException e) {
logger.error("PortInUseException while opening serial port {}: {}", spid.getName(), e.getMessage());
return false;
}
return true;
}

@Override
public @Nullable String getName() {
@Nullable
SerialPort lsp = sp;
if (lsp != null) {
return lsp.getName();
} else {
return null;
}
}

@Override
public @Nullable InputStream getInputStream() throws IOException {
@Nullable
SerialPort lsp = sp;
if (lsp != null) {
return lsp.getInputStream();
} else {
return null;
}
}

@Override
public @Nullable OutputStream getOutputStream() throws IOException {
@Nullable
SerialPort lsp = sp;
if (lsp != null) {
return lsp.getOutputStream();
} else {
return null;
}
}

@Override
public void close() {
@Nullable
SerialPort lsp = sp;
if (lsp != null) {
lsp.close();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* 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.binding.openwebnet.internal.serial;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openwebnet4j.communication.serial.spi.SerialPortEvent;

/**
* openwebnet4j SerialPortEvent implementation based on OH serial transport
*
* @author M. Valla - Initial contribution
*/

@NonNullByDefault
public class SerialPortEventAdapter implements SerialPortEvent {

private final org.openhab.core.io.transport.serial.SerialPortEvent event;

/**
* Constructor.
*
* @param event the underlying event implementation
*/
public SerialPortEventAdapter(org.openhab.core.io.transport.serial.SerialPortEvent event) {
this.event = event;
}

@Override
public int getEventType() {
if (event.getEventType() == org.openhab.core.io.transport.serial.SerialPortEvent.PORT_DISCONNECTED) {
return SerialPortEvent.EVENT_PORT_DISCONNECTED;
} else if (event.getEventType() == org.openhab.core.io.transport.serial.SerialPortEvent.DATA_AVAILABLE) {
return SerialPortEvent.EVENT_DATA_AVAILABLE;
} else {
return event.getEventType();
}
}
}

0 comments on commit a097b3d

Please sign in to comment.