getSuggestedAddons() {
}
// now check if a process matches the pattern defined in addon.xml
- logger.debug("Checking candidate: {}", candidate.getUID());
+ logger.trace("Checking candidate: {}", candidate.getUID());
for (AddonMatchProperty command : commands) {
logger.trace("Candidate {}, pattern \"{}\"", candidate.getUID(), command.getRegex());
diff --git a/bundles/org.openhab.core.config.discovery.addon.upnp/src/main/java/org/openhab/core/config/discovery/addon/upnp/UpnpAddonFinder.java b/bundles/org.openhab.core.config.discovery.addon.upnp/src/main/java/org/openhab/core/config/discovery/addon/upnp/UpnpAddonFinder.java
index 68925b6ce67..8ef19064bf6 100644
--- a/bundles/org.openhab.core.config.discovery.addon.upnp/src/main/java/org/openhab/core/config/discovery/addon/upnp/UpnpAddonFinder.java
+++ b/bundles/org.openhab.core.config.discovery.addon.upnp/src/main/java/org/openhab/core/config/discovery/addon/upnp/UpnpAddonFinder.java
@@ -188,7 +188,7 @@ && propertyMatches(matchProperties, MODEL_URI, modelURI)
&& propertyMatches(matchProperties, SERIAL_NUMBER, serialNumber)
&& propertyMatches(matchProperties, FRIENDLY_NAME, friendlyName)) {
result.add(candidate);
- logger.debug("Suggested addon found: {}", candidate.getUID());
+ logger.debug("Suggested add-on found: {}", candidate.getUID());
break;
}
}
diff --git a/bundles/org.openhab.core.config.discovery.addon.usb/.classpath b/bundles/org.openhab.core.config.discovery.addon.usb/.classpath
new file mode 100644
index 00000000000..d3d6b3c11b6
--- /dev/null
+++ b/bundles/org.openhab.core.config.discovery.addon.usb/.classpath
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bundles/org.openhab.core.config.discovery.addon.usb/.project b/bundles/org.openhab.core.config.discovery.addon.usb/.project
new file mode 100644
index 00000000000..bf360c9c71e
--- /dev/null
+++ b/bundles/org.openhab.core.config.discovery.addon.usb/.project
@@ -0,0 +1,23 @@
+
+
+ org.openhab.core.config.discovery.addon.usb
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/bundles/org.openhab.core.config.discovery.addon.usb/NOTICE b/bundles/org.openhab.core.config.discovery.addon.usb/NOTICE
new file mode 100644
index 00000000000..6c17d0d8a45
--- /dev/null
+++ b/bundles/org.openhab.core.config.discovery.addon.usb/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.config.discovery.addon.usb/pom.xml b/bundles/org.openhab.core.config.discovery.addon.usb/pom.xml
new file mode 100644
index 00000000000..7ca3bcafc8d
--- /dev/null
+++ b/bundles/org.openhab.core.config.discovery.addon.usb/pom.xml
@@ -0,0 +1,35 @@
+
+
+
+ 4.0.0
+
+
+ org.openhab.core.bundles
+ org.openhab.core.reactor.bundles
+ 4.2.0-SNAPSHOT
+
+
+ org.openhab.core.config.discovery.addon.usb
+
+ openHAB Core :: Bundles :: USB Suggested Add-on Finder
+
+
+
+ org.openhab.core.bundles
+ org.openhab.core.config.discovery.addon
+ ${project.version}
+
+
+ org.openhab.core.bundles
+ org.openhab.core.addon
+ ${project.version}
+
+
+ org.openhab.core.bundles
+ org.openhab.core.config.discovery.usbserial
+ ${project.version}
+
+
+
+
diff --git a/bundles/org.openhab.core.config.discovery.addon.usb/src/main/java/org/openhab/core/config/discovery/addon/usb/UsbAddonFinder.java b/bundles/org.openhab.core.config.discovery.addon.usb/src/main/java/org/openhab/core/config/discovery/addon/usb/UsbAddonFinder.java
new file mode 100644
index 00000000000..2015a1c8914
--- /dev/null
+++ b/bundles/org.openhab.core.config.discovery.addon.usb/src/main/java/org/openhab/core/config/discovery/addon/usb/UsbAddonFinder.java
@@ -0,0 +1,186 @@
+/**
+ * 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.config.discovery.addon.usb;
+
+import static org.openhab.core.config.discovery.addon.AddonFinderConstants.SERVICE_NAME_USB;
+import static org.openhab.core.config.discovery.addon.AddonFinderConstants.SERVICE_TYPE_USB;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.addon.AddonDiscoveryMethod;
+import org.openhab.core.addon.AddonInfo;
+import org.openhab.core.config.discovery.addon.AddonFinder;
+import org.openhab.core.config.discovery.addon.BaseAddonFinder;
+import org.openhab.core.config.discovery.usbserial.UsbSerialDeviceInformation;
+import org.openhab.core.config.discovery.usbserial.UsbSerialDiscovery;
+import org.openhab.core.config.discovery.usbserial.UsbSerialDiscoveryListener;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is a {@link USBAddonFinder} for finding suggested add-ons related to USB devices.
+ *
+ * It supports the following values for the 'match-property' 'name' element:
+ *
product - match on the product description text
+ * manufacturer - match on the device manufacturer text
+ * chipId - match on the chip vendor id plus product id
+ * remote - match on whether the device is connected remotely or locally
+ *
+ * @author Andrew Fiddian-Green - Initial contribution
+ */
+@NonNullByDefault
+@Component(service = AddonFinder.class, name = UsbAddonFinder.SERVICE_NAME)
+public class UsbAddonFinder extends BaseAddonFinder implements UsbSerialDiscoveryListener {
+
+ public static final String SERVICE_TYPE = SERVICE_TYPE_USB;
+ public static final String SERVICE_NAME = SERVICE_NAME_USB;
+
+ /*
+ * Supported 'match-property' names
+ */
+ public static final String PRODUCT = "product";
+ public static final String MANUFACTURER = "manufacturer";
+ public static final String CHIP_ID = "chipId";
+ public static final String REMOTE = "remote";
+
+ public static final Set SUPPORTED_PROPERTIES = Set.of(PRODUCT, MANUFACTURER, CHIP_ID, REMOTE);
+
+ private final Logger logger = LoggerFactory.getLogger(UsbAddonFinder.class);
+ private final Set usbSerialDiscoveries = new CopyOnWriteArraySet<>();
+ private final Map usbDeviceInformations = new ConcurrentHashMap<>();
+
+ @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
+ protected void addUsbSerialDiscovery(UsbSerialDiscovery usbSerialDiscovery) {
+ usbSerialDiscoveries.add(usbSerialDiscovery);
+ usbSerialDiscovery.registerDiscoveryListener(this);
+ usbSerialDiscovery.doSingleScan();
+ }
+
+ protected synchronized void removeUsbSerialDiscovery(UsbSerialDiscovery usbSerialDiscovery) {
+ usbSerialDiscovery.unregisterDiscoveryListener(this);
+ usbSerialDiscoveries.remove(usbSerialDiscovery);
+ }
+
+ @Override
+ public Set getSuggestedAddons() {
+ Set result = new HashSet<>();
+ for (AddonInfo candidate : addonCandidates) {
+ for (AddonDiscoveryMethod method : candidate.getDiscoveryMethods().stream()
+ .filter(method -> SERVICE_TYPE.equals(method.getServiceType())).toList()) {
+ Map matchProperties = method.getMatchProperties().stream()
+ .collect(Collectors.toMap(property -> property.getName(), property -> property.getPattern()));
+
+ Set propertyNames = new HashSet<>(matchProperties.keySet());
+ propertyNames.removeAll(SUPPORTED_PROPERTIES);
+
+ if (!propertyNames.isEmpty()) {
+ logger.warn("Add-on '{}' addon.xml file contains unsupported 'match-property' [{}]",
+ candidate.getUID(), String.join(",", propertyNames));
+ break;
+ }
+
+ logger.trace("Checking candidate: {}", candidate.getUID());
+ for (UsbSerialDeviceInformation device : usbDeviceInformations.values()) {
+ logger.trace("Checking device: {}", device);
+
+ if (propertyMatches(matchProperties, PRODUCT, device.getProduct())
+ && propertyMatches(matchProperties, MANUFACTURER, device.getManufacturer())
+ && propertyMatches(matchProperties, CHIP_ID,
+ getChipId(device.getVendorId(), device.getProductId()))
+ && propertyMatches(matchProperties, REMOTE, String.valueOf(device.getRemote()))) {
+ result.add(candidate);
+ logger.debug("Suggested add-on found: {}", candidate.getUID());
+ break;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ private String getChipId(int vendorId, int productId) {
+ return String.format("%04x:%04x", vendorId, productId);
+ }
+
+ @Override
+ public String getServiceName() {
+ return SERVICE_NAME;
+ }
+
+ /**
+ * Create a unique 33 bit integer map hash key comprising the remote flag in the upper bit, the vendorId in the
+ * middle 16 bits, and the productId in the lower 16 bits.
+ */
+ private long keyOf(UsbSerialDeviceInformation deviceInfo) {
+ return (deviceInfo.getRemote() ? 0x1_0000_0000L : 0) + (deviceInfo.getVendorId() * 0x1_0000L)
+ + deviceInfo.getProductId();
+ }
+
+ /**
+ * Add the discovered USB device information record to our internal map. If there is already an entry in the map
+ * then merge the two sets of data.
+ *
+ * @param discoveredInfo the newly discovered USB device information.
+ */
+ @Override
+ public void usbSerialDeviceDiscovered(UsbSerialDeviceInformation discoveredInfo) {
+ UsbSerialDeviceInformation targetInfo = discoveredInfo;
+ UsbSerialDeviceInformation existingInfo = usbDeviceInformations.get(keyOf(targetInfo));
+
+ if (existingInfo != null) {
+ boolean isMerging = false;
+ String product = existingInfo.getProduct();
+ if (product != null) {
+ product = discoveredInfo.getProduct();
+ isMerging = true;
+ }
+ String manufacturer = existingInfo.getManufacturer();
+ if (manufacturer != null) {
+ manufacturer = discoveredInfo.getManufacturer();
+ isMerging = true;
+ }
+ String serialNumber = existingInfo.getSerialNumber();
+ if (serialNumber != null) {
+ serialNumber = discoveredInfo.getSerialNumber();
+ isMerging = true;
+ }
+ boolean remote = existingInfo.getRemote();
+ if (remote == discoveredInfo.getRemote()) {
+ isMerging = true;
+ }
+ if (isMerging) {
+ targetInfo = new UsbSerialDeviceInformation(discoveredInfo.getVendorId(), discoveredInfo.getProductId(),
+ serialNumber, manufacturer, product, discoveredInfo.getInterfaceNumber(),
+ discoveredInfo.getInterfaceDescription(), discoveredInfo.getSerialPort()).setRemote(remote);
+ }
+ }
+
+ usbDeviceInformations.put(keyOf(targetInfo), targetInfo);
+ }
+
+ @Override
+ public void usbSerialDeviceRemoved(UsbSerialDeviceInformation removedInfo) {
+ usbDeviceInformations.remove(keyOf(removedInfo));
+ }
+}
diff --git a/bundles/org.openhab.core.config.discovery.addon.usb/src/test/java/org/openhab/core/config/discovery/addon/usb/UsbAddonFinderTests.java b/bundles/org.openhab.core.config.discovery.addon.usb/src/test/java/org/openhab/core/config/discovery/addon/usb/UsbAddonFinderTests.java
new file mode 100644
index 00000000000..ad8a305786c
--- /dev/null
+++ b/bundles/org.openhab.core.config.discovery.addon.usb/src/test/java/org/openhab/core/config/discovery/addon/usb/UsbAddonFinderTests.java
@@ -0,0 +1,101 @@
+/**
+ * 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.config.discovery.addon.usb;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestInstance.Lifecycle;
+import org.openhab.core.addon.AddonDiscoveryMethod;
+import org.openhab.core.addon.AddonInfo;
+import org.openhab.core.addon.AddonMatchProperty;
+import org.openhab.core.config.discovery.usbserial.UsbSerialDeviceInformation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.Level;
+
+/**
+ * This contains tests for the {@link UsbAddonFinder} class.
+ *
+ * @author Andrew Fiddian-Green - Initial contribution
+ */
+@NonNullByDefault
+@TestInstance(Lifecycle.PER_CLASS)
+class UsbAddonFinderTests {
+
+ @Test
+ void testSuggestionFinder() {
+ Logger root = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
+ ((ch.qos.logback.classic.Logger) root).setLevel(Level.ERROR);
+
+ AddonMatchProperty matchProperty = new AddonMatchProperty("product", "(?i).*zigbee.*");
+
+ AddonDiscoveryMethod discoveryMethod = new AddonDiscoveryMethod();
+ discoveryMethod.setMatchProperties(List.of(matchProperty)).setServiceType("usb");
+
+ List addons = new ArrayList<>();
+ addons.add(AddonInfo.builder("id", "binding").withName("name").withDescription("description")
+ .withDiscoveryMethods(List.of(discoveryMethod)).build());
+
+ UsbAddonFinder finder = new UsbAddonFinder();
+ finder.setAddonCandidates(addons);
+
+ finder.usbSerialDeviceDiscovered(
+ new UsbSerialDeviceInformation(0x123, 0x234, null, null, null, 0, "n/a", "n/a"));
+
+ Set suggestions = finder.getSuggestedAddons();
+ assertNotNull(suggestions);
+ assertTrue(suggestions.isEmpty());
+
+ finder.usbSerialDeviceDiscovered(
+ new UsbSerialDeviceInformation(0x345, 0x456, null, null, "some zigBEE product", 0, "n/a", "n/a"));
+
+ suggestions = finder.getSuggestedAddons();
+ assertNotNull(suggestions);
+ assertFalse(suggestions.isEmpty());
+ }
+
+ @Test
+ void testBadSyntax() {
+ Logger root = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
+ ((ch.qos.logback.classic.Logger) root).setLevel(Level.ERROR);
+
+ AddonMatchProperty matchProperty = new AddonMatchProperty("aardvark", "(?i).*zigbee.*");
+
+ AddonDiscoveryMethod discoveryMethod = new AddonDiscoveryMethod();
+ discoveryMethod.setMatchProperties(List.of(matchProperty)).setServiceType("usb");
+
+ List addons = new ArrayList<>();
+ addons.add(AddonInfo.builder("id", "binding").withName("name").withDescription("description")
+ .withDiscoveryMethods(List.of(discoveryMethod)).build());
+
+ UsbAddonFinder finder = new UsbAddonFinder();
+ finder.setAddonCandidates(addons);
+
+ finder.usbSerialDeviceDiscovered(
+ new UsbSerialDeviceInformation(0x123, 0x234, null, null, null, 0, "n/a", "n/a"));
+
+ Set suggestions = finder.getSuggestedAddons();
+ assertNotNull(suggestions);
+ assertTrue(suggestions.isEmpty());
+ }
+}
diff --git a/bundles/org.openhab.core.config.discovery.addon/src/main/java/org/openhab/core/config/discovery/addon/AddonFinderConstants.java b/bundles/org.openhab.core.config.discovery.addon/src/main/java/org/openhab/core/config/discovery/addon/AddonFinderConstants.java
index d282be84b54..a72764f6ce4 100644
--- a/bundles/org.openhab.core.config.discovery.addon/src/main/java/org/openhab/core/config/discovery/addon/AddonFinderConstants.java
+++ b/bundles/org.openhab.core.config.discovery.addon/src/main/java/org/openhab/core/config/discovery/addon/AddonFinderConstants.java
@@ -43,10 +43,17 @@ public class AddonFinderConstants {
public static final String SERVICE_NAME_UPNP = SERVICE_TYPE_UPNP + ADDON_SUGGESTION_FINDER;
public static final String FEATURE_UPNP = ADDON_SUGGESTION_FINDER_FEATURE + SERVICE_TYPE_UPNP;
- public static final List SUGGESTION_FINDERS = List.of(SERVICE_NAME_IP, SERVICE_NAME_MDNS,
- SERVICE_NAME_UPNP);
+ public static final String SERVICE_TYPE_USB = "usb";
+ public static final String CFG_FINDER_USB = "suggestionFinderUsb";
+ public static final String SERVICE_NAME_USB = SERVICE_TYPE_USB + ADDON_SUGGESTION_FINDER;
+ public static final String FEATURE_USB = ADDON_SUGGESTION_FINDER_FEATURE + SERVICE_TYPE_USB;
+
+ public static final List SUGGESTION_FINDERS = List.of(SERVICE_NAME_IP, SERVICE_NAME_MDNS, SERVICE_NAME_UPNP,
+ SERVICE_NAME_USB);
+
public static final Map SUGGESTION_FINDER_CONFIGS = Map.of(SERVICE_NAME_IP, CFG_FINDER_IP,
- SERVICE_NAME_MDNS, CFG_FINDER_MDNS, SERVICE_NAME_UPNP, CFG_FINDER_UPNP);
+ SERVICE_NAME_MDNS, CFG_FINDER_MDNS, SERVICE_NAME_UPNP, CFG_FINDER_UPNP, SERVICE_NAME_USB, CFG_FINDER_USB);
+
public static final Map SUGGESTION_FINDER_FEATURES = Map.of(SERVICE_NAME_IP, FEATURE_IP,
- SERVICE_NAME_MDNS, FEATURE_MDNS, SERVICE_NAME_UPNP, FEATURE_UPNP);
+ SERVICE_NAME_MDNS, FEATURE_MDNS, SERVICE_NAME_UPNP, FEATURE_UPNP, SERVICE_NAME_USB, FEATURE_USB);
}
diff --git a/bundles/org.openhab.core.config.discovery.usbserial.ser2net/src/main/java/org/openhab/core/config/discovery/usbserial/ser2net/internal/Ser2NetUsbSerialDiscovery.java b/bundles/org.openhab.core.config.discovery.usbserial.ser2net/src/main/java/org/openhab/core/config/discovery/usbserial/ser2net/internal/Ser2NetUsbSerialDiscovery.java
index c7a17b0d2b6..2cf0e0e71ba 100644
--- a/bundles/org.openhab.core.config.discovery.usbserial.ser2net/src/main/java/org/openhab/core/config/discovery/usbserial/ser2net/internal/Ser2NetUsbSerialDiscovery.java
+++ b/bundles/org.openhab.core.config.discovery.usbserial.ser2net/src/main/java/org/openhab/core/config/discovery/usbserial/ser2net/internal/Ser2NetUsbSerialDiscovery.java
@@ -198,7 +198,8 @@ private Optional createUsbSerialDeviceInformation(Se
serviceInfo.getPort());
UsbSerialDeviceInformation deviceInfo = new UsbSerialDeviceInformation(vendorId, productId, serialNumber,
- manufacturer, product, interfaceNumber, interfaceDescription, serialPortName);
+ manufacturer, product, interfaceNumber, interfaceDescription, serialPortName).setRemote(true);
+
logger.debug("Created {} based on {}", deviceInfo, serviceInfo);
return Optional.of(deviceInfo);
} catch (NumberFormatException e) {
diff --git a/bundles/org.openhab.core.config.discovery.usbserial.ser2net/src/test/java/org/openhab/core/config/discovery/usbserial/ser2net/internal/Ser2NetUsbSerialDiscoveryTest.java b/bundles/org.openhab.core.config.discovery.usbserial.ser2net/src/test/java/org/openhab/core/config/discovery/usbserial/ser2net/internal/Ser2NetUsbSerialDiscoveryTest.java
index 48dae85d310..538b828d53f 100644
--- a/bundles/org.openhab.core.config.discovery.usbserial.ser2net/src/test/java/org/openhab/core/config/discovery/usbserial/ser2net/internal/Ser2NetUsbSerialDiscoveryTest.java
+++ b/bundles/org.openhab.core.config.discovery.usbserial.ser2net/src/test/java/org/openhab/core/config/discovery/usbserial/ser2net/internal/Ser2NetUsbSerialDiscoveryTest.java
@@ -61,11 +61,11 @@ public class Ser2NetUsbSerialDiscoveryTest {
private @NonNullByDefault({}) Ser2NetUsbSerialDiscovery discovery;
private UsbSerialDeviceInformation usb1 = new UsbSerialDeviceInformation(0x100, 0x111, "serial1", "manufacturer1",
- "product1", 0x1, "interface1", "rfc2217://1.1.1.1:1000");
+ "product1", 0x1, "interface1", "rfc2217://1.1.1.1:1000").setRemote(true);
private UsbSerialDeviceInformation usb2 = new UsbSerialDeviceInformation(0x200, 0x222, "serial2", "manufacturer2",
- "product2", 0x2, "interface2", "rfc2217://[0:0:0:0:0:ffff:0202:0202]:2222");
+ "product2", 0x2, "interface2", "rfc2217://[0:0:0:0:0:ffff:0202:0202]:2222").setRemote(true);
private UsbSerialDeviceInformation usb3 = new UsbSerialDeviceInformation(0x300, 0x333, null, null, null, 0x3, null,
- "rfc2217://123.222.100.000:3030");
+ "rfc2217://123.222.100.000:3030").setRemote(true);
@BeforeEach
public void beforeEach() {
diff --git a/bundles/org.openhab.core.config.discovery.usbserial/src/main/java/org/openhab/core/config/discovery/usbserial/UsbSerialDeviceInformation.java b/bundles/org.openhab.core.config.discovery.usbserial/src/main/java/org/openhab/core/config/discovery/usbserial/UsbSerialDeviceInformation.java
index 60ed8b2714d..c446ad00c8f 100644
--- a/bundles/org.openhab.core.config.discovery.usbserial/src/main/java/org/openhab/core/config/discovery/usbserial/UsbSerialDeviceInformation.java
+++ b/bundles/org.openhab.core.config.discovery.usbserial/src/main/java/org/openhab/core/config/discovery/usbserial/UsbSerialDeviceInformation.java
@@ -45,6 +45,8 @@ public class UsbSerialDeviceInformation {
private final String serialPort;
+ private boolean remote = false;
+
public UsbSerialDeviceInformation(int vendorId, int productId, @Nullable String serialNumber,
@Nullable String manufacturer, @Nullable String product, int interfaceNumber,
@Nullable String interfaceDescription, String serialPort) {
@@ -118,6 +120,21 @@ public String getSerialPort() {
return serialPort;
}
+ /**
+ * @return if the serial device is remote or local.
+ */
+ public boolean getRemote() {
+ return remote;
+ }
+
+ /**
+ * Set the remote flag
+ */
+ public UsbSerialDeviceInformation setRemote(boolean remote) {
+ this.remote = remote;
+ return this;
+ }
+
@SuppressWarnings("null")
@Override
public int hashCode() {
@@ -131,6 +148,7 @@ public int hashCode() {
result = prime * result + ((product == null) ? 0 : product.hashCode());
result = prime * result + ((serialNumber == null) ? 0 : serialNumber.hashCode());
result = prime * result + ((interfaceDescription == null) ? 0 : interfaceDescription.hashCode());
+ result = prime * result + (remote ? 1 : 0);
return result;
}
@@ -180,6 +198,10 @@ public boolean equals(@Nullable Object obj) {
return false;
}
+ if (remote != other.remote) {
+ return false;
+ }
+
return true;
}
@@ -187,8 +209,8 @@ public boolean equals(@Nullable Object obj) {
public String toString() {
return String.format(
"UsbSerialDeviceInformation [vendorId=0x%04X, productId=0x%04X, serialNumber=%s, manufacturer=%s, "
- + "product=%s, interfaceNumber=0x%02X, interfaceDescription=%s, serialPort=%s]",
+ + "product=%s, interfaceNumber=0x%02X, interfaceDescription=%s, serialPort=%s, remote=%b]",
vendorId, productId, serialNumber, manufacturer, product, interfaceNumber, interfaceDescription,
- serialPort);
+ serialPort, remote);
}
}
diff --git a/bundles/org.openhab.core/src/main/resources/OH-INF/config/addons.xml b/bundles/org.openhab.core/src/main/resources/OH-INF/config/addons.xml
index cbd0802400e..752351223b7 100644
--- a/bundles/org.openhab.core/src/main/resources/OH-INF/config/addons.xml
+++ b/bundles/org.openhab.core/src/main/resources/OH-INF/config/addons.xml
@@ -33,6 +33,11 @@
true
Use IP network discovery broadcasts to suggest add-ons. Enabling/disabling may take up to 1 minute.
+
+
+ true
+
+ Scan connected USB devices to suggest add-ons. Enabling/disabling may take up to 1 minute.
true
diff --git a/bundles/org.openhab.core/src/main/resources/OH-INF/i18n/addons.properties b/bundles/org.openhab.core/src/main/resources/OH-INF/i18n/addons.properties
index d63c1ac73a5..0d22f9d7de4 100644
--- a/bundles/org.openhab.core/src/main/resources/OH-INF/i18n/addons.properties
+++ b/bundles/org.openhab.core/src/main/resources/OH-INF/i18n/addons.properties
@@ -8,5 +8,7 @@ system.config.addons.suggestionFinderMdns.label = mDNS Suggestion Finder
system.config.addons.suggestionFinderMdns.description = Use mDNS network scan to suggest add-ons. Enabling/disabling may take up to 1 minute.
system.config.addons.suggestionFinderUpnp.label = UPnP Suggestion Finder
system.config.addons.suggestionFinderUpnp.description = Use UPnP network scan to suggest add-ons. Enabling/disabling may take up to 1 minute.
+system.config.addons.suggestionFinderUsb.label = USB Suggestion Finder
+system.config.addons.suggestionFinderUsb.description = Scan connected USB devices to suggest add-ons. Enabling/disabling may take up to 1 minute.
service.system.addons.label = Add-on Management
diff --git a/bundles/pom.xml b/bundles/pom.xml
index 3d4b79ecd9d..5035de7e1a7 100644
--- a/bundles/pom.xml
+++ b/bundles/pom.xml
@@ -35,6 +35,7 @@
org.openhab.core.config.discovery.addon.mdns
org.openhab.core.config.discovery.addon.process
org.openhab.core.config.discovery.addon.upnp
+ org.openhab.core.config.discovery.addon.usb
org.openhab.core.config.discovery.mdns
org.openhab.core.config.discovery.usbserial
org.openhab.core.config.discovery.usbserial.linuxsysfs
diff --git a/features/karaf/openhab-core/src/main/feature/feature.xml b/features/karaf/openhab-core/src/main/feature/feature.xml
index 44e3eb37a79..a5062604397 100644
--- a/features/karaf/openhab-core/src/main/feature/feature.xml
+++ b/features/karaf/openhab-core/src/main/feature/feature.xml
@@ -98,6 +98,13 @@
openhab.tp-jupnp
+
+ openhab-core-base
+ openhab-core-config-discovery-addon
+ openhab-transport-serial
+ mvn:org.openhab.core.bundles/org.openhab.core.config.discovery.addon.usb/${project.version}
+
+
kar
openhab-core-base