[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 <github@maindrain.net>
This commit is contained in:
Wouter Born
2023-12-23 18:29:41 +01:00
committed by GitHub
parent 5d4ac65991
commit 039bb98151
6 changed files with 111 additions and 2 deletions
@@ -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.
@@ -4,6 +4,7 @@
<feature name="openhab-binding-asuswrt" description="Asuswrt Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<feature>openhab-transport-upnp</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.asuswrt/${project.version}</bundle>
</feature>
</features>
@@ -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<ThingTypeUID> 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<String, Object> 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;
}
}
@@ -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
@@ -6,4 +6,21 @@
<name>Asuswrt Binding</name>
<description>Binding for ASUS routers (Asuswrt / Asuswrt-Merlin only)</description>
<connection>local</connection>
<discovery-methods>
<discovery-method>
<service-type>upnp</service-type>
<match-properties>
<match-property>
<name>manufacturer</name>
<regex>(?i).*ASUS.*</regex>
</match-property>
<match-property>
<name>modelName</name>
<regex>(?i)ASUS Wireless Router</regex>
</match-property>
</match-properties>
</discovery-method>
</discovery-methods>
</addon:addon>
@@ -13,6 +13,8 @@
<channel-group id="client-list" typeId="client-list-group"></channel-group>
</channel-groups>
<representation-property>macAddress</representation-property>
<config-description>
<parameter name="hostname" type="text" required="true">
<context>network-address</context>