From 039bb9815146d502e44c313d4d627b3107692e7b Mon Sep 17 00:00:00 2001 From: Wouter Born Date: Sat, 23 Dec 2023 18:29:41 +0100 Subject: [PATCH] [asuswrt] Support router discovery and add-on suggestion using UPnP (#16084) This makes it easier to discover the devices and the add-on. Signed-off-by: Wouter Born --- bundles/org.openhab.binding.asuswrt/README.md | 5 ++ .../src/main/feature/feature.xml | 1 + .../internal/AsuswrtDiscoveryParticipant.java | 81 +++++++++++++++++++ .../constants/AsuswrtBindingConstants.java | 7 +- .../src/main/resources/OH-INF/addon/addon.xml | 17 ++++ .../main/resources/OH-INF/thing/router.xml | 2 + 6 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 bundles/org.openhab.binding.asuswrt/src/main/java/org/openhab/binding/asuswrt/internal/AsuswrtDiscoveryParticipant.java diff --git a/bundles/org.openhab.binding.asuswrt/README.md b/bundles/org.openhab.binding.asuswrt/README.md index 39dd664f30..1b39fc9b22 100644 --- a/bundles/org.openhab.binding.asuswrt/README.md +++ b/bundles/org.openhab.binding.asuswrt/README.md @@ -2,6 +2,11 @@ This binding adds support to read information from ASUS-Routers (Copyright © ASUS). +## Discovery + +The ASUS routers are discovered through UPnP in the local network. +After adding a discovered router it is required to configure the username and password to use it. + ## Supported Things This binding supports ASUS routers with Asuswrt or [Asuswrt-Merlin](https://www.asuswrt-merlin.net/) firmware. diff --git a/bundles/org.openhab.binding.asuswrt/src/main/feature/feature.xml b/bundles/org.openhab.binding.asuswrt/src/main/feature/feature.xml index 73416289ca..0ea6d21144 100644 --- a/bundles/org.openhab.binding.asuswrt/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.asuswrt/src/main/feature/feature.xml @@ -4,6 +4,7 @@ openhab-runtime-base + openhab-transport-upnp mvn:org.openhab.addons.bundles/org.openhab.binding.asuswrt/${project.version} diff --git a/bundles/org.openhab.binding.asuswrt/src/main/java/org/openhab/binding/asuswrt/internal/AsuswrtDiscoveryParticipant.java b/bundles/org.openhab.binding.asuswrt/src/main/java/org/openhab/binding/asuswrt/internal/AsuswrtDiscoveryParticipant.java new file mode 100644 index 0000000000..1705023fbc --- /dev/null +++ b/bundles/org.openhab.binding.asuswrt/src/main/java/org/openhab/binding/asuswrt/internal/AsuswrtDiscoveryParticipant.java @@ -0,0 +1,81 @@ +/** + * 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.binding.asuswrt.internal; + +import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingConstants.PROPERTY_HOSTNAME; +import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingConstants.THING_TYPE_ROUTER; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.jupnp.model.meta.DeviceDetails; +import org.jupnp.model.meta.RemoteDevice; +import org.openhab.core.config.discovery.DiscoveryResult; +import org.openhab.core.config.discovery.DiscoveryResultBuilder; +import org.openhab.core.config.discovery.upnp.UpnpDiscoveryParticipant; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.ThingUID; +import org.osgi.service.component.annotations.Component; + +/** + * The {@link AsuswrtDiscoveryParticipant} discovers the ASUS routers using UPnP. + * + * @author Wouter Born - Initial contribution + */ +@NonNullByDefault +@Component(service = UpnpDiscoveryParticipant.class, configurationPid = "discovery.asuswrt") +public class AsuswrtDiscoveryParticipant implements UpnpDiscoveryParticipant { + @Override + public Set getSupportedThingTypeUIDs() { + return Set.of(THING_TYPE_ROUTER); + } + + @Override + public @Nullable DiscoveryResult createResult(RemoteDevice device) { + ThingUID uid = getThingUID(device); + if (uid == null) { + return null; + } + + DeviceDetails details = device.getDetails(); + + String host = details.getPresentationURI().getHost(); + String model = details.getModelDetails().getModelNumber(); + + Map properties = new HashMap<>(); + properties.put(PROPERTY_HOSTNAME, host); + properties.put(Thing.PROPERTY_VENDOR, details.getManufacturerDetails().getManufacturer()); + properties.put(Thing.PROPERTY_MODEL_ID, model); + properties.put(Thing.PROPERTY_MAC_ADDRESS, details.getSerialNumber()); + + String label = String.format("ASUS %s Wireless Router (%s)", model, host); + + return DiscoveryResultBuilder.create(uid).withProperties(properties).withLabel(label) + .withRepresentationProperty(Thing.PROPERTY_MAC_ADDRESS).build(); + } + + @Override + public @Nullable ThingUID getThingUID(RemoteDevice device) { + DeviceDetails details = device.getDetails(); + String modelName = details.getModelDetails().getModelName(); + String modelManufacturer = details.getManufacturerDetails().getManufacturer(); + if (modelManufacturer.toUpperCase().contains("ASUS") && ("ASUS Wireless Router".equalsIgnoreCase(modelName))) { + return new ThingUID(THING_TYPE_ROUTER, details.getSerialNumber().replace(':', '-')); + } + return null; + } +} diff --git a/bundles/org.openhab.binding.asuswrt/src/main/java/org/openhab/binding/asuswrt/internal/constants/AsuswrtBindingConstants.java b/bundles/org.openhab.binding.asuswrt/src/main/java/org/openhab/binding/asuswrt/internal/constants/AsuswrtBindingConstants.java index edcbdd2d06..46031a0ffd 100644 --- a/bundles/org.openhab.binding.asuswrt/src/main/java/org/openhab/binding/asuswrt/internal/constants/AsuswrtBindingConstants.java +++ b/bundles/org.openhab.binding.asuswrt/src/main/java/org/openhab/binding/asuswrt/internal/constants/AsuswrtBindingConstants.java @@ -18,6 +18,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingTypeUID; /** @@ -101,12 +102,14 @@ public class AsuswrtBindingConstants { * Properties */ + // Router + public static final String PROPERTY_HOSTNAME = "hostname"; // Interface public static final String PROPERTY_INTERFACE_NAME = "interfaceName"; public static final String NETWORK_REPRESENTATION_PROPERTY = "interfaceName"; - // client + // Client public static final String PROPERTY_CLIENT_NAME = "dnsName"; - public static final String CLIENT_REPRESENTATION_PROPERTY = "macAddress"; + public static final String CLIENT_REPRESENTATION_PROPERTY = Thing.PROPERTY_MAC_ADDRESS; /* * JSON request member names diff --git a/bundles/org.openhab.binding.asuswrt/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.asuswrt/src/main/resources/OH-INF/addon/addon.xml index 691ab88beb..6c895d3bdc 100644 --- a/bundles/org.openhab.binding.asuswrt/src/main/resources/OH-INF/addon/addon.xml +++ b/bundles/org.openhab.binding.asuswrt/src/main/resources/OH-INF/addon/addon.xml @@ -6,4 +6,21 @@ Asuswrt Binding Binding for ASUS routers (Asuswrt / Asuswrt-Merlin only) local + + + + upnp + + + manufacturer + (?i).*ASUS.* + + + modelName + (?i)ASUS Wireless Router + + + + + diff --git a/bundles/org.openhab.binding.asuswrt/src/main/resources/OH-INF/thing/router.xml b/bundles/org.openhab.binding.asuswrt/src/main/resources/OH-INF/thing/router.xml index 0d7a1d6424..17eae93b9f 100644 --- a/bundles/org.openhab.binding.asuswrt/src/main/resources/OH-INF/thing/router.xml +++ b/bundles/org.openhab.binding.asuswrt/src/main/resources/OH-INF/thing/router.xml @@ -13,6 +13,8 @@ + macAddress + network-address -- 2.47.3