mirror of
https://github.com/danieldemus/openhab-core.git
synced 2025-01-10 21:31:53 +01:00
Add-on suggestion finder for USB devices (#3922)
Also-by: Holger Friedrich <mail@holger-friedrich.de> Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
This commit is contained in:
parent
f5bd7f94f3
commit
a93f3d7d90
@ -334,6 +334,12 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openhab.core.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.core.config.discovery.addon.usb</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openhab.core.bundles</groupId>
|
<groupId>org.openhab.core.bundles</groupId>
|
||||||
<artifactId>org.openhab.core.config.discovery.mdns</artifactId>
|
<artifactId>org.openhab.core.config.discovery.mdns</artifactId>
|
||||||
|
@ -105,7 +105,7 @@ public class ProcessAddonFinder extends BaseAddonFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// now check if a process matches the pattern defined in addon.xml
|
// 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) {
|
for (AddonMatchProperty command : commands) {
|
||||||
logger.trace("Candidate {}, pattern \"{}\"", candidate.getUID(), command.getRegex());
|
logger.trace("Candidate {}, pattern \"{}\"", candidate.getUID(), command.getRegex());
|
||||||
|
@ -188,7 +188,7 @@ public class UpnpAddonFinder extends BaseAddonFinder implements RegistryListener
|
|||||||
&& propertyMatches(matchProperties, SERIAL_NUMBER, serialNumber)
|
&& propertyMatches(matchProperties, SERIAL_NUMBER, serialNumber)
|
||||||
&& propertyMatches(matchProperties, FRIENDLY_NAME, friendlyName)) {
|
&& propertyMatches(matchProperties, FRIENDLY_NAME, friendlyName)) {
|
||||||
result.add(candidate);
|
result.add(candidate);
|
||||||
logger.debug("Suggested addon found: {}", candidate.getUID());
|
logger.debug("Suggested add-on found: {}", candidate.getUID());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="optional" value="true"/>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="test" value="true"/>
|
||||||
|
<attribute name="optional" value="true"/>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
<attribute name="annotationpath" value="target/dependency"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
<attribute name="annotationpath" value="target/dependency"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="output" path="target/classes"/>
|
||||||
|
</classpath>
|
23
bundles/org.openhab.core.config.discovery.addon.usb/.project
Normal file
23
bundles/org.openhab.core.config.discovery.addon.usb/.project
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>org.openhab.core.config.discovery.addon.usb</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
14
bundles/org.openhab.core.config.discovery.addon.usb/NOTICE
Normal file
14
bundles/org.openhab.core.config.discovery.addon.usb/NOTICE
Normal file
@ -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
|
||||||
|
|
35
bundles/org.openhab.core.config.discovery.addon.usb/pom.xml
Normal file
35
bundles/org.openhab.core.config.discovery.addon.usb/pom.xml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.openhab.core.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.core.reactor.bundles</artifactId>
|
||||||
|
<version>4.2.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>org.openhab.core.config.discovery.addon.usb</artifactId>
|
||||||
|
|
||||||
|
<name>openHAB Core :: Bundles :: USB Suggested Add-on Finder</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openhab.core.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.core.config.discovery.addon</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openhab.core.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.core.addon</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openhab.core.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.core.config.discovery.usbserial</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -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.
|
||||||
|
* <p>
|
||||||
|
* It supports the following values for the 'match-property' 'name' element:
|
||||||
|
* <li>product - match on the product description text
|
||||||
|
* <li>manufacturer - match on the device manufacturer text
|
||||||
|
* <li>chipId - match on the chip vendor id plus product id
|
||||||
|
* <li>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<String> SUPPORTED_PROPERTIES = Set.of(PRODUCT, MANUFACTURER, CHIP_ID, REMOTE);
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(UsbAddonFinder.class);
|
||||||
|
private final Set<UsbSerialDiscovery> usbSerialDiscoveries = new CopyOnWriteArraySet<>();
|
||||||
|
private final Map<Long, UsbSerialDeviceInformation> 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<AddonInfo> getSuggestedAddons() {
|
||||||
|
Set<AddonInfo> result = new HashSet<>();
|
||||||
|
for (AddonInfo candidate : addonCandidates) {
|
||||||
|
for (AddonDiscoveryMethod method : candidate.getDiscoveryMethods().stream()
|
||||||
|
.filter(method -> SERVICE_TYPE.equals(method.getServiceType())).toList()) {
|
||||||
|
Map<String, Pattern> matchProperties = method.getMatchProperties().stream()
|
||||||
|
.collect(Collectors.toMap(property -> property.getName(), property -> property.getPattern()));
|
||||||
|
|
||||||
|
Set<String> 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));
|
||||||
|
}
|
||||||
|
}
|
@ -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<AddonInfo> 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<AddonInfo> 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<AddonInfo> 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<AddonInfo> suggestions = finder.getSuggestedAddons();
|
||||||
|
assertNotNull(suggestions);
|
||||||
|
assertTrue(suggestions.isEmpty());
|
||||||
|
}
|
||||||
|
}
|
@ -43,10 +43,17 @@ public class AddonFinderConstants {
|
|||||||
public static final String SERVICE_NAME_UPNP = SERVICE_TYPE_UPNP + ADDON_SUGGESTION_FINDER;
|
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 String FEATURE_UPNP = ADDON_SUGGESTION_FINDER_FEATURE + SERVICE_TYPE_UPNP;
|
||||||
|
|
||||||
public static final List<String> SUGGESTION_FINDERS = List.of(SERVICE_NAME_IP, SERVICE_NAME_MDNS,
|
public static final String SERVICE_TYPE_USB = "usb";
|
||||||
SERVICE_NAME_UPNP);
|
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<String> SUGGESTION_FINDERS = List.of(SERVICE_NAME_IP, SERVICE_NAME_MDNS, SERVICE_NAME_UPNP,
|
||||||
|
SERVICE_NAME_USB);
|
||||||
|
|
||||||
public static final Map<String, String> SUGGESTION_FINDER_CONFIGS = Map.of(SERVICE_NAME_IP, CFG_FINDER_IP,
|
public static final Map<String, String> 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<String, String> SUGGESTION_FINDER_FEATURES = Map.of(SERVICE_NAME_IP, FEATURE_IP,
|
public static final Map<String, String> 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);
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,8 @@ public class Ser2NetUsbSerialDiscovery implements ServiceListener, UsbSerialDisc
|
|||||||
serviceInfo.getPort());
|
serviceInfo.getPort());
|
||||||
|
|
||||||
UsbSerialDeviceInformation deviceInfo = new UsbSerialDeviceInformation(vendorId, productId, serialNumber,
|
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);
|
logger.debug("Created {} based on {}", deviceInfo, serviceInfo);
|
||||||
return Optional.of(deviceInfo);
|
return Optional.of(deviceInfo);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
|
@ -61,11 +61,11 @@ public class Ser2NetUsbSerialDiscoveryTest {
|
|||||||
private @NonNullByDefault({}) Ser2NetUsbSerialDiscovery discovery;
|
private @NonNullByDefault({}) Ser2NetUsbSerialDiscovery discovery;
|
||||||
|
|
||||||
private UsbSerialDeviceInformation usb1 = new UsbSerialDeviceInformation(0x100, 0x111, "serial1", "manufacturer1",
|
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",
|
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,
|
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
|
@BeforeEach
|
||||||
public void beforeEach() {
|
public void beforeEach() {
|
||||||
|
@ -45,6 +45,8 @@ public class UsbSerialDeviceInformation {
|
|||||||
|
|
||||||
private final String serialPort;
|
private final String serialPort;
|
||||||
|
|
||||||
|
private boolean remote = false;
|
||||||
|
|
||||||
public UsbSerialDeviceInformation(int vendorId, int productId, @Nullable String serialNumber,
|
public UsbSerialDeviceInformation(int vendorId, int productId, @Nullable String serialNumber,
|
||||||
@Nullable String manufacturer, @Nullable String product, int interfaceNumber,
|
@Nullable String manufacturer, @Nullable String product, int interfaceNumber,
|
||||||
@Nullable String interfaceDescription, String serialPort) {
|
@Nullable String interfaceDescription, String serialPort) {
|
||||||
@ -118,6 +120,21 @@ public class UsbSerialDeviceInformation {
|
|||||||
return serialPort;
|
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")
|
@SuppressWarnings("null")
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
@ -131,6 +148,7 @@ public class UsbSerialDeviceInformation {
|
|||||||
result = prime * result + ((product == null) ? 0 : product.hashCode());
|
result = prime * result + ((product == null) ? 0 : product.hashCode());
|
||||||
result = prime * result + ((serialNumber == null) ? 0 : serialNumber.hashCode());
|
result = prime * result + ((serialNumber == null) ? 0 : serialNumber.hashCode());
|
||||||
result = prime * result + ((interfaceDescription == null) ? 0 : interfaceDescription.hashCode());
|
result = prime * result + ((interfaceDescription == null) ? 0 : interfaceDescription.hashCode());
|
||||||
|
result = prime * result + (remote ? 1 : 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,6 +198,10 @@ public class UsbSerialDeviceInformation {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (remote != other.remote) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,8 +209,8 @@ public class UsbSerialDeviceInformation {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format(
|
return String.format(
|
||||||
"UsbSerialDeviceInformation [vendorId=0x%04X, productId=0x%04X, serialNumber=%s, manufacturer=%s, "
|
"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,
|
vendorId, productId, serialNumber, manufacturer, product, interfaceNumber, interfaceDescription,
|
||||||
serialPort);
|
serialPort, remote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,11 @@
|
|||||||
<advanced>true</advanced>
|
<advanced>true</advanced>
|
||||||
<label>IP-based Suggestion Finder</label>
|
<label>IP-based Suggestion Finder</label>
|
||||||
<description>Use IP network discovery broadcasts to suggest add-ons. Enabling/disabling may take up to 1 minute.</description>
|
<description>Use IP network discovery broadcasts to suggest add-ons. Enabling/disabling may take up to 1 minute.</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="suggestionFinderUsb" type="boolean">
|
||||||
|
<advanced>true</advanced>
|
||||||
|
<label>USB Suggestion Finder</label>
|
||||||
|
<description>Scan connected USB devices to suggest add-ons. Enabling/disabling may take up to 1 minute.</description>
|
||||||
<default>true</default>
|
<default>true</default>
|
||||||
</parameter>
|
</parameter>
|
||||||
</config-description>
|
</config-description>
|
||||||
|
@ -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.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.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.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
|
service.system.addons.label = Add-on Management
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
<module>org.openhab.core.config.discovery.addon.mdns</module>
|
<module>org.openhab.core.config.discovery.addon.mdns</module>
|
||||||
<module>org.openhab.core.config.discovery.addon.process</module>
|
<module>org.openhab.core.config.discovery.addon.process</module>
|
||||||
<module>org.openhab.core.config.discovery.addon.upnp</module>
|
<module>org.openhab.core.config.discovery.addon.upnp</module>
|
||||||
|
<module>org.openhab.core.config.discovery.addon.usb</module>
|
||||||
<module>org.openhab.core.config.discovery.mdns</module>
|
<module>org.openhab.core.config.discovery.mdns</module>
|
||||||
<module>org.openhab.core.config.discovery.usbserial</module>
|
<module>org.openhab.core.config.discovery.usbserial</module>
|
||||||
<module>org.openhab.core.config.discovery.usbserial.linuxsysfs</module>
|
<module>org.openhab.core.config.discovery.usbserial.linuxsysfs</module>
|
||||||
|
@ -98,6 +98,13 @@
|
|||||||
<feature dependency="true">openhab.tp-jupnp</feature>
|
<feature dependency="true">openhab.tp-jupnp</feature>
|
||||||
</feature>
|
</feature>
|
||||||
|
|
||||||
|
<feature name="openhab-core-config-discovery-addon-usb" version="${project.version}">
|
||||||
|
<feature>openhab-core-base</feature>
|
||||||
|
<feature>openhab-core-config-discovery-addon</feature>
|
||||||
|
<feature dependency="true">openhab-transport-serial</feature>
|
||||||
|
<bundle>mvn:org.openhab.core.bundles/org.openhab.core.config.discovery.addon.usb/${project.version}</bundle>
|
||||||
|
</feature>
|
||||||
|
|
||||||
<feature name="openhab-core-addon-marketplace" version="${project.version}">
|
<feature name="openhab-core-addon-marketplace" version="${project.version}">
|
||||||
<feature>kar</feature>
|
<feature>kar</feature>
|
||||||
<feature>openhab-core-base</feature>
|
<feature>openhab-core-base</feature>
|
||||||
|
Loading…
Reference in New Issue
Block a user