mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[asuswrt] Initial contribution (#13815)
Signed-off-by: Christian Wild <christian@wildclan.de>
This commit is contained in:
parent
ee687aa1cd
commit
d2f4e05295
@ -131,6 +131,11 @@
|
||||
<artifactId>org.openhab.binding.astro</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.binding.asuswrt</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.binding.atlona</artifactId>
|
||||
|
13
bundles/org.openhab.binding.asuswrt/NOTICE
Normal file
13
bundles/org.openhab.binding.asuswrt/NOTICE
Normal file
@ -0,0 +1,13 @@
|
||||
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-addons
|
91
bundles/org.openhab.binding.asuswrt/README.md
Normal file
91
bundles/org.openhab.binding.asuswrt/README.md
Normal file
@ -0,0 +1,91 @@
|
||||
# Asuswrt Binding
|
||||
|
||||
This binding adds support to read information from ASUS-Routers (Copyright © ASUS).
|
||||
|
||||
## Supported Things
|
||||
|
||||
This binding supports ASUS routers with Asuswrt or [Asuswrt-Merlin](https://www.asuswrt-merlin.net/) firmware.
|
||||
Firmware 5.x.x (some DSL models) is NOT supported (not Asuswrt).
|
||||
|
||||
| ThingType | Name | Descripion |
|
||||
|---------------|------------|--------------------------------------|
|
||||
| bridge | router | Router to which the binding connects |
|
||||
| - | interface | Network interface of the router |
|
||||
| - | client | Client is connected to the bridge |
|
||||
|
||||
### `router` Thing Configuration
|
||||
|
||||
| Name | Type | Description | Default | Required | Advanced |
|
||||
|-----------------|---------|---------------------------------------|---------------------|----------|----------|
|
||||
| hostname | text | Hostname or IP address of the device | router.asus.com | yes | no |
|
||||
| username | text | Username to access the device | N/A | yes | no |
|
||||
| password | text | Password to access the device | N/A | yes | no |
|
||||
| useSSL | boolean | Connect over SSL or use http:// | false | no | no |
|
||||
| refreshInterval | integer | Interval the device is polled in sec. | 20 | no | yes |
|
||||
| httpPort | integer | HTTP-Port | 80 | no | yes |
|
||||
| httpsPort | integer | HTTPS-Port | 443 | no | yes |
|
||||
|
||||
### `interface` Thing Configuration
|
||||
|
||||
| Name | Type | Description | Default | Required | Advanced |
|
||||
|-----------------|---------|---------------------------------------|---------------------|----------|----------|
|
||||
| interfaceName | text | options name of interface (wan/lan) | N/A | yes | no |
|
||||
|
||||
### `client` Thing Configuration
|
||||
|
||||
| Name | Type | Description | Default | Required | Advanced |
|
||||
|-----------------|---------|---------------------------------------|---------------------|----------|----------|
|
||||
| macAddress | text | Unique MAC address of the device | N/A | yes | no |
|
||||
| clientNick | text | Nickname used by OH | N/A | no | no |
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
All devices support some of the following properties:
|
||||
|
||||
| property | description | things supporting this channel |
|
||||
|------------------|------------------------------|---------------------------------------|
|
||||
| vendor | Vendor of device | router, client |
|
||||
| dnsName | DNS name of device | router, client |
|
||||
|
||||
|
||||
## Channels
|
||||
|
||||
All devices support some of the following channels:
|
||||
|
||||
| group | channel |type | description | things supporting this channel |
|
||||
|------------------|----------------------|------------------------|--------------------------------------------|-----------------------------------|
|
||||
| network-info | mac-address | text (RO) | HW address | interface, client |
|
||||
| | ip-address | text (RO) | IP address | interface |
|
||||
| | ip-method | text (RO) | IP method (static/dhcp) | interface, client |
|
||||
| | subnet | text (RO) | Subnetmask | interface |
|
||||
| | gateway | text (RO) | Default gateway | interface |
|
||||
| | dns-servers | text (RO) | DNS servers | interface |
|
||||
| | network-state | Switch (RO) | Client is online | interface, client |
|
||||
| | internet-state | Switch (RO) | Client connected to Internet | client |
|
||||
| sys-info | mem-total | Number:DataAmountype | Total memory in MB | router |
|
||||
| | mem-used | Number:DataAmountype | Used memory in MB | router |
|
||||
| | mem-free | Number:DataAmountype | Free memory in MB | router |
|
||||
| | mem-used-percent | Number:Dimensionles | Used memory in % | router |
|
||||
| | cpu-used-percent | Number:Dimensionles | Total CPU usage in percent over all cores | router |
|
||||
| client-list | known-clients | text (RO) | Known clients with name and MAC addresses | router |
|
||||
| | online-clients | text (RO) | Online clients with name and MAC addresses | router |
|
||||
| | online-macs | text (RO) | List with MAC addresses of online clients | router |
|
||||
| | online-clients-count | Number:Dimensionless | Count of online clients | router |
|
||||
| traffic | current-rx | Number:DataTransferRate| Current DataTransferRate MBits/s (receive) | interface, client |
|
||||
| | current-tx | Number:DataTransferRate| Current DataTransferRate MBits/s (send) | interface, client |
|
||||
| | today-rx | Number:DataAmount | Data received since 0:00 a clock in MB | interface, client |
|
||||
| | today-tx | Number:DataAmount | Data sent since 0:00 a clock in MB | interface, client |
|
||||
| | total-rx | Number:DataAmount | Data received since reboot in MB | interface, client |
|
||||
| | total-tx | Number:DataAmount | Data sent since reboot in MB | interface, client |
|
||||
|
||||
|
||||
## Events
|
||||
|
||||
All devices support some of the following Events:
|
||||
|
||||
| group | event |kind | description | things supporting this event |
|
||||
|------------------|---------------------|------------|------------------------------------------------------------------------|---------------------------------|
|
||||
| network-info | connection-event | Trigger | Fired if connection is established ('connected') or ('disconnected') | interface |
|
||||
| | client-online-event | Trigger | Fired if client leaves ('gone') or enters ('connected') the network | client |
|
||||
| client-list | client-online-event | Trigger | Fired if client leaves ('gone') or enters ('connected') the network | router |
|
17
bundles/org.openhab.binding.asuswrt/pom.xml
Normal file
17
bundles/org.openhab.binding.asuswrt/pom.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
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.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||
<version>4.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.asuswrt</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: Asuswrt Binding</name>
|
||||
|
||||
</project>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.asuswrt-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-binding-asuswrt" description="Asuswrt Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.asuswrt/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
@ -0,0 +1,212 @@
|
||||
/**
|
||||
* 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.*;
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingSettings.*;
|
||||
import static org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.asuswrt.internal.structures.AsuswrtClientInfo;
|
||||
import org.openhab.binding.asuswrt.internal.structures.AsuswrtClientList;
|
||||
import org.openhab.binding.asuswrt.internal.structures.AsuswrtInterfaceList;
|
||||
import org.openhab.binding.asuswrt.internal.structures.AsuswrtIpInfo;
|
||||
import org.openhab.binding.asuswrt.internal.things.AsuswrtRouter;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtDiscoveryService} is responsible for discovering clients.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtDiscoveryService extends AbstractDiscoveryService implements ThingHandlerService {
|
||||
private final Logger logger = LoggerFactory.getLogger(AsuswrtDiscoveryService.class);
|
||||
private String uid = "";
|
||||
protected @NonNullByDefault({}) AsuswrtRouter router;
|
||||
|
||||
public AsuswrtDiscoveryService() {
|
||||
super(SUPPORTED_THING_TYPES_UIDS, DISCOVERY_TIMEOUT_S, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
super.deactivate();
|
||||
removeAllResults();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThingHandler(@Nullable ThingHandler handler) {
|
||||
if (handler instanceof AsuswrtRouter router) {
|
||||
router.setDiscoveryService(this);
|
||||
this.router = router;
|
||||
this.uid = router.getUID().getAsString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingHandler getThingHandler() {
|
||||
return this.router;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan handling
|
||||
*/
|
||||
|
||||
/**
|
||||
* Starts a manual scan.
|
||||
*/
|
||||
@Override
|
||||
public void startScan() {
|
||||
logger.trace("{} starting scan", uid);
|
||||
if (router != null) {
|
||||
/* query Data */
|
||||
router.queryDeviceData(false);
|
||||
/* discover interfaces */
|
||||
AsuswrtInterfaceList ifList = router.getInterfaces();
|
||||
handleInterfaceScan(ifList);
|
||||
/* discover clients */
|
||||
AsuswrtClientList clientList = router.getClients();
|
||||
handleClientScan(clientList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopScan() {
|
||||
super.stopScan();
|
||||
removeOlderResults(getTimestampOfLastScan());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all scan results.
|
||||
*/
|
||||
private void removeAllResults() {
|
||||
removeOlderResults(new Date().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates {@link DiscoveryResult}s from the provided {@link AsuswrtInterfaceList}.
|
||||
*/
|
||||
private void handleInterfaceScan(AsuswrtInterfaceList ifList) {
|
||||
try {
|
||||
for (AsuswrtIpInfo ifInfo : ifList) {
|
||||
DiscoveryResult discoveryResult = createInterfaceResult(ifInfo);
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("Error while handling interface scan reults", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates {@link DiscoveryResult}s from the provided {@link AsuswrtClientList}.
|
||||
*/
|
||||
public void handleClientScan(AsuswrtClientList clientList) {
|
||||
try {
|
||||
for (AsuswrtClientInfo client : clientList) {
|
||||
DiscoveryResult discoveryResult = createClientResult(client);
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("Error while handling client scan results", e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Discovery result creation
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a {@link DiscoveryResult} from the provided {@link AsuswrtIpInfo}.
|
||||
*/
|
||||
private DiscoveryResult createInterfaceResult(AsuswrtIpInfo interfaceInfo) {
|
||||
String ifName = interfaceInfo.getName();
|
||||
String macAddress = interfaceInfo.getMAC();
|
||||
String label = "AwrtInterface_" + ifName;
|
||||
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put(NETWORK_REPRESENTATION_PROPERTY, ifName);
|
||||
properties.put(Thing.PROPERTY_MAC_ADDRESS, macAddress);
|
||||
|
||||
logger.debug("{} thing discovered: '{}", uid, label);
|
||||
if (this.router != null) {
|
||||
ThingUID bridgeUID = router.getUID();
|
||||
ThingUID thingUID = new ThingUID(THING_TYPE_INTERFACE, bridgeUID, ifName);
|
||||
return DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
.withRepresentationProperty(NETWORK_REPRESENTATION_PROPERTY).withBridge(bridgeUID).withLabel(label)
|
||||
.build();
|
||||
} else {
|
||||
ThingUID thingUID = new ThingUID(BINDING_ID, ifName);
|
||||
return DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
.withRepresentationProperty(NETWORK_REPRESENTATION_PROPERTY).withLabel(label).build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DiscoveryResult} from the provided {@link AsuswrtClientInfo}.
|
||||
*/
|
||||
private DiscoveryResult createClientResult(AsuswrtClientInfo clientInfo) {
|
||||
String macAddress = clientInfo.getMac();
|
||||
String unformatedMac = unformatMac(macAddress);
|
||||
String clientName;
|
||||
String nickName;
|
||||
String label = "AwrtClient_";
|
||||
|
||||
// Create label and thing names
|
||||
clientName = stringOrDefault(clientInfo.getName(), "client_" + unformatedMac);
|
||||
nickName = stringOrDefault(clientInfo.getNickName(), clientName);
|
||||
if (nickName.equals(clientName)) {
|
||||
label += nickName;
|
||||
} else {
|
||||
label += nickName + " (" + clientName + ")";
|
||||
}
|
||||
|
||||
// Create properties
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put(Thing.PROPERTY_MAC_ADDRESS, macAddress);
|
||||
properties.put(Thing.PROPERTY_VENDOR, clientInfo.getVendor());
|
||||
properties.put(PROPERTY_CLIENT_NAME, clientName);
|
||||
properties.put(CHANNEL_CLIENT_NICKNAME, nickName);
|
||||
|
||||
logger.debug("{} thing discovered: '{}", uid, label);
|
||||
if (this.router != null) {
|
||||
ThingUID bridgeUID = router.getUID();
|
||||
ThingUID thingUID = new ThingUID(THING_TYPE_CLIENT, bridgeUID, unformatedMac);
|
||||
return DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
.withRepresentationProperty(CLIENT_REPRESENTATION_PROPERTY).withTTL(DISCOVERY_AUTOREMOVE_S)
|
||||
.withBridge(bridgeUID).withLabel(label).build();
|
||||
} else {
|
||||
ThingUID thingUID = new ThingUID(BINDING_ID, unformatedMac);
|
||||
return DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
.withRepresentationProperty(CLIENT_REPRESENTATION_PROPERTY).withTTL(DISCOVERY_AUTOREMOVE_S)
|
||||
.withLabel(label).build();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
/**
|
||||
* 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.*;
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingSettings.*;
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtErrorConstants.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.openhab.binding.asuswrt.internal.things.AsuswrtClient;
|
||||
import org.openhab.binding.asuswrt.internal.things.AsuswrtInterface;
|
||||
import org.openhab.binding.asuswrt.internal.things.AsuswrtRouter;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.service.component.ComponentContext;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtHandlerFactory} is responsible for creating things and thing handlers.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.asuswrt", service = ThingHandlerFactory.class)
|
||||
public class AsuswrtHandlerFactory extends BaseThingHandlerFactory {
|
||||
private final Logger logger = LoggerFactory.getLogger(AsuswrtHandlerFactory.class);
|
||||
private final Set<AsuswrtRouter> routerHandlers = new HashSet<>();
|
||||
private final HttpClient httpClient;
|
||||
|
||||
public AsuswrtHandlerFactory() {
|
||||
// Set SslContextfactory
|
||||
SslContextFactory sslContextFactory = new SslContextFactory.Client();
|
||||
if (HTTP_SSL_TRUST_ALL) {
|
||||
sslContextFactory.setTrustAll(true);
|
||||
sslContextFactory.setEndpointIdentificationAlgorithm(null);
|
||||
}
|
||||
// Create new httpClient
|
||||
httpClient = new HttpClient(sslContextFactory);
|
||||
httpClient.setFollowRedirects(false);
|
||||
httpClient.setMaxConnectionsPerDestination(HTTP_MAX_CONNECTIONS);
|
||||
httpClient.setMaxRequestsQueuedPerDestination(HTTP_MAX_QUEUED_REQUESTS);
|
||||
try {
|
||||
httpClient.start();
|
||||
} catch (Exception e) {
|
||||
logger.error(ERR_HTTP_CLIENT_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
@Override
|
||||
protected void deactivate(ComponentContext componentContext) {
|
||||
super.deactivate(componentContext);
|
||||
try {
|
||||
httpClient.stop();
|
||||
} catch (Exception e) {
|
||||
logger.debug("Unable to stop httpClient");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (THING_TYPE_ROUTER.equals(thingTypeUID)) {
|
||||
AsuswrtRouter router = new AsuswrtRouter((Bridge) thing, this.httpClient);
|
||||
routerHandlers.add(router);
|
||||
return router;
|
||||
} else if (THING_TYPE_CLIENT.equals(thingTypeUID)) {
|
||||
AsuswrtRouter router = getRouter(thing);
|
||||
if (router != null) {
|
||||
return new AsuswrtClient(thing, router);
|
||||
}
|
||||
} else if (THING_TYPE_INTERFACE.equals(thingTypeUID)) {
|
||||
AsuswrtRouter router = getRouter(thing);
|
||||
if (router != null) {
|
||||
return new AsuswrtInterface(thing, router);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link AsuswrtRouter} handler (Bridge) from a Thing.
|
||||
*/
|
||||
protected @Nullable AsuswrtRouter getRouter(Thing thing) {
|
||||
ThingUID bridgeUID = thing.getBridgeUID();
|
||||
if (bridgeUID != null) {
|
||||
for (AsuswrtRouter router : routerHandlers) {
|
||||
if (bridgeUID.equals(router.getUID())) {
|
||||
return router;
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.warn(ERR_BRIDGE_NOT_DECLARED);
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
/**
|
||||
* 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.api;
|
||||
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingSettings.*;
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtErrorConstants.*;
|
||||
import static org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils.getValueOrDefault;
|
||||
|
||||
import java.net.NoRouteToHostException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.net.ssl.SSLKeyException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.openhab.binding.asuswrt.internal.structures.AsuswrtConfiguration;
|
||||
import org.openhab.binding.asuswrt.internal.structures.AsuswrtCredentials;
|
||||
import org.openhab.binding.asuswrt.internal.things.AsuswrtRouter;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtConnector} is a {@link AsuswrtHttpClient} that also keeps track of router configuration and
|
||||
* credentials.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtConnector extends AsuswrtHttpClient {
|
||||
private final Logger logger = LoggerFactory.getLogger(AsuswrtConnector.class);
|
||||
private AsuswrtCredentials credentials;
|
||||
private AsuswrtConfiguration routerConfig;
|
||||
protected Long lastQuery = 0L;
|
||||
|
||||
public AsuswrtConnector(AsuswrtRouter router) {
|
||||
super(router);
|
||||
routerConfig = router.getConfiguration();
|
||||
this.credentials = new AsuswrtCredentials(routerConfig);
|
||||
}
|
||||
|
||||
/*
|
||||
* Connector commands
|
||||
*/
|
||||
|
||||
/**
|
||||
* Login to the router.
|
||||
*/
|
||||
public Boolean login() {
|
||||
String url = getURL("login.cgi");
|
||||
String encodedCredentials = credentials.getEncodedCredentials();
|
||||
String payload = "";
|
||||
|
||||
logout(); // logout (unset cookie) first
|
||||
router.errorHandler.reset();
|
||||
|
||||
logger.trace("({}) perform login to '{}' with '{}'", uid, url, encodedCredentials);
|
||||
|
||||
payload = "login_authorization=" + encodedCredentials + "}";
|
||||
ContentResponse response = getSyncRequest(url, payload);
|
||||
if (response != null) {
|
||||
setCookieFromResponse(response);
|
||||
}
|
||||
if (cookieStore.isValid()) {
|
||||
router.setState(ThingStatus.ONLINE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout and unsets the cookie.
|
||||
*/
|
||||
public void logout() {
|
||||
this.cookieStore.resetCookie();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets system information from the device.
|
||||
*/
|
||||
public void querySysInfo(boolean asyncRequest) {
|
||||
queryDeviceData(CMD_GET_SYSINFO, asyncRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries data from the device.
|
||||
*
|
||||
* @param command command constant to sent
|
||||
* @param asyncRequest <code>true</code> if request should be sent asynchronous, <code>false</code> if synchronous
|
||||
*/
|
||||
public void queryDeviceData(String command, boolean asyncRequest) {
|
||||
logger.trace("({}) queryDeviceData", uid);
|
||||
Long now = System.currentTimeMillis();
|
||||
|
||||
router.errorHandler.reset();
|
||||
if (cookieStore.cookieIsExpired()) {
|
||||
login();
|
||||
}
|
||||
|
||||
if (now > this.lastQuery + HTTP_QUERY_MIN_GAP_MS) {
|
||||
String url = getURL("appGet.cgi");
|
||||
String payload = "hook=" + command;
|
||||
this.lastQuery = now;
|
||||
|
||||
// Send payload as url parameter
|
||||
url = url + "?" + payload;
|
||||
url = url.replace(";", "%3B");
|
||||
|
||||
// Send asynchronous or synchronous HTTP request
|
||||
if (asyncRequest) {
|
||||
sendAsyncRequest(url, payload, command);
|
||||
} else {
|
||||
sendSyncRequest(url, payload, command);
|
||||
}
|
||||
} else {
|
||||
logger.trace("({}) query skipped cause of min_gap: {} <- {}", uid, now, lastQuery);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Response handling
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handle successful HTTP response by delegating to the connector class.
|
||||
*
|
||||
* @param responseBody response body as string
|
||||
* @param command command constant which was sent
|
||||
*/
|
||||
@Override
|
||||
protected void handleHttpSuccessResponse(String responseBody, String command) {
|
||||
JsonObject jsonObject = getJsonFromString(responseBody);
|
||||
router.dataReceived(jsonObject, command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles HTTP result failures.
|
||||
*
|
||||
* @param e Throwable exception
|
||||
* @param payload full payload for debugging
|
||||
*/
|
||||
@Override
|
||||
protected void handleHttpResultError(Throwable e, String payload) {
|
||||
super.handleHttpResultError(e, payload);
|
||||
String errorMessage = getValueOrDefault(e.getMessage(), "");
|
||||
|
||||
if (e instanceof TimeoutException || e instanceof NoRouteToHostException) {
|
||||
router.errorHandler.raiseError(ERR_CONN_TIMEOUT, errorMessage);
|
||||
router.setState(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, errorMessage);
|
||||
} else if (e instanceof SSLException || e instanceof SSLKeyException || e instanceof SSLHandshakeException) {
|
||||
router.errorHandler.raiseError(ERR_SSL_EXCEPTION, payload);
|
||||
router.setState(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, errorMessage);
|
||||
} else if (e instanceof InterruptedException) {
|
||||
router.errorHandler.raiseError(new Exception(e), payload);
|
||||
router.setState(ThingStatus.UNKNOWN, ThingStatusDetail.COMMUNICATION_ERROR, errorMessage);
|
||||
} else {
|
||||
router.errorHandler.raiseError(new Exception(e), errorMessage);
|
||||
router.setState(ThingStatus.UNKNOWN, ThingStatusDetail.COMMUNICATION_ERROR, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Other
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets the target URL.
|
||||
*/
|
||||
protected String getURL(String site) {
|
||||
String url = routerConfig.hostname;
|
||||
if (routerConfig.useSSL) {
|
||||
url = HTTPS_PROTOCOL + url;
|
||||
if (routerConfig.httpsPort != 443) {
|
||||
url = url + ":" + routerConfig.httpsPort;
|
||||
}
|
||||
} else {
|
||||
url = HTTP_PROTOCOL + url;
|
||||
if (routerConfig.httpPort != 80) {
|
||||
url = url + ":" + routerConfig.httpPort;
|
||||
}
|
||||
}
|
||||
return url + "/" + site;
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* 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.api;
|
||||
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingSettings.COOKIE_LIFETIME_S;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtCookie} is used for storing cookie details.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtCookie {
|
||||
protected String cookie = "";
|
||||
protected String token = "";
|
||||
protected Long cookieTimeStamp = 0L;
|
||||
|
||||
/*
|
||||
* Set and reset functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets a new cookie.
|
||||
*/
|
||||
public void setCookie(String cookie) {
|
||||
this.cookie = cookie;
|
||||
cookieTimeStamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets a cookie.
|
||||
*/
|
||||
public void resetCookie() {
|
||||
cookie = "";
|
||||
token = "";
|
||||
cookieTimeStamp = 0L;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cookie checks
|
||||
*/
|
||||
|
||||
/**
|
||||
* Checks if a cookie is set.
|
||||
*/
|
||||
public boolean cookieIsSet() {
|
||||
return !cookie.isBlank();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a cookie is expired.
|
||||
*
|
||||
* @return <code>true</code> if cookie is set and expired
|
||||
*/
|
||||
public boolean cookieIsExpired() {
|
||||
return cookieTimeStamp > 0L && System.currentTimeMillis() > cookieTimeStamp + (COOKIE_LIFETIME_S * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a cookie is set and not expired.
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return !cookieIsExpired() && cookieIsSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cookie.
|
||||
*/
|
||||
public String getCookie() {
|
||||
return cookie;
|
||||
}
|
||||
}
|
@ -0,0 +1,249 @@
|
||||
/**
|
||||
* 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.api;
|
||||
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingConstants.JSON_MEMBER_TOKEN;
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingSettings.*;
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtErrorConstants.*;
|
||||
import static org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils.getValueOrDefault;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpResponse;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.client.api.Result;
|
||||
import org.eclipse.jetty.client.util.BufferingResponseListener;
|
||||
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils;
|
||||
import org.openhab.binding.asuswrt.internal.things.AsuswrtRouter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtHttpClient} is used for (a)synchronous HTTP requests.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtHttpClient {
|
||||
private final Logger logger = LoggerFactory.getLogger(AsuswrtHttpClient.class);
|
||||
private Gson gson = new Gson();
|
||||
protected AsuswrtRouter router;
|
||||
protected final String uid;
|
||||
public AsuswrtCookie cookieStore = new AsuswrtCookie();
|
||||
|
||||
public AsuswrtHttpClient(AsuswrtRouter router) {
|
||||
this.router = router;
|
||||
uid = router.getUID().toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* HTTP actions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sends a synchronous HTTP request.
|
||||
*
|
||||
* The result will be handled in {@link #handleHttpSuccessResponse(String, String) or
|
||||
* {@link #handleHttpResultError(Throwable)}.
|
||||
*
|
||||
* If the response should be returned use {@link #getSyncRequest(String, String)} instead.
|
||||
*
|
||||
* @param url the URL the request is sent to
|
||||
* @param payload the payload to send
|
||||
* @param command the command to perform
|
||||
*/
|
||||
protected void sendSyncRequest(String url, String payload, String command) {
|
||||
ContentResponse response = getSyncRequest(url, payload);
|
||||
if (response != null) {
|
||||
handleHttpSuccessResponse(response.getContentAsString(), command);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a synchronous HTTP request.
|
||||
*
|
||||
* @param url the URL the request is sent to
|
||||
* @param payload the payload to send
|
||||
* @return {@link ContentResponse} of the request
|
||||
*/
|
||||
protected @Nullable ContentResponse getSyncRequest(String url, String payload) {
|
||||
logger.trace("({}) sendRequest '{}' to '{}' with cookie '{}'", uid, payload, url, cookieStore.getCookie());
|
||||
Request httpRequest = this.router.getHttpClient().newRequest(url).method(HttpMethod.POST.toString());
|
||||
|
||||
// Set header
|
||||
httpRequest = setHeaders(httpRequest);
|
||||
httpRequest.timeout(HTTP_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
|
||||
// Add request body
|
||||
httpRequest.content(new StringContentProvider(payload, HTTP_CONTENT_CHARSET), HTTP_CONTENT_TYPE);
|
||||
try {
|
||||
return httpRequest.send();
|
||||
} catch (Exception e) {
|
||||
handleHttpResultError(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an asynchronous HTTP request so it does not wait for an answer.
|
||||
*
|
||||
* The result will be handled in {@link #handleHttpSuccessResponse(String, String) or
|
||||
* {@link #handleHttpResultError(Throwable)}.
|
||||
*
|
||||
* @param url the URL to which the request is sent to
|
||||
* @param payload the payload data
|
||||
* @param command command to execute, this will handle ResponseType
|
||||
*/
|
||||
protected void sendAsyncRequest(String url, String payload, String command) {
|
||||
logger.trace("({}) sendAsyncRequest to '{}' with cookie '{}'", uid, url, cookieStore.getCookie());
|
||||
try {
|
||||
Request httpRequest = router.getHttpClient().newRequest(url).method(HttpMethod.POST.toString());
|
||||
|
||||
// Set header
|
||||
httpRequest = setHeaders(httpRequest);
|
||||
|
||||
// Add request body
|
||||
httpRequest.content(new StringContentProvider(payload, HTTP_CONTENT_CHARSET), HTTP_CONTENT_TYPE);
|
||||
|
||||
httpRequest.timeout(HTTP_TIMEOUT_MS, TimeUnit.MILLISECONDS).send(new BufferingResponseListener() {
|
||||
@NonNullByDefault({})
|
||||
@Override
|
||||
public void onComplete(Result result) {
|
||||
final HttpResponse response = (HttpResponse) result.getResponse();
|
||||
if (result.getFailure() != null) {
|
||||
// Handle result errors
|
||||
handleHttpResultError(result.getFailure());
|
||||
} else if (response.getStatus() != 200) {
|
||||
logger.debug("({}) sendAsyncRequest response error '{}'", uid, response.getStatus());
|
||||
router.errorHandler.raiseError(ERR_RESPONSE, getContentAsString());
|
||||
} else {
|
||||
// Request successful
|
||||
String rBody = getContentAsString();
|
||||
logger.trace("({}) requestCompleted '{}'", uid, rBody);
|
||||
// Handle result
|
||||
handleHttpSuccessResponse(rBody, command);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
router.errorHandler.raiseError(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets HTTP headers.
|
||||
*/
|
||||
private Request setHeaders(Request httpRequest) {
|
||||
// Set header
|
||||
httpRequest.header("content-type", HTTP_CONTENT_TYPE);
|
||||
httpRequest.header("user-agent", HTTP_USER_AGENT);
|
||||
if (cookieStore.isValid()) {
|
||||
httpRequest.header("cookie", cookieStore.getCookie());
|
||||
}
|
||||
return httpRequest;
|
||||
}
|
||||
|
||||
/*
|
||||
* Response handling
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handles HTTP result failures.
|
||||
*
|
||||
* @param e the exception
|
||||
* @param payload full payload for debugging
|
||||
*/
|
||||
protected void handleHttpResultError(Throwable e, String payload) {
|
||||
String errorMessage = getValueOrDefault(e.getMessage(), "");
|
||||
|
||||
if (e instanceof TimeoutException) {
|
||||
logger.debug("({}) sendAsyncRequest timeout'{}'", uid, errorMessage);
|
||||
} else if (e instanceof InterruptedException) {
|
||||
logger.debug("({}) sending request interrupted: {}", uid, e.toString());
|
||||
} else {
|
||||
logger.debug("({}) sendAsyncRequest failed'{}'", uid, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleHttpResultError(Throwable e) {
|
||||
handleHttpResultError(e, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a successful HTTP response.
|
||||
*
|
||||
* @param responseBody response body as string
|
||||
* @param command command constant which was sent
|
||||
*/
|
||||
protected void handleHttpSuccessResponse(String responseBody, String command) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a cookie from a response.
|
||||
*/
|
||||
protected void setCookieFromResponse(ContentResponse response) {
|
||||
cookieStore.resetCookie();
|
||||
if (response.getStatus() == 200) {
|
||||
String rBody = response.getContentAsString();
|
||||
logger.trace("({}) received response '{}'", uid, rBody);
|
||||
try {
|
||||
/* get json object 'asus_token' */
|
||||
JsonObject jsonObject = gson.fromJson(rBody, JsonObject.class);
|
||||
if (jsonObject != null && jsonObject.has(JSON_MEMBER_TOKEN)) {
|
||||
String token = jsonObject.get(JSON_MEMBER_TOKEN).getAsString();
|
||||
this.cookieStore.setCookie("asus_token=" + token);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("({}) {} on login request '{}'", uid, ERR_RESPONSE, e.getMessage());
|
||||
router.errorHandler.raiseError(ERR_RESPONSE, e.getMessage());
|
||||
}
|
||||
} else {
|
||||
String reason = AsuswrtUtils.getValueOrDefault(response.getReason(), "");
|
||||
router.errorHandler.raiseError(ERR_RESPONSE, reason);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets JSON from a response.
|
||||
*/
|
||||
protected JsonObject getJsonFromResponse(ContentResponse response) {
|
||||
return getJsonFromString(response.getContentAsString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets JSON from a response.
|
||||
*/
|
||||
protected JsonObject getJsonFromString(String responseBody) {
|
||||
try {
|
||||
JsonObject jsonObject = gson.fromJson(responseBody, JsonObject.class);
|
||||
logger.trace("({}) received result: {}", uid, responseBody);
|
||||
/* get error code (0=success) */
|
||||
if (jsonObject != null) {
|
||||
return jsonObject;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("({}) {} {}", uid, ERR_JSON_FORMAT, responseBody);
|
||||
router.getErrorHandler().raiseError(e);
|
||||
}
|
||||
return new JsonObject();
|
||||
}
|
||||
}
|
@ -0,0 +1,194 @@
|
||||
/**
|
||||
* 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.constants;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtBindingConstants} class defines common constants, which are used across the whole binding.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "asuswrt";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_ROUTER = new ThingTypeUID(BINDING_ID, "router");
|
||||
public static final ThingTypeUID THING_TYPE_CLIENT = new ThingTypeUID(BINDING_ID, "client");
|
||||
public static final ThingTypeUID THING_TYPE_INTERFACE = new ThingTypeUID(BINDING_ID, "interface");
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_ROUTER, THING_TYPE_CLIENT,
|
||||
THING_TYPE_INTERFACE);
|
||||
|
||||
// Things with channel groups
|
||||
public static final Set<ThingTypeUID> CHANNEL_GROUP_THING_SET = Collections
|
||||
.unmodifiableSet(Stream.of(SUPPORTED_THING_TYPES_UIDS).flatMap(Set::stream).collect(Collectors.toSet()));
|
||||
|
||||
/*
|
||||
* Channel lists
|
||||
* Item channel names
|
||||
*/
|
||||
|
||||
// General event constants
|
||||
public static final String EVENT_STATE_CONNECTED = "connected";
|
||||
public static final String EVENT_STATE_GONE = "gone";
|
||||
public static final String EVENT_STATE_DISCONNECTED = "disconnected";
|
||||
|
||||
// Global channels
|
||||
public static final String CHANNELS_ALL = "any-channel";
|
||||
|
||||
// Channel group system info
|
||||
public static final String CHANNEL_GROUP_SYSINFO = "sys-info";
|
||||
public static final String CHANNEL_MEM_FREE = "mem-free";
|
||||
public static final String CHANNEL_MEM_FREE_PERCENT = "mem-free-percent";
|
||||
public static final String CHANNEL_MEM_TOTAL = "mem-total";
|
||||
public static final String CHANNEL_MEM_USED = "mem-used";
|
||||
public static final String CHANNEL_MEM_USED_PERCENT = "mem-used-percent";
|
||||
public static final String CHANNEL_CPU_USED_PERCENT = "cpu-used-percent";
|
||||
|
||||
// Channel group interface information
|
||||
public static final String CHANNEL_GROUP_NETWORK = "network-info";
|
||||
public static final String CHANNEL_NETWORK_IP = "ip-address";
|
||||
public static final String CHANNEL_NETWORK_MAC = "mac-address";
|
||||
public static final String CHANNEL_NETWORK_MASK = "subnet";
|
||||
public static final String CHANNEL_NETWORK_GATEWAY = "gateway";
|
||||
public static final String CHANNEL_NETWORK_METHOD = "ip-method";
|
||||
public static final String CHANNEL_NETWORK_DNS = "dns-servers";
|
||||
public static final String CHANNEL_NETWORK_STATE = "network-state";
|
||||
public static final String CHANNEL_NETWORK_INTERNET = "internet-state";
|
||||
public static final String EVENT_CONNECTION = "connection-event";
|
||||
|
||||
// Channel group clientList information
|
||||
public static final String CHANNEL_GROUP_CLIENTS = "client-list";
|
||||
public static final String CHANNEL_CLIENTS_KNOWN = "known-clients";
|
||||
public static final String CHANNEL_CLIENTS_ONLINE = "online-clients";
|
||||
public static final String CHANNEL_CLIENTS_COUNT = "online-clients-count";
|
||||
public static final String CHANNEL_CLIENTS_ONLINE_MAC = "online-macs";
|
||||
public static final String EVENT_CLIENT_CONNECTION = "client-online-event";
|
||||
|
||||
// Channel group client information
|
||||
public static final String CHANNEL_GROUP_CLIENT = "client";
|
||||
public static final String CHANNEL_CLIENT_NICKNAME = "client-name";
|
||||
|
||||
// Channel group traffic
|
||||
public static final String CHANNEL_GROUP_TRAFFIC = "traffic";
|
||||
public static final String CHANNEL_TRAFFIC_TOTAL_RX = "total-rx";
|
||||
public static final String CHANNEL_TRAFFIC_TOTAL_TX = "total-tx";
|
||||
public static final String CHANNEL_TRAFFIC_TODAY_RX = "today-rx";
|
||||
public static final String CHANNEL_TRAFFIC_TODAY_TX = "today-tx";
|
||||
public static final String CHANNEL_TRAFFIC_CURRENT_RX = "current-rx";
|
||||
public static final String CHANNEL_TRAFFIC_CURRENT_TX = "current-tx";
|
||||
|
||||
/*
|
||||
* Properties
|
||||
*/
|
||||
|
||||
// Interface
|
||||
public static final String PROPERTY_INTERFACE_NAME = "interfaceName";
|
||||
public static final String NETWORK_REPRESENTATION_PROPERTY = "interfaceName";
|
||||
// client
|
||||
public static final String PROPERTY_CLIENT_NAME = "dnsName";
|
||||
public static final String CLIENT_REPRESENTATION_PROPERTY = "macAddress";
|
||||
|
||||
/*
|
||||
* JSON request member names
|
||||
* Member names of JSON response
|
||||
*/
|
||||
public static final String JSON_MEMBER_TOKEN = "asus_token";
|
||||
// sysInfo
|
||||
public static final String JSON_MEMBER_PRODUCTID = "productid";
|
||||
public static final String JSON_MEMBER_FIRMWARE = "firmver";
|
||||
public static final String JSON_MEMBER_BUILD = "buildno";
|
||||
public static final String JSON_MEMBER_EXTENDNO = "extendo";
|
||||
public static final String JSON_MEMBER_MAC = "lan_hwaddr";
|
||||
|
||||
// lanInfo
|
||||
public static final String JSON_MEMBER_LAN_IP = "lan_ipaddr";
|
||||
public static final String JSON_MEMBER_LAN_GATEWAY = "lan_gateway";
|
||||
public static final String JSON_MEMBER_LAN_NETMASK = "lan_netmask";
|
||||
public static final String JSON_MEMBER_LAN_PROTO = "lan_proto";
|
||||
|
||||
// wanInfo
|
||||
public static final String JSON_MEMBER_WAN_IP = "wanlink-ipaddr";
|
||||
public static final String JSON_MEMBER_WAN_GATEWAY = "wanlink-gateway";
|
||||
public static final String JSON_MEMBER_WAN_NETMASK = "wanlink-netmask";
|
||||
public static final String JSON_MEMBER_WAN_PROTO = "wanlink-type";
|
||||
public static final String JSON_MEMBER_WAN_DNS_SERVER = "wanlink-dns";
|
||||
public static final String JSON_MEMBER_WAN_CONNECTED = "wanlink-status";
|
||||
|
||||
// clientInfo
|
||||
public static final String JSON_MEMBER_CLIENTS = "get_clientlist";
|
||||
public static final String JSON_MEMBER_MACLIST = "maclist";
|
||||
public static final String JSON_MEMBER_API_LEVEL = "ClientAPILevel";
|
||||
public static final String JSON_MEMBER_CLIENT_RXCUR = "curRx";
|
||||
public static final String JSON_MEMBER_CLIENT_TXCUR = "curTx";
|
||||
public static final String JSON_MEMBER_CLIENT_DEFTYPE = "defaultType";
|
||||
public static final String JSON_MEMBER_CLIENT_DPIDEVICE = "dpiDevice";
|
||||
public static final String JSON_MEMBER_CLIENT_DPITYPE = "dpiType";
|
||||
public static final String JSON_MEMBER_CLIENT_IPFROM = "from";
|
||||
public static final String JSON_MEMBER_CLIENT_GROUP = "group";
|
||||
public static final String JSON_MEMBER_CLIENT_INETMODE = "internetMode";
|
||||
public static final String JSON_MEMBER_CLIENT_INETSTATE = "internet-state";
|
||||
public static final String JSON_MEMBER_CLIENT_IP = "ip";
|
||||
public static final String JSON_MEMBER_CLIENT_IPMETHOD = "ip-method";
|
||||
public static final String JSON_MEMBER_CLIENT_IPGATEWAY = "isGateway";
|
||||
public static final String JSON_MEMBER_CLIENT_GN = "isGN";
|
||||
public static final String JSON_MEMBER_CLIENT_ITUNES = "isITunes";
|
||||
public static final String JSON_MEMBER_CLIENT_LOGIN = "isLogin";
|
||||
public static final String JSON_MEMBER_CLIENT_ONLINE = "isOnline";
|
||||
public static final String JSON_MEMBER_CLIENT_PRINTER = "isPrinter";
|
||||
public static final String JSON_MEMBER_CLIENT_WEBSRV = "isWebServer";
|
||||
public static final String JSON_MEMBER_CLIENT_WIFI = "isWL";
|
||||
public static final String JSON_MEMBER_CLIENT_KEEPARP = "keeparp";
|
||||
public static final String JSON_MEMBER_CLIENT_MAC = "mac";
|
||||
public static final String JSON_MEMBER_CLIENT_MACREPEAT = "macRepeat";
|
||||
public static final String JSON_MEMBER_CLIENT_NAME = "name";
|
||||
public static final String JSON_MEMBER_CLIENT_NICK = "nickName";
|
||||
public static final String JSON_MEMBER_CLIENT_MODE = "opMode";
|
||||
public static final String JSON_MEMBER_CLIENT_QOSLVL = "qosLevel";
|
||||
public static final String JSON_MEMBER_CLIENT_ROG = "ROG";
|
||||
public static final String JSON_MEMBER_CLIENT_RSSI = "rssi";
|
||||
public static final String JSON_MEMBER_CLIENT_SSID = "ssid";
|
||||
public static final String JSON_MEMBER_CLIENT_RXTOTAL = "totalRx";
|
||||
public static final String JSON_MEMBER_CLIENT_TXTOTAL = "totalTx";
|
||||
public static final String JSON_MEMBER_CLIENT_VENDOR = "vendor";
|
||||
public static final String JSON_MEMBER_CLIENT_CONNECTTIME = "wlConnectTime";
|
||||
public static final String JSON_MEMBER_CLIENT_WTFAST = "wtfast";
|
||||
|
||||
// usage
|
||||
public static final String JSON_MEMBER_CPU_USAGE = "cpu_usage";
|
||||
public static final String JSON_MEMBER_CPU_TOTAL = "cpu{x}_total";
|
||||
public static final String JSON_MEMBER_CPU_USED = "cpu{x}_usage";
|
||||
public static final String JSON_MEMBER_MEM_USAGE = "memory_usage";
|
||||
public static final String JSON_MEMBER_MEM_TOTAL = "mem_total";
|
||||
public static final String JSON_MEMBER_MEM_USED = "mem_used";
|
||||
public static final String JSON_MEMBER_MEM_FREE = "mem_free";
|
||||
public static final Integer USAGE_CPU_COUNT = 4; // max count of CPU cores
|
||||
|
||||
// traffic
|
||||
public static final String JSON_MEMBER_TRAFFIC = "netdev";
|
||||
public static final String JSON_MEMBER_INET_RX = "INTERNET_rx";
|
||||
public static final String JSON_MEMBER_INET_TX = "INTERNET_tx";
|
||||
public static final String JSON_MEMBER_LAN_RX = "WIRED_rx";
|
||||
public static final String JSON_MEMBER_LAN_TX = "WIRED_tx";
|
||||
public static final String JSON_MEMBER_WLAN_RX = "WIRELESS{}_rx";
|
||||
public static final String JSON_MEMBER_WLAN_TX = "WIRELESS{}_tx";
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 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.constants;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtBindingSettings} class defines common settings constants, which are used across the whole binding.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtBindingSettings {
|
||||
|
||||
// Binding settings
|
||||
public static final Integer HTTP_MAX_CONNECTIONS = 10; // setMaxConnectionsPerDestination for HTTP-Client
|
||||
public static final Integer HTTP_MAX_QUEUED_REQUESTS = 10; // setMaxRequestsQueuedPerDestination for HTTP-Client
|
||||
public static final Integer HTTP_TIMEOUT_MS = 5000; // http request timeout
|
||||
public static final Integer HTTP_QUERY_MIN_GAP_MS = 5000; // http minimun gap between query data requests
|
||||
public static final String HTTP_CONTENT_TYPE = "application/x-www-form-urlencoded";
|
||||
public static final String HTTP_USER_AGENT = "asusrouter-Android-DUTUtil-1.0.0.3.58-163";
|
||||
public static final String HTTP_CONTENT_CHARSET = "utf-8";
|
||||
public static final String HTTP_PROTOCOL = "http://";
|
||||
public static final String HTTPS_PROTOCOL = "https://";
|
||||
public static final Boolean HTTP_SSL_TRUST_ALL = true; // trust all ssl-certs
|
||||
|
||||
public static final Integer COOKIE_LIFETIME_S = 3600; // lifetime of login-cookie
|
||||
public static final Integer POLLING_INTERVAL_S_MIN = 5; // minimum polling interval
|
||||
public static final Integer POLLING_INTERVAL_S_DEFAULT = 20; // default polling interval
|
||||
public static final Integer RECONNECT_INTERVAL_S = 30; // interval trying try to reconnect to router
|
||||
public static final Integer DISCOVERY_TIMEOUT_S = 10; // discovery service timeout in s
|
||||
public static final Integer DISCOVERY_AUTOREMOVE_S = 1800; // discovery service remove things after x seconds
|
||||
|
||||
// List of device commands
|
||||
public static final String CMD_GET_SYSINFO = "nvram_get(productid);nvram_get(firmver);nvram_get(buildno);nvram_get(extendno);nvram_get(lan_hwaddr);";
|
||||
public static final String CMD_GET_LANINFO = "nvram_get(lan_hwaddr);nvram_get(lan_ipaddr);nvram_get(lan_proto);nvram_get(lan_netmask);nvram_get(lan_gateway);";
|
||||
public static final String CMD_GET_WANINFO = "wanlink(status);wanlink(type);wanlink(ipaddr);wanlink(netmask);wanlink(gateway);wanlink(dns);wanlink(lease);wanlink(expires);";
|
||||
public static final String CMD_GET_CLIENTLIST = "get_clientlist();";
|
||||
public static final String CMD_GET_TRAFFIC = "netdev(appobj);";
|
||||
public static final String CMD_GET_UPTIME = "uptime();";
|
||||
public static final String CMD_GET_USAGE = "cpu_usage(appobj);memory_usage(appobj);";
|
||||
public static final String CMD_GET_MEMUSAGE = "memory_usage(appobj);";
|
||||
public static final String CMD_GET_CPUUSAGE = "cpu_usage(appobj);";
|
||||
|
||||
// List of interfaces
|
||||
public static final String INTERFACE_WAN = "wan";
|
||||
public static final String INTERFACE_LAN = "lan";
|
||||
public static final String INTERFACE_WLAN = "wlan";
|
||||
public static final String INTERFACE_CLIENT = "client";
|
||||
public static final Set<String> INTERFACE_LIST = Set.of(INTERFACE_WAN, INTERFACE_LAN);
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 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.constants;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtErrorConstants} class defines error constants, which are used across the whole binding.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtErrorConstants {
|
||||
|
||||
public static final String ERR_HTTP_CLIENT_FAILED = "Starting 'httpClient' failed";
|
||||
public static final String ERR_CONN_TIMEOUT = "Connection timeout";
|
||||
public static final String ERR_RESPONSE = "Response not okay";
|
||||
public static final String ERR_JSON_FORMAT = "Unexpected or malfomrated JSON response";
|
||||
public static final String ERR_JSON_UNKNOWN_MEMBER = "JSON member not found";
|
||||
public static final String ERR_SSL_EXCEPTION = "SSL Exception";
|
||||
public static final String ERR_INVALID_MAC_ADDRESS = "Invalid MAC address";
|
||||
public static final String ERR_BRIDGE_OFFLINE = "Bridge is offline";
|
||||
public static final String ERR_BRIDGE_NOT_DECLARED = "Bridge not found or not declared";
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/**
|
||||
* 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.helpers;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This class is used for handling errors.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtErrorHandler {
|
||||
private String errorMessage = "";
|
||||
private String infoMessage = "";
|
||||
|
||||
public AsuswrtErrorHandler() {
|
||||
}
|
||||
|
||||
public AsuswrtErrorHandler(Exception ex) {
|
||||
raiseError(ex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Public functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Raises a new error.
|
||||
*
|
||||
* @param exception the exception
|
||||
*/
|
||||
public void raiseError(Exception ex) {
|
||||
raiseError(ex, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Raises a new error.
|
||||
*
|
||||
* @param exception the exception
|
||||
* @param infoMessage optional info message
|
||||
*/
|
||||
public void raiseError(Exception ex, @Nullable String infoMessage) {
|
||||
this.errorMessage = AsuswrtUtils.getValueOrDefault(ex.getMessage(), "");
|
||||
this.infoMessage = AsuswrtUtils.getValueOrDefault(infoMessage, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Raises a new error.
|
||||
*
|
||||
* @param errorMessage the error message
|
||||
* @param infoMessage optional info message
|
||||
*/
|
||||
public void raiseError(String errorMessage, @Nullable String infoMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
this.infoMessage = AsuswrtUtils.getValueOrDefault(infoMessage, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the error.
|
||||
*/
|
||||
public void reset() {
|
||||
errorMessage = "";
|
||||
infoMessage = "";
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the error message.
|
||||
*/
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the info message.
|
||||
*/
|
||||
public String getInfoMessage() {
|
||||
return infoMessage;
|
||||
}
|
||||
}
|
@ -0,0 +1,414 @@
|
||||
/**
|
||||
* 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.helpers;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.measure.Unit;
|
||||
import javax.measure.quantity.Energy;
|
||||
import javax.measure.quantity.Power;
|
||||
import javax.measure.quantity.Time;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.types.State;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtUtils} contains utility helper functions.
|
||||
*
|
||||
* @author Christian Wild - Initial Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtUtils {
|
||||
private static final Pattern PATTERN_MAC_PAIRS = Pattern.compile("^([a-fA-F0-9]{2}[:\\.-]?){5}[a-fA-F0-9]{2}$");
|
||||
private static final Pattern PATTERN_MAC_TRIPLES = Pattern.compile("^([a-fA-F0-9]{3}[:\\.-]?){3}[a-fA-F0-9]{3}$");
|
||||
|
||||
/*
|
||||
* Calculation utility methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* Limits a value between limits.
|
||||
*
|
||||
* @param value the value that should be limited
|
||||
* @param lowerLimit will be returned if value is below
|
||||
* @param upperLimit will be returned if value is higher
|
||||
*/
|
||||
public static int limitVal(@Nullable Integer value, int lowerLimit, int upperLimit) {
|
||||
if (value == null || value < lowerLimit) {
|
||||
return lowerLimit;
|
||||
} else if (value > upperLimit) {
|
||||
return upperLimit;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Formatting utility methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a value or default value when the value is <code>null</code>.
|
||||
*
|
||||
* @param <T> Type of value
|
||||
* @param value the value which should be checked
|
||||
* @param defaultValue the default value that will be returned when <code>value</code> is <code>null</code>
|
||||
*/
|
||||
public static <T> T getValueOrDefault(@Nullable T value, T defaultValue) {
|
||||
return value == null ? defaultValue : value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a MAC address by replacing old separator characters and adding new ones.
|
||||
*
|
||||
* @param mac unformatted MAC address
|
||||
* @param newSeparatorChar new separator characters (e.g. ":","-" )
|
||||
*/
|
||||
public static String formatMac(String mac, char newSeparatorChar) {
|
||||
String unformatedMac = unformatMac(mac);
|
||||
String formatedMac = "";
|
||||
try {
|
||||
formatedMac = unformatedMac.replaceAll("(.{2})", "$1" + newSeparatorChar).substring(0, 17);
|
||||
return formatedMac;
|
||||
} catch (Exception e) {
|
||||
return mac;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unformats a MAC address. Removes all separator characters.
|
||||
*/
|
||||
public static String unformatMac(String rawMac) {
|
||||
String mac = rawMac;
|
||||
mac = mac.replace("-", "");
|
||||
mac = mac.replace(":", "");
|
||||
mac = mac.replace(".", "");
|
||||
mac = mac.replace(" ", "");
|
||||
return mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a MAC address is valid.
|
||||
*/
|
||||
public static boolean isValidMacAddress(String mac) {
|
||||
// MAC-Addresses usually are 6 * 2 hex nibbles separated by colons,
|
||||
// but apparently it is legal to have 4 * 3 hex nibbles as well,
|
||||
// and the separators can be any of : or - or . or nothing.
|
||||
return (PATTERN_MAC_PAIRS.matcher(mac).find() || PATTERN_MAC_TRIPLES.matcher(mac).find());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a hexadecimal String to a byte array.
|
||||
*/
|
||||
public static byte[] hexStringToByteArray(String s) {
|
||||
int len = s.length();
|
||||
byte[] data = new byte[len / 2];
|
||||
try {
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link String} to a <code>boolean</code>.
|
||||
*
|
||||
* @param s the string to be converted ('0', '1', '-1', 'true', 'false')
|
||||
* @param defVal default value if no match was found
|
||||
*/
|
||||
public static boolean stringToBool(@Nullable String s, boolean defVal) {
|
||||
if (s == null) {
|
||||
return defVal;
|
||||
} else if ("1".equals(s) || "-1".equals(s)) {
|
||||
return true;
|
||||
} else if ("0".equals(s)) {
|
||||
return false;
|
||||
} else {
|
||||
try {
|
||||
return Boolean.parseBoolean(s);
|
||||
} catch (Exception e) {
|
||||
return defVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link String} to an <code>int</code>.
|
||||
*
|
||||
* @param s the string to be converted
|
||||
* @param defVal the default value if the string is not a number
|
||||
*/
|
||||
public static int stringToInteger(@Nullable String s, int defVal) {
|
||||
if (s == null) {
|
||||
return defVal;
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(s);
|
||||
} catch (Exception e) {
|
||||
return defVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the provided string if it is not <code>null</code>, empty or blank. Otherwise the default value is
|
||||
* returned.
|
||||
*
|
||||
* @param s the string to check
|
||||
* @param defVal the default value
|
||||
* @return the string or the default value
|
||||
*/
|
||||
public static String stringOrDefault(@Nullable String s, String defVal) {
|
||||
if (s == null || s.isEmpty() || s.isBlank()) {
|
||||
return defVal;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* JSON formatting
|
||||
*/
|
||||
|
||||
/**
|
||||
* Checks if a String is valid JSON.
|
||||
*/
|
||||
public static boolean isValidJson(String json) {
|
||||
try {
|
||||
Gson gson = new Gson();
|
||||
JsonObject jsnObject = gson.fromJson(json, JsonObject.class);
|
||||
return jsnObject != null;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link String} value from a {@link JsonObject}.
|
||||
*
|
||||
* @param jsonObject the object that will be searched for the key
|
||||
* @param name the name of the key containing the value
|
||||
* @param defVal the default value if the key does not exist
|
||||
*/
|
||||
public static String jsonObjectToString(@Nullable JsonObject jsonObject, String name, String defVal) {
|
||||
if (jsonObject != null && jsonObject.has(name)) {
|
||||
return jsonObject.get(name).getAsString();
|
||||
} else {
|
||||
return defVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link String} value from a {@link JsonObject} using an empty String as default value.
|
||||
*
|
||||
* @param jsonObject the object that will be searched for the key
|
||||
* @param name the name of the key containing the value
|
||||
*/
|
||||
public static String jsonObjectToString(@Nullable JsonObject jsonObject, String name) {
|
||||
return jsonObjectToString(jsonObject, name, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a <code>boolean</code> value from a {@link JsonObject}.
|
||||
*
|
||||
* @param jsonObject the object that will be searched for the key
|
||||
* @param name the name of the key containing the value
|
||||
* @param defVal the default value if the key does not exist
|
||||
*/
|
||||
public static boolean jsonObjectToBool(@Nullable JsonObject jsonObject, String name, boolean defVal) {
|
||||
if (jsonObject != null && jsonObject.has(name)) {
|
||||
JsonPrimitive o = jsonObject.getAsJsonPrimitive(name);
|
||||
if (o.isBoolean()) {
|
||||
return jsonObject.get(name).getAsBoolean();
|
||||
} else if (o.isNumber()) {
|
||||
Integer iVal = jsonObject.get(name).getAsInt();
|
||||
return (iVal.equals(1) || iVal.equals(-1));
|
||||
} else if (o.isString()) {
|
||||
String val = jsonObject.get(name).getAsString();
|
||||
return stringToBool(val, defVal);
|
||||
}
|
||||
}
|
||||
return defVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a <code>boolean</code> value from a {@link JsonObject} using <code>false</code> as default value.
|
||||
*
|
||||
* @param jsonObject the object that will be searched for the key
|
||||
* @param name the name of the key containing the value
|
||||
*/
|
||||
public static boolean jsonObjectToBool(@Nullable JsonObject jsonObject, String name) {
|
||||
return jsonObjectToBool(jsonObject, name, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an <code>int</code> value from a {@link JsonObject}.
|
||||
*
|
||||
* @param jsonObject the object that will be searched for the key
|
||||
* @param name the name of the key containing the value
|
||||
* @param defVal the default value if the key does not exist
|
||||
*/
|
||||
public static int jsonObjectToInt(@Nullable JsonObject jsonObject, String name, int defVal) {
|
||||
if (jsonObject != null && jsonObject.has(name)) {
|
||||
JsonPrimitive o = jsonObject.getAsJsonPrimitive(name);
|
||||
if (o.isNumber()) {
|
||||
return jsonObject.get(name).getAsInt();
|
||||
} else if (o.isString()) {
|
||||
String val = jsonObject.get(name).getAsString();
|
||||
return stringToInteger(val, defVal);
|
||||
}
|
||||
}
|
||||
return defVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an <code>int</code> value from a {@link JsonObject} using <code>0</code> as default value.
|
||||
*
|
||||
* @param jsonObject the object that will be searched for the key
|
||||
* @param name the name of the key containing the value
|
||||
*/
|
||||
public static int jsonObjectToInt(@Nullable JsonObject jsonObject, String name) {
|
||||
return jsonObjectToInt(jsonObject, name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Number} value from a {@link JsonObject}.
|
||||
*
|
||||
* @param jsonObject the object that will be searched for the key
|
||||
* @param name the name of the key containing the value
|
||||
* @param defVal the default value if the key does not exist
|
||||
*/
|
||||
public static Number jsonObjectToNumber(@Nullable JsonObject jsonObject, String name, Number defVal) {
|
||||
if (jsonObject != null && jsonObject.has(name)) {
|
||||
return jsonObject.get(name).getAsNumber();
|
||||
} else {
|
||||
return defVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Number} value from a {@link JsonObject} using <code>0</code> as default value.
|
||||
*
|
||||
* @param jsonObject the object that will be searched for the key
|
||||
* @param name the name of the key containing the value
|
||||
*/
|
||||
public static Number jsonObjectToNumber(@Nullable JsonObject jsonObject, String name) {
|
||||
return jsonObjectToNumber(jsonObject, name, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Type utility methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns an {@link OnOffType} from a {@link Boolean}.
|
||||
*/
|
||||
public static OnOffType getOnOffType(@Nullable Boolean boolVal) {
|
||||
return (boolVal != null ? boolVal ? OnOffType.ON : OnOffType.OFF : OnOffType.OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link OnOffType} from an {@link Integer}.
|
||||
*/
|
||||
public static OnOffType getOnOffType(Integer intVal) {
|
||||
return intVal == 0 ? OnOffType.OFF : OnOffType.ON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link StringType} from a {@link String}.
|
||||
*/
|
||||
public static StringType getStringType(@Nullable String strVal) {
|
||||
return new StringType(strVal != null ? strVal : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link DecimalType} from a {@link Double}.
|
||||
*/
|
||||
public static DecimalType getDecimalType(@Nullable Double numVal) {
|
||||
return new DecimalType((numVal != null ? numVal : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link DecimalType} from an {@link Integer}.
|
||||
*/
|
||||
public static DecimalType getDecimalType(@Nullable Integer numVal) {
|
||||
return new DecimalType((numVal != null ? numVal : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link DecimalType} from a {@link Long}.
|
||||
*/
|
||||
public static DecimalType getDecimalType(@Nullable Long numVal) {
|
||||
return new DecimalType((numVal != null ? numVal : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link PercentType} from an {@link Integer}.
|
||||
*/
|
||||
public static PercentType getPercentType(@Nullable Integer numVal) {
|
||||
Integer val = limitVal(numVal, 0, 100);
|
||||
return new PercentType(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link HSBType} from {@link Integer}s.
|
||||
*
|
||||
* @param hue the hue color
|
||||
* @param saturation the saturation (0-100)
|
||||
* @param brightness the brightness (0-100)
|
||||
*/
|
||||
public static HSBType getHSBType(Integer hue, Integer saturation, Integer brightness) {
|
||||
DecimalType h = new DecimalType(hue);
|
||||
PercentType s = new PercentType(saturation);
|
||||
PercentType b = new PercentType(brightness);
|
||||
return new HSBType(h, s, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link QuantityType} with the {@link Time} unit.
|
||||
*/
|
||||
public static QuantityType<Time> getTimeType(@Nullable Number numVal, Unit<Time> unit) {
|
||||
return new QuantityType<>((numVal != null ? numVal : 0), unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link QuantityType} with the {@link Power} unit.
|
||||
*/
|
||||
public static QuantityType<Power> getPowerType(@Nullable Number numVal, Unit<Power> unit) {
|
||||
return new QuantityType<>((numVal != null ? numVal : 0), unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link QuantityType} with the {@link Energy} unit.
|
||||
*/
|
||||
public static QuantityType<Energy> getEnergyType(@Nullable Number numVal, Unit<Energy> unit) {
|
||||
return new QuantityType<>((numVal != null ? numVal : 0), unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link QuantityType} with the provided unit.
|
||||
*/
|
||||
public static State getQuantityType(@Nullable Number numVal, Unit<?> unit) {
|
||||
return new QuantityType<>((numVal != null ? numVal : 0), unit);
|
||||
}
|
||||
}
|
@ -0,0 +1,235 @@
|
||||
/**
|
||||
* 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.structures;
|
||||
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingConstants.*;
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingSettings.INTERFACE_CLIENT;
|
||||
import static org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtClientInfo} class stores client data.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtClientInfo {
|
||||
private AsuswrtTraffic traffic = new AsuswrtTraffic();
|
||||
private Integer defaultType = 0;
|
||||
private String dpiDevice = "";
|
||||
private String dpiType = "";
|
||||
private String from = "";
|
||||
private String group = "";
|
||||
private String internetMode = "";
|
||||
private Boolean internetState = false;
|
||||
private String ip = "";
|
||||
private String ipMethod = "";
|
||||
private Boolean isGateway = false;
|
||||
private Boolean isGN = false;
|
||||
private Boolean isITunes = false;
|
||||
private Boolean isLogin = false;
|
||||
private Boolean isOnline = false;
|
||||
private Boolean isPrinter = false;
|
||||
private Boolean isWebServer = false;
|
||||
private Integer isWL = 0;
|
||||
private String keeparp = "";
|
||||
private String mac = "";
|
||||
private Boolean macRepeat = false;
|
||||
private String name = "";
|
||||
private String nickName = "";
|
||||
private Integer opMode = 0;
|
||||
private String qosLevel = "";
|
||||
private Integer rog = 0;
|
||||
private Integer rssi = 0;
|
||||
private String ssid = "";
|
||||
private String vendor = "";
|
||||
private String wlConnectTime = "";
|
||||
private Integer wtfast = 0;
|
||||
|
||||
public AsuswrtClientInfo() {
|
||||
}
|
||||
|
||||
public AsuswrtClientInfo(JsonObject jsonObject) {
|
||||
traffic = new AsuswrtTraffic(INTERFACE_CLIENT);
|
||||
setData(jsonObject);
|
||||
}
|
||||
|
||||
public void setData(JsonObject jsonObject) {
|
||||
traffic.setData(jsonObject);
|
||||
defaultType = jsonObjectToInt(jsonObject, JSON_MEMBER_CLIENT_DEFTYPE, defaultType);
|
||||
dpiDevice = jsonObjectToString(jsonObject, JSON_MEMBER_CLIENT_DPIDEVICE, dpiDevice);
|
||||
dpiType = jsonObjectToString(jsonObject, JSON_MEMBER_CLIENT_DPITYPE, dpiType);
|
||||
from = jsonObjectToString(jsonObject, JSON_MEMBER_CLIENT_IPFROM, from);
|
||||
group = jsonObjectToString(jsonObject, JSON_MEMBER_CLIENT_GROUP, group);
|
||||
internetMode = jsonObjectToString(jsonObject, JSON_MEMBER_CLIENT_INETMODE, internetMode);
|
||||
internetState = jsonObjectToBool(jsonObject, JSON_MEMBER_CLIENT_INETSTATE, internetState);
|
||||
ip = jsonObjectToString(jsonObject, JSON_MEMBER_CLIENT_IP, ip);
|
||||
ipMethod = jsonObjectToString(jsonObject, JSON_MEMBER_CLIENT_IPMETHOD, ipMethod);
|
||||
isGateway = jsonObjectToBool(jsonObject, JSON_MEMBER_CLIENT_IPGATEWAY, isGateway);
|
||||
isGN = jsonObjectToBool(jsonObject, JSON_MEMBER_CLIENT_GN, isGN);
|
||||
isITunes = jsonObjectToBool(jsonObject, JSON_MEMBER_CLIENT_ITUNES, isITunes);
|
||||
isLogin = jsonObjectToBool(jsonObject, JSON_MEMBER_CLIENT_LOGIN, isLogin);
|
||||
isOnline = jsonObjectToBool(jsonObject, JSON_MEMBER_CLIENT_ONLINE, isOnline);
|
||||
isPrinter = jsonObjectToBool(jsonObject, JSON_MEMBER_CLIENT_PRINTER, isPrinter);
|
||||
isWebServer = jsonObjectToBool(jsonObject, JSON_MEMBER_CLIENT_WEBSRV, isWebServer);
|
||||
isWL = jsonObjectToInt(jsonObject, JSON_MEMBER_CLIENT_WIFI, isWL);
|
||||
keeparp = jsonObjectToString(jsonObject, JSON_MEMBER_CLIENT_KEEPARP, keeparp);
|
||||
mac = jsonObjectToString(jsonObject, JSON_MEMBER_CLIENT_MAC, mac);
|
||||
macRepeat = jsonObjectToBool(jsonObject, JSON_MEMBER_CLIENT_MACREPEAT, macRepeat);
|
||||
name = jsonObjectToString(jsonObject, JSON_MEMBER_CLIENT_NAME, name);
|
||||
nickName = jsonObjectToString(jsonObject, JSON_MEMBER_CLIENT_NICK, nickName);
|
||||
opMode = jsonObjectToInt(jsonObject, JSON_MEMBER_CLIENT_MODE, opMode);
|
||||
qosLevel = jsonObjectToString(jsonObject, JSON_MEMBER_CLIENT_QOSLVL, qosLevel);
|
||||
rog = jsonObjectToInt(jsonObject, JSON_MEMBER_CLIENT_ROG, rog);
|
||||
rssi = jsonObjectToInt(jsonObject, JSON_MEMBER_CLIENT_RSSI, rssi);
|
||||
ssid = jsonObjectToString(jsonObject, JSON_MEMBER_CLIENT_SSID, ssid);
|
||||
vendor = jsonObjectToString(jsonObject, JSON_MEMBER_CLIENT_VENDOR, vendor);
|
||||
wlConnectTime = jsonObjectToString(jsonObject, JSON_MEMBER_CLIENT_CONNECTTIME, wlConnectTime);
|
||||
wtfast = jsonObjectToInt(jsonObject, JSON_MEMBER_CLIENT_WTFAST, wtfast);
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters
|
||||
*/
|
||||
|
||||
public AsuswrtTraffic getTraffic() {
|
||||
return traffic;
|
||||
}
|
||||
|
||||
public Integer getDefaultType() {
|
||||
return defaultType;
|
||||
}
|
||||
|
||||
public String getDpiDevice() {
|
||||
return dpiDevice;
|
||||
}
|
||||
|
||||
public String getDpiType() {
|
||||
return dpiType;
|
||||
}
|
||||
|
||||
public String getIpFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
public String getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public String getInternetMode() {
|
||||
return internetMode;
|
||||
}
|
||||
|
||||
public Boolean getInternetState() {
|
||||
return internetState;
|
||||
}
|
||||
|
||||
public String getIP() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public String getIpMethod() {
|
||||
return ipMethod;
|
||||
}
|
||||
|
||||
public Boolean isGateway() {
|
||||
return isGateway;
|
||||
}
|
||||
|
||||
public Boolean isGN() {
|
||||
return isGN;
|
||||
}
|
||||
|
||||
public Boolean isITunes() {
|
||||
return isITunes;
|
||||
}
|
||||
|
||||
public Boolean isLogin() {
|
||||
return isLogin;
|
||||
}
|
||||
|
||||
public Boolean isOnline() {
|
||||
return isOnline;
|
||||
}
|
||||
|
||||
public Boolean isPrinter() {
|
||||
return isPrinter;
|
||||
}
|
||||
|
||||
public Boolean isWebServer() {
|
||||
return isWebServer;
|
||||
}
|
||||
|
||||
public Integer isWL() {
|
||||
return isWL;
|
||||
}
|
||||
|
||||
public Boolean isWiFiConnected() {
|
||||
return isWL > 0;
|
||||
}
|
||||
|
||||
public String getKeepArp() {
|
||||
return keeparp;
|
||||
}
|
||||
|
||||
public String getMac() {
|
||||
return mac;
|
||||
}
|
||||
|
||||
public Boolean getMacRepeat() {
|
||||
return macRepeat;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getNickName() {
|
||||
return nickName;
|
||||
}
|
||||
|
||||
public Integer getOpMode() {
|
||||
return opMode;
|
||||
}
|
||||
|
||||
public String getQosLevel() {
|
||||
return qosLevel;
|
||||
}
|
||||
|
||||
public Integer getROG() {
|
||||
return rog;
|
||||
}
|
||||
|
||||
public Integer getRSSI() {
|
||||
return rssi;
|
||||
}
|
||||
|
||||
public String getSSID() {
|
||||
return ssid;
|
||||
}
|
||||
|
||||
public String getVendor() {
|
||||
return vendor;
|
||||
}
|
||||
|
||||
public String getWlanConnectTime() {
|
||||
return wlConnectTime;
|
||||
}
|
||||
|
||||
public Integer getWtFast() {
|
||||
return wtfast;
|
||||
}
|
||||
}
|
@ -0,0 +1,177 @@
|
||||
/**
|
||||
* 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.structures;
|
||||
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingConstants.*;
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtErrorConstants.*;
|
||||
import static org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils.isValidMacAddress;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtClientList} class stores a list of {@link AsuswrtClientInfo}.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtClientList implements Iterable<AsuswrtClientInfo> {
|
||||
private final Logger logger = LoggerFactory.getLogger(AsuswrtClientList.class);
|
||||
private List<AsuswrtClientInfo> clientList = new ArrayList<>();
|
||||
|
||||
public AsuswrtClientList() {
|
||||
}
|
||||
|
||||
public AsuswrtClientList(JsonObject jsonObject) {
|
||||
setData(jsonObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<AsuswrtClientInfo> iterator() {
|
||||
return clientList.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AsuswrtClientList} using a {@link JsonObject}.
|
||||
*/
|
||||
public void setData(JsonObject jsonObject) {
|
||||
clientList.clear();
|
||||
try {
|
||||
JsonObject jsonList = jsonObject.getAsJsonObject(JSON_MEMBER_CLIENTS);
|
||||
// Remove the member MAC list, it contains only online clients
|
||||
jsonList.remove(JSON_MEMBER_MACLIST);
|
||||
jsonList.remove(JSON_MEMBER_API_LEVEL);
|
||||
// Iterate over the MAC addresses
|
||||
jsonList.keySet().forEach(macAddress -> {
|
||||
if (isValidMacAddress(macAddress)) {
|
||||
AsuswrtClientInfo clientInfo = new AsuswrtClientInfo(jsonList.getAsJsonObject(macAddress));
|
||||
addClient(clientInfo);
|
||||
} else {
|
||||
logger.trace("getClientlist: {} '{}'", ERR_INVALID_MAC_ADDRESS, macAddress);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
logger.debug("getClientlist: {} - {}'", ERR_JSON_FORMAT, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@link AsuswrtClientInfo} to the list.
|
||||
*/
|
||||
private void addClient(AsuswrtClientInfo clientInfo) {
|
||||
clientList.add(clientInfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets {@link AsuswrtClientInfo} from the list for a client based on its name.
|
||||
*
|
||||
* @param clientName the name of the client for which the info is returned
|
||||
*/
|
||||
public AsuswrtClientInfo getClientByName(String clientName) {
|
||||
for (AsuswrtClientInfo client : this.clientList) {
|
||||
if (client.getName().equals(clientName)) {
|
||||
return client;
|
||||
}
|
||||
}
|
||||
return new AsuswrtClientInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets {@link AsuswrtClientInfo} from the list for a client based on its MAC address.
|
||||
*
|
||||
* @param clientMAC the MAC address of the client for which the info is returned
|
||||
*/
|
||||
public AsuswrtClientInfo getClientByMAC(String clientMAC) {
|
||||
for (AsuswrtClientInfo client : this.clientList) {
|
||||
if (client.getMac().equals(clientMAC)) {
|
||||
return client;
|
||||
}
|
||||
}
|
||||
return new AsuswrtClientInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets {@link AsuswrtClientInfo} from the list for a client based on its IP address.
|
||||
*
|
||||
* @param clientIP the IP address of the client for which the info is returned
|
||||
*/
|
||||
public AsuswrtClientInfo getClientByIP(String clientIP) {
|
||||
for (AsuswrtClientInfo client : this.clientList) {
|
||||
if (client.getIP().equals(clientIP)) {
|
||||
return client;
|
||||
}
|
||||
}
|
||||
return new AsuswrtClientInfo();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a <code>;</code> separated list with client names and MAC addresses.
|
||||
*/
|
||||
public String getClientList() {
|
||||
StringBuilder clients = new StringBuilder();
|
||||
for (AsuswrtClientInfo client : this.clientList) {
|
||||
clients.append(client.getName() + " [" + client.getMac() + "]; ");
|
||||
}
|
||||
return clients.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a <code>;</code> separated list with client names.
|
||||
*/
|
||||
public String getClientNames() {
|
||||
return clientList.stream().map(AsuswrtClientInfo::getName).collect(Collectors.joining("; "));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of clients in the list.
|
||||
*/
|
||||
public Integer getCount() {
|
||||
return clientList.size();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a <code>;</code> separated list with MAC addresses.
|
||||
*/
|
||||
public String getMacAddresses() {
|
||||
StringBuilder clients = new StringBuilder();
|
||||
for (AsuswrtClientInfo client : this.clientList) {
|
||||
clients.append(client.getMac() + "; ");
|
||||
}
|
||||
return clients.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link AsuswrtClientList} of online clients.
|
||||
*/
|
||||
public AsuswrtClientList getOnlineClients() {
|
||||
AsuswrtClientList clients = new AsuswrtClientList();
|
||||
for (AsuswrtClientInfo client : this.clientList) {
|
||||
if (client.isOnline()) {
|
||||
clients.addClient(client);
|
||||
}
|
||||
}
|
||||
return clients;
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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.structures;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtConfiguration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtConfiguration {
|
||||
|
||||
// Thing configuration properties
|
||||
public static final String CONFIG_USER = "username";
|
||||
public static final String CONFIG_PASS = "password";
|
||||
public static final String CONFIG_HOSTNAME = "hostname";
|
||||
public static final String CONFIG_UPDATE_INTERVAL = "refreshInterval";
|
||||
public static final String CONFIG_SSL_AUTH = "useSSL";
|
||||
public static final String CONFIG_PORT_HTTP = "httpPort";
|
||||
public static final String CONFIG_PORT_HTTPS = "httpsPort";
|
||||
|
||||
// Thing configuration parameters
|
||||
public String hostname = "";
|
||||
public String username = "";
|
||||
public String password = "";
|
||||
public int pollingInterval = 20;
|
||||
public int reconnectInterval = 60;
|
||||
public int discoveryInterval = 3600;
|
||||
public int httpPort = 80;
|
||||
public int httpsPort = 443;
|
||||
public boolean autoDiscoveryEnabled = false;
|
||||
public boolean useSSL = false;
|
||||
}
|
@ -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.structures;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* This class is used for storing Asuswrt credentials.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtCredentials {
|
||||
private String username = "";
|
||||
private String password = "";
|
||||
private String encodedCredentials = "";
|
||||
|
||||
public AsuswrtCredentials() {
|
||||
}
|
||||
|
||||
public AsuswrtCredentials(AsuswrtConfiguration routerConfig) {
|
||||
setCredentials(routerConfig.username, routerConfig.password);
|
||||
}
|
||||
|
||||
public AsuswrtCredentials(String username, String password) {
|
||||
setCredentials(username, password);
|
||||
}
|
||||
|
||||
/*
|
||||
* Private methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* Stores the given credentials.
|
||||
*/
|
||||
private void setCredentials(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
encodedCredentials = b64encode(username + ":" + password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a String using Base64.
|
||||
*/
|
||||
private String b64encode(String string) {
|
||||
return Base64.getEncoder().encodeToString((string).getBytes());
|
||||
}
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns Base64 encoded credentials.
|
||||
*
|
||||
* @return 'username:password' as Base64 encoded string
|
||||
*/
|
||||
public String getEncodedCredentials() {
|
||||
return encodedCredentials;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
/**
|
||||
* 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.structures;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtInterfaceList} class stores a list of {@link AsuswrtIpInfo}.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtInterfaceList implements Iterable<AsuswrtIpInfo> {
|
||||
private List<AsuswrtIpInfo> ipInfoList = new ArrayList<>();
|
||||
|
||||
public AsuswrtInterfaceList() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<AsuswrtIpInfo> iterator() {
|
||||
return ipInfoList.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* Setters
|
||||
*/
|
||||
|
||||
/**
|
||||
* Adds an {@link AsuswrtIpInfo} to the list.
|
||||
*/
|
||||
private void addInterface(AsuswrtIpInfo ipInfo) {
|
||||
ipInfoList.add(ipInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AsuswrtInterfaceList} using a {@link JsonObject}.
|
||||
*/
|
||||
public void setData(String ifName, JsonObject jsonObject) {
|
||||
if (hasInterface(ifName)) {
|
||||
getByName(ifName).setData(jsonObject);
|
||||
} else {
|
||||
addInterface(new AsuswrtIpInfo(ifName, jsonObject));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets {@link AsuswrtIpInfo} from the list for an interface based on its name.
|
||||
*
|
||||
* @param ifName the name of the interface for which the info is returned
|
||||
*/
|
||||
public AsuswrtIpInfo getByName(String ifName) {
|
||||
for (AsuswrtIpInfo ipInfo : ipInfoList) {
|
||||
if (ipInfo.getName().equals(ifName)) {
|
||||
return ipInfo;
|
||||
}
|
||||
}
|
||||
return new AsuswrtIpInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets {@link AsuswrtIpInfo} from the list for an interface based on its MAC address.
|
||||
*
|
||||
* @param ipInfoMAC the MAC address of the interface for which the info is returned
|
||||
*/
|
||||
public AsuswrtIpInfo getByMAC(String ipInfoMAC) {
|
||||
for (AsuswrtIpInfo ipInfo : ipInfoList) {
|
||||
if (ipInfo.getMAC().equals(ipInfoMAC)) {
|
||||
return ipInfo;
|
||||
}
|
||||
}
|
||||
return new AsuswrtIpInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets {@link AsuswrtIpInfo} from the list for an interface based on its IP address.
|
||||
*
|
||||
* @param ipAddress the IP address of the interface for which the info is returned
|
||||
*/
|
||||
public AsuswrtIpInfo getByIP(String ipAddress) {
|
||||
for (AsuswrtIpInfo ipInfo : ipInfoList) {
|
||||
if (ipInfo.getIpAddress().equals(ipAddress)) {
|
||||
return ipInfo;
|
||||
}
|
||||
}
|
||||
return new AsuswrtIpInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an interface with the given name is in the list.
|
||||
*
|
||||
* @param ifName the name of the interface
|
||||
*/
|
||||
public boolean hasInterface(String ifName) {
|
||||
for (AsuswrtIpInfo ipInfo : ipInfoList) {
|
||||
if (ipInfo.getName().equals(ifName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
/**
|
||||
* 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.structures;
|
||||
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingConstants.*;
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingSettings.*;
|
||||
import static org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtIpInfo} class stores IP data.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtIpInfo {
|
||||
private final Logger logger = LoggerFactory.getLogger(AsuswrtIpInfo.class);
|
||||
private AsuswrtTraffic traffic = new AsuswrtTraffic();
|
||||
private String ifName = "";
|
||||
private String hwAddress = "";
|
||||
private String ipAddress = "";
|
||||
private String ipProto = "";
|
||||
private String subnet = "";
|
||||
private String gateway = "";
|
||||
private String dnsServer = "";
|
||||
private Boolean connected = false;
|
||||
|
||||
public AsuswrtIpInfo() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param interfaceName name of interface
|
||||
* @param jsonObject with ipInfo
|
||||
*/
|
||||
public AsuswrtIpInfo(String ifName, JsonObject jsonObject) {
|
||||
this.ifName = ifName;
|
||||
traffic = new AsuswrtTraffic(ifName);
|
||||
setData(jsonObject);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setters
|
||||
*/
|
||||
|
||||
public void setData(JsonObject jsonObject) {
|
||||
if (ifName.startsWith(INTERFACE_LAN)) {
|
||||
logger.trace("(AsuswrtIpInfo) setData for interface {}", INTERFACE_LAN);
|
||||
hwAddress = jsonObjectToString(jsonObject, JSON_MEMBER_MAC, hwAddress);
|
||||
ipAddress = jsonObjectToString(jsonObject, JSON_MEMBER_LAN_IP, ipAddress);
|
||||
subnet = jsonObjectToString(jsonObject, JSON_MEMBER_LAN_NETMASK, subnet);
|
||||
gateway = jsonObjectToString(jsonObject, JSON_MEMBER_LAN_GATEWAY, gateway);
|
||||
ipProto = jsonObjectToString(jsonObject, JSON_MEMBER_LAN_PROTO, ipProto);
|
||||
} else if (ifName.startsWith(INTERFACE_WAN)) {
|
||||
logger.trace("(AsuswrtIpInfo) setData for interface {}", INTERFACE_WAN);
|
||||
hwAddress = jsonObjectToString(jsonObject, JSON_MEMBER_MAC, hwAddress);
|
||||
ipAddress = jsonObjectToString(jsonObject, JSON_MEMBER_WAN_IP, ipAddress);
|
||||
subnet = jsonObjectToString(jsonObject, JSON_MEMBER_WAN_NETMASK, subnet);
|
||||
gateway = jsonObjectToString(jsonObject, JSON_MEMBER_WAN_GATEWAY, gateway);
|
||||
ipProto = jsonObjectToString(jsonObject, JSON_MEMBER_WAN_PROTO, ipProto);
|
||||
dnsServer = jsonObjectToString(jsonObject, JSON_MEMBER_WAN_DNS_SERVER, dnsServer);
|
||||
connected = (jsonObjectToInt(jsonObject, JSON_MEMBER_WAN_CONNECTED) == 1);
|
||||
}
|
||||
if (jsonObject.has(JSON_MEMBER_TRAFFIC)) {
|
||||
traffic.setData(jsonObject.getAsJsonObject(JSON_MEMBER_TRAFFIC));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters
|
||||
*/
|
||||
|
||||
public AsuswrtTraffic getTraffic() {
|
||||
return traffic;
|
||||
}
|
||||
|
||||
public String getMAC() {
|
||||
return hwAddress;
|
||||
}
|
||||
|
||||
public String getIpAddress() {
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
public String getSubnet() {
|
||||
return subnet;
|
||||
}
|
||||
|
||||
public String getGateway() {
|
||||
return gateway;
|
||||
}
|
||||
|
||||
public String getIpProto() {
|
||||
return ipProto;
|
||||
}
|
||||
|
||||
public String getDNSNServer() {
|
||||
return dnsServer;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return ifName;
|
||||
}
|
||||
|
||||
public Boolean isConnected() {
|
||||
return connected;
|
||||
}
|
||||
}
|
@ -0,0 +1,154 @@
|
||||
/**
|
||||
* 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.structures;
|
||||
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingConstants.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtRouterInfo} class stores the router data
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtRouterInfo {
|
||||
private final Logger logger = LoggerFactory.getLogger(AsuswrtRouterInfo.class);
|
||||
private String productId = "";
|
||||
private String fwVersion = "";
|
||||
private String fwBuild = "";
|
||||
private String macAddress = "";
|
||||
private Map<String, AsuswrtUsage> usageStats = new HashMap<>();
|
||||
|
||||
public AsuswrtRouterInfo() {
|
||||
}
|
||||
|
||||
public AsuswrtRouterInfo(JsonObject jsonObject) {
|
||||
setSysInfo(jsonObject);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setters
|
||||
*/
|
||||
|
||||
public void setAllData(JsonObject jsonObject) {
|
||||
setSysInfo(jsonObject);
|
||||
setUsageStats(jsonObject);
|
||||
}
|
||||
|
||||
public void setSysInfo(JsonObject jsonObject) {
|
||||
try {
|
||||
productId = jsonObject.get(JSON_MEMBER_PRODUCTID).toString();
|
||||
fwVersion = jsonObject.get(JSON_MEMBER_FIRMWARE).toString();
|
||||
fwBuild = jsonObject.get(JSON_MEMBER_BUILD).toString();
|
||||
macAddress = jsonObject.get(JSON_MEMBER_MAC).toString();
|
||||
} catch (Exception e) {
|
||||
logger.trace("incomplete SysInfo");
|
||||
}
|
||||
}
|
||||
|
||||
public void setUsageStats(JsonObject jsonObject) {
|
||||
JsonObject jsnMemUsage = jsonObject.getAsJsonObject(JSON_MEMBER_MEM_USAGE);
|
||||
JsonObject jsnCpuUsage = jsonObject.getAsJsonObject(JSON_MEMBER_CPU_USAGE);
|
||||
// Get memory usage
|
||||
if (jsnMemUsage != null) {
|
||||
usageStats.put(JSON_MEMBER_MEM_USAGE,
|
||||
new AsuswrtUsage(jsnMemUsage, JSON_MEMBER_MEM_TOTAL, JSON_MEMBER_MEM_USED));
|
||||
}
|
||||
// Loop cpu usages
|
||||
if (jsnCpuUsage != null) {
|
||||
for (Integer i = 1; i <= USAGE_CPU_COUNT; i++) {
|
||||
String member = JSON_MEMBER_CPU_USAGE + "_" + i;
|
||||
String total = JSON_MEMBER_CPU_TOTAL.replace("{x}", "" + i);
|
||||
String used = JSON_MEMBER_CPU_USED.replace("{x}", "" + i);
|
||||
if (jsnCpuUsage.has(total) && jsnCpuUsage.has(used)) {
|
||||
usageStats.put(member, new AsuswrtUsage(jsnCpuUsage, total, used));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters
|
||||
*/
|
||||
|
||||
public String getProductId() {
|
||||
return productId;
|
||||
}
|
||||
|
||||
public String getFirmwareVersion() {
|
||||
return fwVersion + " (" + fwBuild + ")";
|
||||
}
|
||||
|
||||
public String getMAC() {
|
||||
return macAddress;
|
||||
}
|
||||
|
||||
public AsuswrtUsage getMemUsage() {
|
||||
if (usageStats.containsKey(JSON_MEMBER_MEM_USAGE)) {
|
||||
AsuswrtUsage usage = usageStats.get(JSON_MEMBER_MEM_USAGE);
|
||||
if (usage != null) {
|
||||
return usage;
|
||||
}
|
||||
}
|
||||
return new AsuswrtUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CPU usage for a core.
|
||||
*
|
||||
* @param coreNum the core number
|
||||
* @return the {@link AsuswrtUsage} for the given core
|
||||
*/
|
||||
public AsuswrtUsage getCpuUsage(Integer coreNum) {
|
||||
String coreKey = JSON_MEMBER_CPU_USAGE + "_" + coreNum;
|
||||
if (usageStats.containsKey(coreKey)) {
|
||||
AsuswrtUsage usage = usageStats.get(coreKey);
|
||||
if (usage != null) {
|
||||
return usage;
|
||||
}
|
||||
}
|
||||
return new AsuswrtUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CPU usage average over all cores.
|
||||
*
|
||||
* @return the {@link AsuswrtUsage} with CPU usage average over all cores
|
||||
*/
|
||||
public AsuswrtUsage getCpuAverage() {
|
||||
String coreKey;
|
||||
AsuswrtUsage coreStatsX;
|
||||
Integer total = 0, used = 0, coreNum;
|
||||
for (coreNum = 1; coreNum <= USAGE_CPU_COUNT; coreNum++) {
|
||||
coreKey = JSON_MEMBER_CPU_USAGE + "_" + coreNum;
|
||||
coreStatsX = usageStats.get(coreKey);
|
||||
if (coreStatsX != null) {
|
||||
total += coreStatsX.getTotal();
|
||||
used += coreStatsX.getUsed();
|
||||
}
|
||||
}
|
||||
if (coreNum > 1) {
|
||||
total = total / coreNum - 1;
|
||||
used = used / coreNum - 1;
|
||||
}
|
||||
return new AsuswrtUsage(total, used);
|
||||
}
|
||||
}
|
@ -0,0 +1,191 @@
|
||||
/**
|
||||
* 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.structures;
|
||||
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingConstants.*;
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingSettings.*;
|
||||
import static org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtTraffic} class handles traffic statistics
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtTraffic {
|
||||
private final Logger logger = LoggerFactory.getLogger(AsuswrtTraffic.class);
|
||||
private Double curTX = 0.0;
|
||||
private Double curRX = 0.0;
|
||||
private Integer totalTX = 0;
|
||||
private Integer totalRX = 0;
|
||||
private Integer zeroHourTX = 0;
|
||||
private Integer zeroHourRX = 0;
|
||||
private LocalDate zeroHourDate = LocalDate.now();
|
||||
private Long lastUpdate = 0L;
|
||||
private String representationProperty = "";
|
||||
|
||||
public AsuswrtTraffic() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param representationProperty representationProperty of the device (i.e. interfaceName)
|
||||
*/
|
||||
public AsuswrtTraffic(String representationProperty) {
|
||||
this.representationProperty = representationProperty.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param jsonObject stores the data
|
||||
* @param representationProperty representationProperty of the device (i.e. interfaceName)
|
||||
*/
|
||||
public AsuswrtTraffic(JsonObject jsonObject, String representationProperty) {
|
||||
this.representationProperty = representationProperty;
|
||||
setData(jsonObject);
|
||||
}
|
||||
|
||||
public void setData(JsonObject jsonObject) {
|
||||
Integer intRX;
|
||||
Integer intTX;
|
||||
if (representationProperty.startsWith(INTERFACE_LAN)) {
|
||||
intRX = getTrafficFromHex(jsonObject, JSON_MEMBER_LAN_RX);
|
||||
intTX = getTrafficFromHex(jsonObject, JSON_MEMBER_LAN_TX);
|
||||
curRX = calculateCurrentTraffic(intRX, totalRX);
|
||||
curTX = calculateCurrentTraffic(intTX, totalTX);
|
||||
totalRX = getTrafficFromHex(jsonObject, JSON_MEMBER_LAN_RX);
|
||||
totalTX = getTrafficFromHex(jsonObject, JSON_MEMBER_LAN_TX);
|
||||
} else if (representationProperty.startsWith(INTERFACE_WAN)) {
|
||||
intRX = getTrafficFromHex(jsonObject, JSON_MEMBER_INET_RX);
|
||||
intTX = getTrafficFromHex(jsonObject, JSON_MEMBER_INET_TX);
|
||||
curRX = calculateCurrentTraffic(intRX, totalRX);
|
||||
curTX = calculateCurrentTraffic(intTX, totalTX);
|
||||
totalRX = getTrafficFromHex(jsonObject, JSON_MEMBER_INET_RX);
|
||||
totalTX = getTrafficFromHex(jsonObject, JSON_MEMBER_INET_TX);
|
||||
} else if (representationProperty.startsWith(INTERFACE_WLAN)) {
|
||||
for (int i = 0; i < 1; i++) {
|
||||
intRX = getTrafficFromHex(jsonObject, JSON_MEMBER_WLAN_RX.replace("{}", Integer.toString(i)));
|
||||
intTX = getTrafficFromHex(jsonObject, JSON_MEMBER_WLAN_TX.replace("{}", Integer.toString(i)));
|
||||
curRX = calculateCurrentTraffic(intRX, totalRX);
|
||||
curTX = calculateCurrentTraffic(intTX, totalTX);
|
||||
totalRX = getTrafficFromHex(jsonObject, JSON_MEMBER_INET_RX);
|
||||
totalTX = getTrafficFromHex(jsonObject, JSON_MEMBER_INET_TX);
|
||||
}
|
||||
} else if (INTERFACE_CLIENT.equals(representationProperty)) {
|
||||
curRX = Double.valueOf(jsonObjectToInt(jsonObject, JSON_MEMBER_CLIENT_RXCUR, -1));
|
||||
curTX = Double.valueOf(jsonObjectToInt(jsonObject, JSON_MEMBER_CLIENT_TXCUR, -1));
|
||||
totalRX = jsonObjectToInt(jsonObject, JSON_MEMBER_CLIENT_RXTOTAL, -1);
|
||||
totalTX = jsonObjectToInt(jsonObject, JSON_MEMBER_CLIENT_TXTOTAL, -1);
|
||||
} else {
|
||||
logger.trace("({}) can't set Trafficdata", representationProperty);
|
||||
}
|
||||
lastUpdate = System.currentTimeMillis();
|
||||
setZeroHourTraffic(totalRX, totalTX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the traffic values at the start of a new day.
|
||||
*/
|
||||
private void setZeroHourTraffic(Integer totalRX, Integer totalTX) {
|
||||
LocalDate today = LocalDate.now();
|
||||
if (today.isAfter(zeroHourDate) || zeroHourRX > totalRX) {
|
||||
zeroHourRX = totalRX;
|
||||
zeroHourTX = totalTX;
|
||||
zeroHourDate = today;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the traffic as {@link Integer} value from a hexadecimal value in a {@link JsonObject}.
|
||||
*
|
||||
* @param jsonObject the object containing the values
|
||||
* @param jsonMember the name of the key that stores the value
|
||||
* @return the traffic value
|
||||
*/
|
||||
private Integer getTrafficFromHex(JsonObject jsonObject, String jsonMember) {
|
||||
Long lngVal;
|
||||
if (jsonObject.has(jsonMember)) {
|
||||
String hex = jsonObjectToString(jsonObject, jsonMember);
|
||||
try {
|
||||
lngVal = Long.decode(hex);
|
||||
lngVal = lngVal * 8 / 1024 / 1024 / 2;
|
||||
return lngVal.intValue();
|
||||
} catch (Exception e) {
|
||||
logger.debug("({}) error calculating traffic from hex '{}'", representationProperty, hex);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the traffic from the actual and old total traffic using the time span.
|
||||
*
|
||||
* @param actVal the actual value
|
||||
* @param oldVal the old value
|
||||
* @return the current traffic value
|
||||
*/
|
||||
private Double calculateCurrentTraffic(Integer actVal, Integer oldVal) {
|
||||
if (lastUpdate > 0) {
|
||||
Long timeSpan = (System.currentTimeMillis() - lastUpdate) / 1000;
|
||||
Integer div = 0;
|
||||
try {
|
||||
if (actVal >= 0) {
|
||||
div = actVal - oldVal;
|
||||
return Double.valueOf(div / timeSpan.intValue());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.debug("({}) error calculating traffic from timeSpan '{}/{}'", representationProperty, div,
|
||||
timeSpan);
|
||||
}
|
||||
}
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters
|
||||
*/
|
||||
|
||||
public Double getCurrentRX() {
|
||||
return curRX;
|
||||
}
|
||||
|
||||
public Double getCurrentTX() {
|
||||
return curTX;
|
||||
}
|
||||
|
||||
public Integer getTotalRX() {
|
||||
return totalRX;
|
||||
}
|
||||
|
||||
public Integer getTotalTX() {
|
||||
return totalTX;
|
||||
}
|
||||
|
||||
public Integer getTodayRX() {
|
||||
return totalRX - zeroHourRX;
|
||||
}
|
||||
|
||||
public Integer getTodayTX() {
|
||||
return totalTX - zeroHourTX;
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/**
|
||||
* 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.structures;
|
||||
|
||||
import static org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils.jsonObjectToInt;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtUsage} class handles usage statistics
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtUsage {
|
||||
private Integer free = 0;
|
||||
private Integer used = 0;
|
||||
private Integer total = 0;
|
||||
|
||||
public AsuswrtUsage() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param jsonObject jsonObject data is stored
|
||||
* @param totalKey name of key total available is stored
|
||||
* @param usedKey name of key used is stored
|
||||
*/
|
||||
public AsuswrtUsage(JsonObject jsonObject, String totalKey, String usedKey) {
|
||||
setData(jsonObject, totalKey, usedKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param totalUsage the total usage
|
||||
* @param used the usage
|
||||
*/
|
||||
public AsuswrtUsage(Integer totalUsage, Integer used) {
|
||||
setData(totalUsage, used);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setters
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets the usage data from a JSON object.
|
||||
*
|
||||
* @param jsonObject the JSON object containing the data
|
||||
* @param totalKey the key name with the 'total available' value
|
||||
* @param usedKey the key name with the 'used' value
|
||||
*/
|
||||
public void setData(JsonObject jsonObject, String totalKey, String usedKey) {
|
||||
total = jsonObjectToInt(jsonObject, totalKey, 0);
|
||||
used = jsonObjectToInt(jsonObject, usedKey, 0);
|
||||
free = total - used;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets usage data from integer values.
|
||||
*
|
||||
* @param totalUsage the total available value
|
||||
* @param used the used value
|
||||
*/
|
||||
public void setData(Integer totalUsage, Integer used) {
|
||||
total = totalUsage;
|
||||
this.used = used;
|
||||
free = total - used;
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters
|
||||
*/
|
||||
|
||||
public Integer getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public Integer getUsed() {
|
||||
return used;
|
||||
}
|
||||
|
||||
public Integer getFree() {
|
||||
return free;
|
||||
}
|
||||
|
||||
public Integer getUsedPercent() {
|
||||
if (total > 0) {
|
||||
return ((used * 100) / total);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Integer getFreePercent() {
|
||||
if (total > 0) {
|
||||
return ((free * 100) / total);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,196 @@
|
||||
/**
|
||||
* 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.things;
|
||||
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingConstants.*;
|
||||
import static org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils;
|
||||
import org.openhab.binding.asuswrt.internal.structures.AsuswrtClientInfo;
|
||||
import org.openhab.binding.asuswrt.internal.structures.AsuswrtTraffic;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtClient} is used as {@link org.openhab.core.thing.binding.ThingHandler ThingHandler} for router
|
||||
* clients.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtClient extends BaseThingHandler {
|
||||
private final Logger logger = LoggerFactory.getLogger(AsuswrtClient.class);
|
||||
private final AsuswrtRouter router;
|
||||
private Map<String, Object> oldStates = new HashMap<>();
|
||||
protected final String uid;
|
||||
|
||||
public AsuswrtClient(Thing thing, AsuswrtRouter router) {
|
||||
super(thing);
|
||||
this.router = router;
|
||||
this.uid = getThing().getUID().getAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.trace("({}) Initializing thing ", uid);
|
||||
router.queryDeviceData(false);
|
||||
refreshData();
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Commands and events
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
refreshData();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateClientProperties(AsuswrtClientInfo clientInfo) {
|
||||
logger.trace("({}) clientPropertiesChanged ", uid);
|
||||
Map<String, String> properties = editProperties();
|
||||
properties.put(Thing.PROPERTY_MAC_ADDRESS, clientInfo.getMac());
|
||||
properties.put(Thing.PROPERTY_VENDOR, clientInfo.getVendor());
|
||||
properties.put(PROPERTY_CLIENT_NAME, clientInfo.getName());
|
||||
updateProperties(properties);
|
||||
}
|
||||
|
||||
public void updateClientChannels(AsuswrtClientInfo clientInfo) {
|
||||
updateState(getChannelID(CHANNEL_GROUP_NETWORK, CHANNEL_NETWORK_STATE), getOnOffType(clientInfo.isOnline()));
|
||||
updateState(getChannelID(CHANNEL_GROUP_NETWORK, CHANNEL_NETWORK_INTERNET),
|
||||
getOnOffType(clientInfo.getInternetState()));
|
||||
updateState(getChannelID(CHANNEL_GROUP_NETWORK, CHANNEL_NETWORK_IP), getStringType(clientInfo.getIP()));
|
||||
updateState(getChannelID(CHANNEL_GROUP_NETWORK, CHANNEL_NETWORK_METHOD),
|
||||
getStringType(clientInfo.getIpMethod()));
|
||||
}
|
||||
|
||||
private void updateTrafficChannels(AsuswrtTraffic traffic) {
|
||||
updateState(getChannelID(CHANNEL_GROUP_TRAFFIC, CHANNEL_TRAFFIC_CURRENT_RX),
|
||||
getQuantityType(traffic.getCurrentRX(), Units.MEGABIT_PER_SECOND));
|
||||
updateState(getChannelID(CHANNEL_GROUP_TRAFFIC, CHANNEL_TRAFFIC_CURRENT_TX),
|
||||
getQuantityType(traffic.getCurrentTX(), Units.MEGABIT_PER_SECOND));
|
||||
updateState(getChannelID(CHANNEL_GROUP_TRAFFIC, CHANNEL_TRAFFIC_TODAY_RX),
|
||||
getQuantityType(traffic.getTodayRX(), Units.MEGABYTE));
|
||||
updateState(getChannelID(CHANNEL_GROUP_TRAFFIC, CHANNEL_TRAFFIC_TODAY_TX),
|
||||
getQuantityType(traffic.getTodayTX(), Units.MEGABYTE));
|
||||
updateState(getChannelID(CHANNEL_GROUP_TRAFFIC, CHANNEL_TRAFFIC_TOTAL_RX),
|
||||
getQuantityType(traffic.getTotalRX(), Units.MEGABYTE));
|
||||
updateState(getChannelID(CHANNEL_GROUP_TRAFFIC, CHANNEL_TRAFFIC_TOTAL_TX),
|
||||
getQuantityType(traffic.getTotalTX(), Units.MEGABYTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires events on {@link AsuswrtClientInfo} changes.
|
||||
*/
|
||||
private void fireEvents(AsuswrtClientInfo clientInfo) {
|
||||
if (checkForStateChange(CHANNEL_GROUP_NETWORK, clientInfo.isOnline())) {
|
||||
if (clientInfo.isOnline()) {
|
||||
triggerChannel(getChannelID(CHANNEL_GROUP_NETWORK, EVENT_CLIENT_CONNECTION), EVENT_STATE_CONNECTED);
|
||||
router.fireEvent(getChannelID(CHANNEL_GROUP_CLIENTS, EVENT_CLIENT_CONNECTION), EVENT_STATE_CONNECTED);
|
||||
} else {
|
||||
triggerChannel(getChannelID(CHANNEL_GROUP_NETWORK, EVENT_CLIENT_CONNECTION), EVENT_STATE_GONE);
|
||||
router.fireEvent(getChannelID(CHANNEL_GROUP_CLIENTS, EVENT_CLIENT_CONNECTION), EVENT_STATE_GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshData() {
|
||||
String mac = getMac();
|
||||
AsuswrtClientInfo clientInfo = router.getClients().getClientByMAC(mac);
|
||||
fireEvents(clientInfo);
|
||||
updateClientProperties(clientInfo);
|
||||
updateClientChannels(clientInfo);
|
||||
updateTrafficChannels(clientInfo.getTraffic());
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets the MAC address of a client from properties or settings.
|
||||
*/
|
||||
public String getMac() {
|
||||
String mac = "";
|
||||
Map<String, String> properties = getThing().getProperties();
|
||||
Configuration config = getThing().getConfiguration();
|
||||
|
||||
/* get mac from properties */
|
||||
if (properties.containsKey(Thing.PROPERTY_MAC_ADDRESS)) {
|
||||
mac = config.get(Thing.PROPERTY_MAC_ADDRESS).toString();
|
||||
}
|
||||
|
||||
/* get mac from config */
|
||||
if (mac.isBlank() && config.containsKey(Thing.PROPERTY_MAC_ADDRESS)) {
|
||||
mac = config.get(Thing.PROPERTY_MAC_ADDRESS).toString();
|
||||
}
|
||||
|
||||
if (mac.isBlank()) {
|
||||
logger.debug("({}) cant find macAddress in properties and config", uid);
|
||||
}
|
||||
return AsuswrtUtils.formatMac(mac, ':');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the channel ID including the group.
|
||||
*/
|
||||
protected String getChannelID(String group, String channel) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
if (CHANNEL_GROUP_THING_SET.contains(thingTypeUID) && group.length() > 0) {
|
||||
return group + "#" + channel;
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a channel name from a channel ID.
|
||||
*/
|
||||
protected String getChannelFromID(ChannelUID channelID) {
|
||||
String channel = channelID.getIdWithoutGroup();
|
||||
channel = channel.replace(CHANNEL_GROUP_CLIENT + "#", "");
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the state changed since the last channel update.
|
||||
*
|
||||
* @param stateName the name of the state (channel)
|
||||
* @param comparator comparison value
|
||||
* @return <code>true</code> if changed, <code>false</code> if not or no old value exists
|
||||
*/
|
||||
private Boolean checkForStateChange(String stateName, Object comparator) {
|
||||
if (oldStates.get(stateName) == null) {
|
||||
oldStates.put(stateName, comparator);
|
||||
} else if (!comparator.equals(oldStates.get(stateName))) {
|
||||
oldStates.put(stateName, comparator);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,177 @@
|
||||
/**
|
||||
* 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.things;
|
||||
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingConstants.*;
|
||||
import static org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.asuswrt.internal.structures.AsuswrtIpInfo;
|
||||
import org.openhab.binding.asuswrt.internal.structures.AsuswrtTraffic;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtInterface} is used as {@link org.openhab.core.thing.binding.ThingHandler ThingHandler} for router
|
||||
* interfaces.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtInterface extends BaseThingHandler {
|
||||
private final Logger logger = LoggerFactory.getLogger(AsuswrtInterface.class);
|
||||
private final AsuswrtRouter router;
|
||||
private String ifName = "";
|
||||
private Map<String, Object> oldStates = new HashMap<>();
|
||||
protected final String uid;
|
||||
|
||||
public AsuswrtInterface(Thing thing, AsuswrtRouter router) {
|
||||
super(thing);
|
||||
this.router = router;
|
||||
this.uid = getThing().getUID().getAsString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.trace("({}) Initializing thing ", uid);
|
||||
Configuration config = getThing().getConfiguration();
|
||||
if (config.containsKey(PROPERTY_INTERFACE_NAME)) {
|
||||
this.ifName = config.get(PROPERTY_INTERFACE_NAME).toString();
|
||||
updateProperty(NETWORK_REPRESENTATION_PROPERTY, ifName);
|
||||
updateChannels();
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
logger.debug("({}) configurtation error", uid);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Commands and events
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
updateChannels();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateChannels() {
|
||||
try {
|
||||
AsuswrtIpInfo interfaceInfo = router.getInterfaces().getByName(ifName);
|
||||
fireEvents(interfaceInfo);
|
||||
updateInterfaceChannels(interfaceInfo);
|
||||
updateTrafficChannels(interfaceInfo.getTraffic());
|
||||
} catch (Exception e) {
|
||||
logger.debug("({}) unable to refresh data - property interfaceName not found ", uid);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateInterfaceChannels(AsuswrtIpInfo interfaceInfo) {
|
||||
updateState(getChannelID(CHANNEL_GROUP_NETWORK, CHANNEL_NETWORK_MAC), getStringType(interfaceInfo.getMAC()));
|
||||
updateState(getChannelID(CHANNEL_GROUP_NETWORK, CHANNEL_NETWORK_IP),
|
||||
getStringType(interfaceInfo.getIpAddress()));
|
||||
updateState(getChannelID(CHANNEL_GROUP_NETWORK, CHANNEL_NETWORK_MASK),
|
||||
getStringType(interfaceInfo.getSubnet()));
|
||||
updateState(getChannelID(CHANNEL_GROUP_NETWORK, CHANNEL_NETWORK_GATEWAY),
|
||||
getStringType(interfaceInfo.getGateway()));
|
||||
updateState(getChannelID(CHANNEL_GROUP_NETWORK, CHANNEL_NETWORK_METHOD),
|
||||
getStringType(interfaceInfo.getIpProto()));
|
||||
updateState(getChannelID(CHANNEL_GROUP_NETWORK, CHANNEL_NETWORK_DNS),
|
||||
getStringType(interfaceInfo.getDNSNServer()));
|
||||
updateState(getChannelID(CHANNEL_GROUP_NETWORK, CHANNEL_NETWORK_STATE),
|
||||
getOnOffType(interfaceInfo.isConnected()));
|
||||
}
|
||||
|
||||
private void updateTrafficChannels(AsuswrtTraffic traffic) {
|
||||
updateState(getChannelID(CHANNEL_GROUP_TRAFFIC, CHANNEL_TRAFFIC_CURRENT_RX),
|
||||
getQuantityType(traffic.getCurrentRX(), Units.MEGABIT_PER_SECOND));
|
||||
updateState(getChannelID(CHANNEL_GROUP_TRAFFIC, CHANNEL_TRAFFIC_CURRENT_TX),
|
||||
getQuantityType(traffic.getCurrentTX(), Units.MEGABIT_PER_SECOND));
|
||||
updateState(getChannelID(CHANNEL_GROUP_TRAFFIC, CHANNEL_TRAFFIC_TODAY_RX),
|
||||
getQuantityType(traffic.getTodayRX(), Units.MEGABYTE));
|
||||
updateState(getChannelID(CHANNEL_GROUP_TRAFFIC, CHANNEL_TRAFFIC_TODAY_TX),
|
||||
getQuantityType(traffic.getTodayTX(), Units.MEGABYTE));
|
||||
updateState(getChannelID(CHANNEL_GROUP_TRAFFIC, CHANNEL_TRAFFIC_TOTAL_RX),
|
||||
getQuantityType(traffic.getTotalRX(), Units.MEGABYTE));
|
||||
updateState(getChannelID(CHANNEL_GROUP_TRAFFIC, CHANNEL_TRAFFIC_TOTAL_TX),
|
||||
getQuantityType(traffic.getTotalTX(), Units.MEGABYTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires events on {@link AsuswrtIpInfo} changes.
|
||||
*/
|
||||
public void fireEvents(AsuswrtIpInfo interfaceInfo) {
|
||||
Boolean isConnected = interfaceInfo.isConnected();
|
||||
if (checkForStateChange(CHANNEL_NETWORK_STATE, isConnected)) {
|
||||
if (isConnected) {
|
||||
triggerChannel(getChannelID(CHANNEL_GROUP_NETWORK, EVENT_CONNECTION), EVENT_STATE_CONNECTED);
|
||||
} else {
|
||||
triggerChannel(getChannelID(CHANNEL_GROUP_NETWORK, EVENT_CONNECTION), EVENT_STATE_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets the channel ID including the group.
|
||||
*/
|
||||
protected String getChannelID(String group, String channel) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
if (CHANNEL_GROUP_THING_SET.contains(thingTypeUID) && group.length() > 0) {
|
||||
return group + "#" + channel;
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a channel name from a channel ID.
|
||||
*/
|
||||
protected String getChannelFromID(ChannelUID channelID) {
|
||||
String channel = channelID.getIdWithoutGroup();
|
||||
channel = channel.replace(CHANNEL_GROUP_NETWORK + "#", "");
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the state changed since the last channel update.
|
||||
*
|
||||
* @param stateName the name of the state (channel)
|
||||
* @param comparator comparison value
|
||||
* @return <code>true</code> if changed, <code>false</code> if not or no old value exists
|
||||
*/
|
||||
private Boolean checkForStateChange(String stateName, Object comparator) {
|
||||
if (oldStates.get(stateName) == null) {
|
||||
oldStates.put(stateName, comparator);
|
||||
} else if (!comparator.equals(oldStates.get(stateName))) {
|
||||
oldStates.put(stateName, comparator);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,531 @@
|
||||
/**
|
||||
* 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.things;
|
||||
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingConstants.*;
|
||||
import static org.openhab.binding.asuswrt.internal.constants.AsuswrtBindingSettings.*;
|
||||
import static org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.asuswrt.internal.AsuswrtDiscoveryService;
|
||||
import org.openhab.binding.asuswrt.internal.api.AsuswrtConnector;
|
||||
import org.openhab.binding.asuswrt.internal.helpers.AsuswrtErrorHandler;
|
||||
import org.openhab.binding.asuswrt.internal.helpers.AsuswrtUtils;
|
||||
import org.openhab.binding.asuswrt.internal.structures.AsuswrtClientList;
|
||||
import org.openhab.binding.asuswrt.internal.structures.AsuswrtConfiguration;
|
||||
import org.openhab.binding.asuswrt.internal.structures.AsuswrtInterfaceList;
|
||||
import org.openhab.binding.asuswrt.internal.structures.AsuswrtRouterInfo;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link AsuswrtRouter} is responsible for handling commands, which are sent to one of the channels.
|
||||
*
|
||||
* @author Christian Wild - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class AsuswrtRouter extends BaseBridgeHandler {
|
||||
private final Logger logger = LoggerFactory.getLogger(AsuswrtRouter.class);
|
||||
|
||||
private @Nullable ScheduledFuture<?> startupJob;
|
||||
private @Nullable ScheduledFuture<?> pollingJob;
|
||||
private @Nullable ScheduledFuture<?> reconnectJob;
|
||||
private @Nullable ScheduledFuture<?> discoveryJob;
|
||||
private @NonNullByDefault({}) AsuswrtDiscoveryService discoveryService;
|
||||
private @Nullable AsuswrtConnector connector;
|
||||
private AsuswrtConfiguration config;
|
||||
private AsuswrtRouterInfo deviceInfo;
|
||||
private AsuswrtInterfaceList interfaceList = new AsuswrtInterfaceList();
|
||||
private AsuswrtClientList clientList = new AsuswrtClientList();
|
||||
private final HttpClient httpClient;
|
||||
private final String uid;
|
||||
|
||||
public AsuswrtErrorHandler errorHandler;
|
||||
|
||||
public AsuswrtRouter(Bridge bridge, HttpClient httpClient) {
|
||||
super(bridge);
|
||||
Thing thing = getThing();
|
||||
uid = thing.getUID().toString();
|
||||
errorHandler = new AsuswrtErrorHandler();
|
||||
this.httpClient = httpClient;
|
||||
deviceInfo = new AsuswrtRouterInfo();
|
||||
config = new AsuswrtConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
config = getConfigAs(AsuswrtConfiguration.class);
|
||||
connector = new AsuswrtConnector(this);
|
||||
|
||||
// Initialize the handler.
|
||||
setState(ThingStatus.UNKNOWN);
|
||||
|
||||
// background initialization (delay it a little bit):
|
||||
startupJob = scheduler.schedule(this::delayedStartUp, 1000, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
stopScheduler(startupJob);
|
||||
stopScheduler(pollingJob);
|
||||
stopScheduler(discoveryJob);
|
||||
stopScheduler(reconnectJob);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return List.of(AsuswrtDiscoveryService.class);
|
||||
}
|
||||
|
||||
public void setDiscoveryService(AsuswrtDiscoveryService discoveryService) {
|
||||
this.discoveryService = discoveryService;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scheduler
|
||||
*/
|
||||
|
||||
/**
|
||||
* Delayed one-time startup job.
|
||||
*/
|
||||
private void delayedStartUp() {
|
||||
connect();
|
||||
}
|
||||
|
||||
public void startPollingJob() {
|
||||
int pollingInterval = AsuswrtUtils.getValueOrDefault(config.pollingInterval, POLLING_INTERVAL_S_DEFAULT);
|
||||
TimeUnit timeUnit = TimeUnit.SECONDS;
|
||||
if (pollingInterval > 0) {
|
||||
if (pollingInterval < POLLING_INTERVAL_S_MIN) {
|
||||
pollingInterval = POLLING_INTERVAL_S_MIN;
|
||||
}
|
||||
logger.trace("({}) start polling scheduler with interval {} {}", getUID(), pollingInterval, timeUnit);
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(this::pollingJobAction, pollingInterval, pollingInterval,
|
||||
timeUnit);
|
||||
} else {
|
||||
stopScheduler(pollingJob);
|
||||
}
|
||||
}
|
||||
|
||||
protected void pollingJobAction() {
|
||||
if (ThingStatus.ONLINE.equals(getState())) {
|
||||
queryDeviceData();
|
||||
}
|
||||
}
|
||||
|
||||
protected void startReconnectScheduler() {
|
||||
int pollingInterval = config.reconnectInterval;
|
||||
TimeUnit timeUnit = TimeUnit.SECONDS;
|
||||
if (pollingInterval < RECONNECT_INTERVAL_S) {
|
||||
pollingInterval = RECONNECT_INTERVAL_S;
|
||||
}
|
||||
logger.trace("({}) start reconnect scheduler in {} {}", getUID(), pollingInterval, timeUnit);
|
||||
reconnectJob = scheduler.schedule(this::reconnectJobAction, pollingInterval, timeUnit);
|
||||
}
|
||||
|
||||
protected void reconnectJobAction() {
|
||||
connect();
|
||||
}
|
||||
|
||||
protected void startDiscoveryScheduler() {
|
||||
int pollingInterval = config.discoveryInterval;
|
||||
TimeUnit timeUnit = TimeUnit.SECONDS;
|
||||
if (config.autoDiscoveryEnabled && pollingInterval > 0) {
|
||||
logger.trace("{} starting bridge discovery sheduler with interval {} {}", getUID(), pollingInterval,
|
||||
timeUnit);
|
||||
discoveryJob = scheduler.scheduleWithFixedDelay(discoveryService::startScan, 0, pollingInterval, timeUnit);
|
||||
} else {
|
||||
stopScheduler(discoveryJob);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops a scheduler.
|
||||
*
|
||||
* @param scheduler ScheduledFeature<?> which should be stopped
|
||||
*/
|
||||
protected void stopScheduler(@Nullable ScheduledFuture<?> scheduler) {
|
||||
if (scheduler != null) {
|
||||
logger.trace("{} stopping scheduler {}", uid, scheduler);
|
||||
scheduler.cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Connects to the router and sets the states.
|
||||
*/
|
||||
@SuppressWarnings("null")
|
||||
protected void connect() {
|
||||
connector.login();
|
||||
if (connector.cookieStore.cookieIsSet()) {
|
||||
stopScheduler(reconnectJob);
|
||||
queryDeviceData(false);
|
||||
devicePropertiesChanged(deviceInfo);
|
||||
setState(ThingStatus.ONLINE);
|
||||
startPollingJob();
|
||||
} else {
|
||||
setState(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, errorHandler.getErrorMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
public void queryDeviceData(Boolean asyncRequest) {
|
||||
connector.queryDeviceData(CMD_GET_SYSINFO + CMD_GET_USAGE + CMD_GET_LANINFO + CMD_GET_WANINFO
|
||||
+ CMD_GET_CLIENTLIST + CMD_GET_TRAFFIC, asyncRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries device data asynchronously.
|
||||
*/
|
||||
public void queryDeviceData() {
|
||||
queryDeviceData(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets routerInfo data and updates channels on receiving new data with the associated command.
|
||||
*
|
||||
* @param jsonObject contains the received data
|
||||
* @param command the command that was sent
|
||||
*/
|
||||
public void dataReceived(JsonObject jsonObject, String command) {
|
||||
if (command.contains(CMD_GET_SYSINFO)) {
|
||||
deviceInfo.setSysInfo(jsonObject);
|
||||
devicePropertiesChanged(deviceInfo);
|
||||
}
|
||||
if (command.contains(CMD_GET_CLIENTLIST)) {
|
||||
clientList.setData(jsonObject);
|
||||
updateClients();
|
||||
}
|
||||
if (command.contains(CMD_GET_LANINFO)) {
|
||||
interfaceList.setData(INTERFACE_LAN, jsonObject);
|
||||
updateChild(THING_TYPE_INTERFACE, NETWORK_REPRESENTATION_PROPERTY, INTERFACE_LAN);
|
||||
}
|
||||
if (command.contains(CMD_GET_WANINFO)) {
|
||||
interfaceList.setData(INTERFACE_WAN, jsonObject);
|
||||
updateChild(THING_TYPE_INTERFACE, NETWORK_REPRESENTATION_PROPERTY, INTERFACE_WAN);
|
||||
}
|
||||
if (command.contains(CMD_GET_USAGE) || command.contains(CMD_GET_MEMUSAGE)
|
||||
|| command.contains(CMD_GET_CPUUSAGE)) {
|
||||
deviceInfo.setUsageStats(jsonObject);
|
||||
}
|
||||
updateChannels(deviceInfo, clientList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the router status.
|
||||
*/
|
||||
public void setState(ThingStatus thingStatus, ThingStatusDetail statusDetail, String text) {
|
||||
if (!thingStatus.equals(getThing().getStatus())) {
|
||||
updateStatus(thingStatus, statusDetail, text);
|
||||
updateChildStates(thingStatus);
|
||||
if (ThingStatus.OFFLINE.equals(thingStatus)) {
|
||||
stopScheduler(pollingJob);
|
||||
// Set channels to undef
|
||||
getThing().getChannels().forEach(c -> updateState(c.getUID(), UnDefType.UNDEF));
|
||||
startReconnectScheduler();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upate RouterStatus
|
||||
*/
|
||||
public void setState(ThingStatus thingStatus) {
|
||||
setState(thingStatus, ThingStatusDetail.NONE, "");
|
||||
}
|
||||
|
||||
/***********************************
|
||||
*
|
||||
* PUBLIC GETs
|
||||
*
|
||||
************************************/
|
||||
|
||||
public HttpClient getHttpClient() {
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
public AsuswrtConfiguration getConfiguration() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public AsuswrtErrorHandler getErrorHandler() {
|
||||
return errorHandler;
|
||||
}
|
||||
|
||||
public ThingUID getUID() {
|
||||
return thing.getUID();
|
||||
}
|
||||
|
||||
public AsuswrtRouterInfo getDeviceInfo() {
|
||||
return deviceInfo;
|
||||
}
|
||||
|
||||
public AsuswrtClientList getClients() {
|
||||
return clientList;
|
||||
}
|
||||
|
||||
public AsuswrtInterfaceList getInterfaces() {
|
||||
return interfaceList;
|
||||
}
|
||||
|
||||
public ThingStatus getState() {
|
||||
return getThing().getStatus();
|
||||
}
|
||||
|
||||
/***********************************
|
||||
*
|
||||
* COMMAND HANDLER
|
||||
*
|
||||
************************************/
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
queryDeviceData();
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************
|
||||
*
|
||||
* PROPERTIES
|
||||
*
|
||||
************************************/
|
||||
|
||||
/**
|
||||
* UPDATE PROPERTIES
|
||||
*
|
||||
* If only one property must be changed, there is also a convenient method
|
||||
* updateProperty(String name, String value).
|
||||
*/
|
||||
public void devicePropertiesChanged(AsuswrtRouterInfo deviceInfo) {
|
||||
/* device properties */
|
||||
Map<String, String> properties = editProperties();
|
||||
properties.put(Thing.PROPERTY_MAC_ADDRESS, interfaceList.getByName(INTERFACE_WAN).getMAC());
|
||||
properties.put(Thing.PROPERTY_MODEL_ID, deviceInfo.getProductId());
|
||||
properties.put(Thing.PROPERTY_FIRMWARE_VERSION, deviceInfo.getFirmwareVersion());
|
||||
updateProperties(properties);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
*
|
||||
* CHANNELS
|
||||
*
|
||||
************************************/
|
||||
|
||||
/**
|
||||
* Update all Channels
|
||||
*/
|
||||
public void updateChannels(AsuswrtRouterInfo deviceInfo, AsuswrtClientList clientList) {
|
||||
updateClientChannels(clientList);
|
||||
updateUsageChannels(deviceInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Channel Usage
|
||||
*/
|
||||
public void updateUsageChannels(AsuswrtRouterInfo deviceInfo) {
|
||||
updateState(getChannelID(CHANNEL_GROUP_SYSINFO, CHANNEL_MEM_TOTAL),
|
||||
getQuantityType(deviceInfo.getMemUsage().getTotal(), Units.MEGABYTE));
|
||||
updateState(getChannelID(CHANNEL_GROUP_SYSINFO, CHANNEL_MEM_FREE),
|
||||
getQuantityType(deviceInfo.getMemUsage().getFree(), Units.MEGABYTE));
|
||||
updateState(getChannelID(CHANNEL_GROUP_SYSINFO, CHANNEL_MEM_USED),
|
||||
getQuantityType(deviceInfo.getMemUsage().getUsed(), Units.MEGABYTE));
|
||||
updateState(getChannelID(CHANNEL_GROUP_SYSINFO, CHANNEL_MEM_FREE_PERCENT),
|
||||
getQuantityType(deviceInfo.getMemUsage().getFreePercent(), Units.PERCENT));
|
||||
updateState(getChannelID(CHANNEL_GROUP_SYSINFO, CHANNEL_MEM_USED_PERCENT),
|
||||
getQuantityType(deviceInfo.getMemUsage().getUsedPercent(), Units.PERCENT));
|
||||
updateState(getChannelID(CHANNEL_GROUP_SYSINFO, CHANNEL_CPU_USED_PERCENT),
|
||||
getQuantityType(deviceInfo.getCpuAverage().getUsedPercent(), Units.PERCENT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Client Channel
|
||||
*/
|
||||
public void updateClientChannels(AsuswrtClientList clientList) {
|
||||
updateState(getChannelID(CHANNEL_GROUP_CLIENTS, CHANNEL_CLIENTS_KNOWN),
|
||||
getStringType(clientList.getClientList()));
|
||||
updateState(getChannelID(CHANNEL_GROUP_CLIENTS, CHANNEL_CLIENTS_ONLINE),
|
||||
getStringType(clientList.getOnlineClients().getClientList()));
|
||||
updateState(getChannelID(CHANNEL_GROUP_CLIENTS, CHANNEL_CLIENTS_COUNT),
|
||||
getDecimalType(clientList.getOnlineClients().getCount()));
|
||||
updateState(getChannelID(CHANNEL_GROUP_CLIENTS, CHANNEL_CLIENTS_ONLINE_MAC),
|
||||
getStringType(clientList.getOnlineClients().getMacAddresses()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire Event
|
||||
*
|
||||
* @param channelUID chanelUID event belongs to
|
||||
* @param event event-name is fired
|
||||
*/
|
||||
protected void fireEvent(String channel, String event) {
|
||||
triggerChannel(channel, event);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
*
|
||||
* CHILD THINGS
|
||||
*
|
||||
************************************/
|
||||
/**
|
||||
* Update all Child-Things with type Client
|
||||
*/
|
||||
public void updateClients() {
|
||||
updateChildThings(THING_TYPE_CLIENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all Child-Things with type Interface
|
||||
*/
|
||||
public void updateInterfaces() {
|
||||
updateChildThings(THING_TYPE_INTERFACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all Child-Things belonging to ThingTypeUID
|
||||
*/
|
||||
public void updateChildThings(ThingTypeUID thingTypeToUpdate) {
|
||||
ThingTypeUID thingTypeUID;
|
||||
List<Thing> things = getThing().getThings();
|
||||
for (Thing thing : things) {
|
||||
thingTypeUID = thing.getThingTypeUID();
|
||||
if (thingTypeToUpdate.equals(thingTypeUID)) {
|
||||
updateChild(thing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Child single child with special representationProperty
|
||||
*
|
||||
* @param thingTypeToUpdate ThingTypeUID of Thing to update
|
||||
* @param representationProperty Name of representationProperty
|
||||
* @param propertyValue Value of representationProperty
|
||||
*/
|
||||
public void updateChild(ThingTypeUID thingTypeToUpdate, String representationProperty, String propertyValue) {
|
||||
List<Thing> things = getThing().getThings();
|
||||
for (Thing thing : things) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
if (thingTypeToUpdate.equals(thingTypeUID)) {
|
||||
String thingProperty = thing.getProperties().get(representationProperty);
|
||||
if (propertyValue.equals(thingProperty)) {
|
||||
updateChild(thing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Child-Thing (send refreshCommand)
|
||||
*
|
||||
* @param thing - Thing to update
|
||||
*/
|
||||
public void updateChild(Thing thing) {
|
||||
ThingHandler handler = thing.getHandler();
|
||||
if (handler != null) {
|
||||
ChannelUID cUid = new ChannelUID(thing.getUID(), CHANNELS_ALL);
|
||||
handler.handleCommand(cUid, RefreshType.REFRESH);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set State of all clients
|
||||
*
|
||||
* @param thingStatus new ThingStatus
|
||||
*/
|
||||
public void updateChildStates(ThingStatus thingStatus) {
|
||||
List<Thing> things = getThing().getThings();
|
||||
for (Thing thing : things) {
|
||||
updateChildState(thing, thingStatus);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set State of a Thing
|
||||
*
|
||||
* @param thing Thing to update
|
||||
* @param thingStatus new ThingStatus
|
||||
*/
|
||||
public void updateChildState(Thing thing, ThingStatus thingStatus) {
|
||||
ThingHandler handler = thing.getHandler();
|
||||
if (handler != null) {
|
||||
if (ThingStatus.OFFLINE.equals(thingStatus)) {
|
||||
handler.bridgeStatusChanged(new ThingStatusInfo(thingStatus, ThingStatusDetail.BRIDGE_OFFLINE, ""));
|
||||
} else {
|
||||
handler.bridgeStatusChanged(new ThingStatusInfo(thingStatus, ThingStatusDetail.NONE, ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************
|
||||
*
|
||||
* FUNCTIONS
|
||||
*
|
||||
************************************/
|
||||
|
||||
/**
|
||||
* Get ChannelID including group
|
||||
*
|
||||
* @param group String channel-group
|
||||
* @param channel String channel-name
|
||||
* @return String channelID
|
||||
*/
|
||||
protected String getChannelID(String group, String channel) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
if (CHANNEL_GROUP_THING_SET.contains(thingTypeUID) && group.length() > 0) {
|
||||
return group + "#" + channel;
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Channel from ChannelID
|
||||
*
|
||||
* @param channelID String channelID
|
||||
* @return String channel-name
|
||||
*/
|
||||
protected String getChannelFromID(ChannelUID channelID) {
|
||||
String channel = channelID.getIdWithoutGroup();
|
||||
channel = channel.replace(CHANNEL_GROUP_SYSINFO + "#", "");
|
||||
channel = channel.replace(CHANNEL_GROUP_CLIENTS + "#", "");
|
||||
return channel;
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<addon:addon id="asuswrt" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:addon="https://openhab.org/schemas/addon/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
|
||||
<type>binding</type>
|
||||
<name>Asuswrt Binding</name>
|
||||
<description>Binding for ASUS routers (Asuswrt / Asuswrt-Merlin only)</description>
|
||||
<connection>local</connection>
|
||||
</addon:addon>
|
@ -0,0 +1,118 @@
|
||||
# add-on
|
||||
|
||||
addon.asuswrt.name = Asuswrt Binding
|
||||
addon.asuswrt.description = Binding for ASUS routers (Asuswrt / Asuswrt-Merlin only)
|
||||
|
||||
# thing types
|
||||
|
||||
thing-type.asuswrt.client.label = Asuswrt Client
|
||||
thing-type.asuswrt.client.description = Client connected to Asuswrt-Router
|
||||
thing-type.asuswrt.interface.label = Router Interface
|
||||
thing-type.asuswrt.interface.description = Interface of router
|
||||
thing-type.asuswrt.router.label = Asuswrt Router
|
||||
thing-type.asuswrt.router.description = Router with Asuswrt or Asuswrt-Merlin OS
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.asuswrt.client.clientNick.label = Nickname
|
||||
thing-type.config.asuswrt.client.clientNick.description = Nickname of the device
|
||||
thing-type.config.asuswrt.client.macAddress.label = MAC Address
|
||||
thing-type.config.asuswrt.client.macAddress.description = MAC address of the device
|
||||
thing-type.config.asuswrt.interface.interfaceName.label = Interface Name
|
||||
thing-type.config.asuswrt.interface.interfaceName.description = Name of selected interface. *Maybe not all are supported by your device*
|
||||
thing-type.config.asuswrt.interface.interfaceName.option.wan = WAN
|
||||
thing-type.config.asuswrt.interface.interfaceName.option.lan = LAN
|
||||
thing-type.config.asuswrt.router.hostname.label = Hostname
|
||||
thing-type.config.asuswrt.router.hostname.description = Hostname or IP address of the device
|
||||
thing-type.config.asuswrt.router.httpPort.label = HTTP Port
|
||||
thing-type.config.asuswrt.router.httpPort.description = Port used for HTTP connection
|
||||
thing-type.config.asuswrt.router.httpsPort.label = HTTPS Port
|
||||
thing-type.config.asuswrt.router.httpsPort.description = Port used for HTTPS connection
|
||||
thing-type.config.asuswrt.router.password.label = Password
|
||||
thing-type.config.asuswrt.router.password.description = Password to access the device
|
||||
thing-type.config.asuswrt.router.pollingInterval.label = Polling Interval
|
||||
thing-type.config.asuswrt.router.pollingInterval.description = Interval the device is polled in sec.
|
||||
thing-type.config.asuswrt.router.useSSL.label = Use SSL
|
||||
thing-type.config.asuswrt.router.useSSL.description = Use SSL to authenticate. If not use HTTP
|
||||
thing-type.config.asuswrt.router.username.label = Username
|
||||
thing-type.config.asuswrt.router.username.description = Username to access the device
|
||||
|
||||
# channel group types
|
||||
|
||||
channel-group-type.asuswrt.client-list-group.label = Clients
|
||||
channel-group-type.asuswrt.client-list-group.description = Clients connected to router
|
||||
channel-group-type.asuswrt.client-list-group.channel.known-clients.label = Known Clients
|
||||
channel-group-type.asuswrt.client-list-group.channel.known-clients.description = Known clients with name and MAC addresses
|
||||
channel-group-type.asuswrt.client-list-group.channel.online-clients.description = Online clients with name and MAC addresses
|
||||
channel-group-type.asuswrt.clientNetworkGroup.label = Clients
|
||||
channel-group-type.asuswrt.clientNetworkGroup.description = Clients connected to router
|
||||
channel-group-type.asuswrt.clientNetworkGroup.channel.ip-address.description = Client IP address
|
||||
channel-group-type.asuswrt.if-info-group.label = LAN Status
|
||||
channel-group-type.asuswrt.if-info-group.description = LAN connection state
|
||||
channel-group-type.asuswrt.sys-info-group.label = System Info
|
||||
channel-group-type.asuswrt.sys-info-group.description = System information about the device
|
||||
channel-group-type.asuswrt.sys-info-group.channel.cpu-used-percent.label = Total CPU Usage
|
||||
channel-group-type.asuswrt.sys-info-group.channel.cpu-used-percent.description = Total CPU usage in percent over all cores
|
||||
channel-group-type.asuswrt.sys-info-group.channel.mem-free.label = Free Memory
|
||||
channel-group-type.asuswrt.sys-info-group.channel.mem-free.description = Free memory in MB
|
||||
channel-group-type.asuswrt.sys-info-group.channel.mem-free-percent.label = Free Memory
|
||||
channel-group-type.asuswrt.sys-info-group.channel.mem-free-percent.description = Free memory in %
|
||||
channel-group-type.asuswrt.sys-info-group.channel.mem-total.label = Total Memory
|
||||
channel-group-type.asuswrt.sys-info-group.channel.mem-total.description = Total memory in MB
|
||||
channel-group-type.asuswrt.sys-info-group.channel.mem-used.label = Used Memory
|
||||
channel-group-type.asuswrt.sys-info-group.channel.mem-used.description = Used memory in MB
|
||||
channel-group-type.asuswrt.sys-info-group.channel.mem-used-percent.label = Used Memory
|
||||
channel-group-type.asuswrt.sys-info-group.channel.mem-used-percent.description = Used memory in %
|
||||
channel-group-type.asuswrt.traffic-group.label = Traffic
|
||||
channel-group-type.asuswrt.traffic-group.description = Traffic Monitoring
|
||||
channel-group-type.asuswrt.traffic-group.channel.cur-rx.label = Current Traffic Received
|
||||
channel-group-type.asuswrt.traffic-group.channel.cur-tx.label = Current Traffic Sent
|
||||
channel-group-type.asuswrt.traffic-group.channel.today-rx.label = Today Traffic Received
|
||||
channel-group-type.asuswrt.traffic-group.channel.today-tx.label = Today Traffic Sent
|
||||
channel-group-type.asuswrt.traffic-group.channel.total-rx.label = Total Traffic Received
|
||||
channel-group-type.asuswrt.traffic-group.channel.total-tx.label = Total Traffic Sent
|
||||
|
||||
# channel types
|
||||
|
||||
channel-type.asuswrt.client-nick-name.label = Nickname
|
||||
channel-type.asuswrt.client-nick-name.description = Nickname of client
|
||||
channel-type.asuswrt.client-online-event-type.label = Online State Changed Trigger
|
||||
channel-type.asuswrt.client-online-event-type.description = Event is fired if client leaves ('gone') or enters ('connected') the network
|
||||
channel-type.asuswrt.clients-online-count-type.label = Online Clients Count
|
||||
channel-type.asuswrt.clients-online-count-type.description = number online clients
|
||||
channel-type.asuswrt.clients-online-mac-type.label = Online MAC Addresses
|
||||
channel-type.asuswrt.clients-online-mac-type.description = List with MAC addresses of online clients
|
||||
channel-type.asuswrt.clients-online-type.label = Online Clients
|
||||
channel-type.asuswrt.clients-online-type.description = List of online clients
|
||||
channel-type.asuswrt.connection-event-type.label = ConnectionState Changed Event
|
||||
channel-type.asuswrt.connection-event-type.description = Event is fired connection state changes ('connected'/'disconnected')
|
||||
channel-type.asuswrt.current-traffic-type.label = Current Traffic
|
||||
channel-type.asuswrt.current-traffic-type.description = Current traffic in MBit/s
|
||||
channel-type.asuswrt.dns-name-type.label = DNS Name
|
||||
channel-type.asuswrt.dns-name-type.description = DNS name
|
||||
channel-type.asuswrt.dns-server-type.label = DNS Server
|
||||
channel-type.asuswrt.dns-server-type.description = Used DNS Servers
|
||||
channel-type.asuswrt.interne-state-type.label = Internet Connected
|
||||
channel-type.asuswrt.interne-state-type.description = Client is connected to Internet
|
||||
channel-type.asuswrt.ip-address-type.label = IP Address
|
||||
channel-type.asuswrt.ip-address-type.description = IP address of interface
|
||||
channel-type.asuswrt.ip-connection-state.label = Connected
|
||||
channel-type.asuswrt.ip-connection-state.description = Connection state of interface
|
||||
channel-type.asuswrt.ip-gateway-type.label = Gateway
|
||||
channel-type.asuswrt.ip-gateway-type.description = Gateway of interface
|
||||
channel-type.asuswrt.ip-netmask-type.label = Subnet
|
||||
channel-type.asuswrt.ip-netmask-type.description = Subnet mask of interface
|
||||
channel-type.asuswrt.ip-proto-type.label = IP Protocol
|
||||
channel-type.asuswrt.ip-proto-type.description = IP address protocol (DHCP/Static)
|
||||
channel-type.asuswrt.is-online-type.label = Online
|
||||
channel-type.asuswrt.is-online-type.description = Client is online
|
||||
channel-type.asuswrt.mac-address-type.label = MAC Address
|
||||
channel-type.asuswrt.mac-address-type.description = MAC address of device (LAN)
|
||||
channel-type.asuswrt.productid.label = Router Model
|
||||
channel-type.asuswrt.productid.description = Model/ProductID of your Router
|
||||
channel-type.asuswrt.today-taffic-type.label = Today Traffic
|
||||
channel-type.asuswrt.today-taffic-type.description = Total traffic in MB since 0:00 a clock
|
||||
channel-type.asuswrt.total-traffic-type.label = Total Traffic
|
||||
channel-type.asuswrt.total-traffic-type.description = Total traffic in MB since reboot
|
||||
channel-type.asuswrt.usage-data-type.label = Usage in MB
|
||||
channel-type.asuswrt.usage-type-percent.label = Percentage
|
@ -0,0 +1,179 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="asuswrt"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- ####################### GLOBAL CHANNEL GROUPS ########################## -->
|
||||
|
||||
<!-- Traffic -->
|
||||
<channel-group-type id="traffic-group">
|
||||
<label>Traffic</label>
|
||||
<description>Traffic Monitoring</description>
|
||||
<channels>
|
||||
<channel id="cur-rx" typeId="current-traffic-type">
|
||||
<label>Current Traffic Received</label>
|
||||
</channel>
|
||||
<channel id="cur-tx" typeId="current-traffic-type">
|
||||
<label>Current Traffic Sent</label>
|
||||
</channel>
|
||||
<channel id="today-rx" typeId="today-taffic-type">
|
||||
<label>Today Traffic Received</label>
|
||||
</channel>
|
||||
<channel id="today-tx" typeId="today-taffic-type">
|
||||
<label>Today Traffic Sent</label>
|
||||
</channel>
|
||||
<channel id="total-rx" typeId="total-traffic-type">
|
||||
<label>Total Traffic Received</label>
|
||||
</channel>
|
||||
<channel id="total-tx" typeId="total-traffic-type">
|
||||
<label>Total Traffic Sent</label>
|
||||
</channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
|
||||
<!-- ############################### CHANNELS ############################### -->
|
||||
|
||||
<!-- Product Id -->
|
||||
<channel-type id="productid">
|
||||
<item-type>String</item-type>
|
||||
<label>Router Model</label>
|
||||
<description>Model/ProductID of your Router</description>
|
||||
</channel-type>
|
||||
|
||||
<!-- Usage -->
|
||||
<channel-type id="usage-data-type">
|
||||
<item-type>Number:DataAmount</item-type>
|
||||
<label>Usage in MB</label>
|
||||
<state pattern="%.0f %unit%" readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="usage-type-percent">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Percentage</label>
|
||||
<state pattern="%.1f %unit%" readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
|
||||
<!-- LAN/WAN INFO -->
|
||||
<channel-type id="dns-name-type">
|
||||
<item-type>String</item-type>
|
||||
<label>DNS Name</label>
|
||||
<description>DNS name</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="dns-server-type">
|
||||
<item-type>String</item-type>
|
||||
<label>DNS Server</label>
|
||||
<description>Used DNS Servers</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="ip-address-type">
|
||||
<item-type>String</item-type>
|
||||
<label>IP Address</label>
|
||||
<description>IP address of interface</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="ip-proto-type">
|
||||
<item-type>String</item-type>
|
||||
<label>IP Protocol</label>
|
||||
<description>IP address protocol (DHCP/Static)</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="mac-address-type">
|
||||
<item-type>String</item-type>
|
||||
<label>MAC Address</label>
|
||||
<description>MAC address of device (LAN)</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="ip-netmask-type">
|
||||
<item-type>String</item-type>
|
||||
<label>Subnet</label>
|
||||
<description>Subnet mask of interface</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="ip-gateway-type">
|
||||
<item-type>String</item-type>
|
||||
<label>Gateway</label>
|
||||
<description>Gateway of interface</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="ip-connection-state">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Connected</label>
|
||||
<description>Connection state of interface</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="connection-event-type">
|
||||
<kind>Trigger</kind>
|
||||
<label>ConnectionState Changed Event</label>
|
||||
<description>Event is fired connection state changes ('connected'/'disconnected')</description>
|
||||
</channel-type>
|
||||
|
||||
<!-- CLIENTS -->
|
||||
<channel-type id="clients-online-type">
|
||||
<item-type>String</item-type>
|
||||
<label>Online Clients</label>
|
||||
<description>List of online clients</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="clients-online-mac-type">
|
||||
<item-type>String</item-type>
|
||||
<label>Online MAC Addresses</label>
|
||||
<description>List with MAC addresses of online clients</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="clients-online-count-type">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Online Clients Count</label>
|
||||
<description>number online clients</description>
|
||||
<state pattern="%.0f" readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="client-nick-name">
|
||||
<item-type>String</item-type>
|
||||
<label>Nickname</label>
|
||||
<description>Nickname of client</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="is-online-type">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Online</label>
|
||||
<description>Client is online</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="interne-state-type">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Internet Connected</label>
|
||||
<description>Client is connected to Internet</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
<channel-type id="client-online-event-type">
|
||||
<kind>Trigger</kind>
|
||||
<label>Online State Changed Trigger</label>
|
||||
<description>Event is fired if client leaves ('gone') or enters ('connected') the network</description>
|
||||
</channel-type>
|
||||
|
||||
|
||||
<!-- Traffic -->
|
||||
<channel-type id="current-traffic-type">
|
||||
<item-type>Number:DataTransferRate</item-type>
|
||||
<label>Current Traffic</label>
|
||||
<description>Current traffic in MBit/s</description>
|
||||
<state pattern="%.2f %unit%" readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="today-taffic-type">
|
||||
<item-type>Number:DataAmount</item-type>
|
||||
<label>Today Traffic</label>
|
||||
<description>Total traffic in MB since 0:00 a clock</description>
|
||||
<state pattern="%.0f %unit%" readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="total-traffic-type">
|
||||
<item-type>Number:DataAmount</item-type>
|
||||
<label>Total Traffic</label>
|
||||
<description>Total traffic in MB since reboot</description>
|
||||
<state pattern="%.0f %unit%" readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="asuswrt"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- Router Thing Type -->
|
||||
<thing-type id="client">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="router"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Asuswrt Client</label>
|
||||
<description>Client connected to Asuswrt-Router</description>
|
||||
<channel-groups>
|
||||
<channel-group id="network-info" typeId="clientNetworkGroup"></channel-group>
|
||||
<channel-group id="traffic" typeId="traffic-group"></channel-group>
|
||||
</channel-groups>
|
||||
<properties>
|
||||
<property name="vendor">Vendor</property>
|
||||
<property name="dnsName">DNS Name</property>
|
||||
</properties>
|
||||
<representation-property>macAddress</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="macAddress" type="text" required="true">
|
||||
<label>MAC Address</label>
|
||||
<description>MAC address of the device</description>
|
||||
<default>00:00:00:00:00:00</default>
|
||||
</parameter>
|
||||
<parameter name="clientNick" type="text" required="false">
|
||||
<label>Nickname</label>
|
||||
<description>Nickname of the device</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<!-- ############################### CHANNEL-GROUPS ############################### -->
|
||||
|
||||
<channel-group-type id="clientNetworkGroup">
|
||||
<label>Clients</label>
|
||||
<description>Clients connected to router</description>
|
||||
<channels>
|
||||
<channel id="network-state" typeId="is-online-type"></channel>
|
||||
<channel id="ip-address" typeId="ip-address-type">
|
||||
<description>Client IP address</description>
|
||||
</channel>
|
||||
<channel id="ip-method" typeId="ip-proto-type"></channel>
|
||||
<channel id="internet-state" typeId="interne-state-type"></channel>
|
||||
<channel id="client-online-event" typeId="client-online-event-type"></channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="asuswrt"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- Router Thing Type -->
|
||||
<thing-type id="interface">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="router"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Router Interface</label>
|
||||
<description>Interface of router</description>
|
||||
<channel-groups>
|
||||
<channel-group id="network-info" typeId="if-info-group"></channel-group>
|
||||
<channel-group id="traffic" typeId="traffic-group"></channel-group>
|
||||
</channel-groups>
|
||||
<representation-property>interfaceName</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="interfaceName" type="text" required="true">
|
||||
<label>Interface Name</label>
|
||||
<description>Name of selected interface. *Maybe not all are supported by your device*</description>
|
||||
<options>
|
||||
<option value="wan">WAN</option>
|
||||
<option value="lan">LAN</option>
|
||||
</options>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
|
||||
<!-- ############################### CHANNEL-GROUPS ############################### -->
|
||||
|
||||
<!-- Interface Information -->
|
||||
<channel-group-type id="if-info-group">
|
||||
<label>LAN Status</label>
|
||||
<description>LAN connection state</description>
|
||||
<channels>
|
||||
<channel id="mac-address" typeId="mac-address-type"></channel>
|
||||
<channel id="ip-address" typeId="ip-address-type"></channel>
|
||||
<channel id="ip-method" typeId="ip-proto-type"></channel>
|
||||
<channel id="subnet" typeId="ip-netmask-type"></channel>
|
||||
<channel id="gateway" typeId="ip-gateway-type"></channel>
|
||||
<channel id="dns-servers" typeId="dns-server-type"></channel>
|
||||
<channel id="network-state" typeId="ip-connection-state"></channel>
|
||||
<channel id="connection-event" typeId="connection-event-type"></channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="asuswrt"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- Router Thing Type -->
|
||||
<bridge-type id="router">
|
||||
<label>Asuswrt Router</label>
|
||||
<description>Router with Asuswrt or Asuswrt-Merlin OS</description>
|
||||
<channel-groups>
|
||||
<channel-group id="sys-info" typeId="sys-info-group"></channel-group>
|
||||
<channel-group id="client-list" typeId="client-list-group"></channel-group>
|
||||
</channel-groups>
|
||||
|
||||
<config-description>
|
||||
<parameter name="hostname" type="text" required="true">
|
||||
<context>network-address</context>
|
||||
<label>Hostname</label>
|
||||
<description>Hostname or IP address of the device</description>
|
||||
<default>router.asus.com</default>
|
||||
</parameter>
|
||||
<parameter name="username" type="text" required="true">
|
||||
<label>Username</label>
|
||||
<description>Username to access the device</description>
|
||||
</parameter>
|
||||
<parameter name="password" type="text" required="true">
|
||||
<context>password</context>
|
||||
<label>Password</label>
|
||||
<description>Password to access the device</description>
|
||||
</parameter>
|
||||
<parameter name="useSSL" type="boolean">
|
||||
<label>Use SSL</label>
|
||||
<description>Use SSL to authenticate. If not use HTTP</description>
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
<parameter name="httpPort" type="integer">
|
||||
<label>HTTP Port</label>
|
||||
<description>Port used for HTTP connection</description>
|
||||
<default>80</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="httpsPort" type="integer">
|
||||
<label>HTTPS Port</label>
|
||||
<description>Port used for HTTPS connection</description>
|
||||
<default>443</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
<parameter name="pollingInterval" type="integer" unit="s" min="3">
|
||||
<label>Polling Interval</label>
|
||||
<description>Interval the device is polled in sec.</description>
|
||||
<default>20</default>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
|
||||
<!-- ############################### CHANNEL-GROUPS ############################### -->
|
||||
<!-- System Information -->
|
||||
<channel-group-type id="sys-info-group">
|
||||
<label>System Info</label>
|
||||
<description>System information about the device</description>
|
||||
<channels>
|
||||
<channel id="mem-total" typeId="usage-data-type">
|
||||
<label>Total Memory</label>
|
||||
<description>Total memory in MB</description>
|
||||
</channel>
|
||||
<channel id="mem-used" typeId="usage-data-type">
|
||||
<label>Used Memory</label>
|
||||
<description>Used memory in MB</description>
|
||||
</channel>
|
||||
<channel id="mem-free" typeId="usage-data-type">
|
||||
<label>Free Memory</label>
|
||||
<description>Free memory in MB</description>
|
||||
</channel>
|
||||
<channel id="mem-free-percent" typeId="usage-type-percent">
|
||||
<label>Free Memory</label>
|
||||
<description>Free memory in %</description>
|
||||
</channel>
|
||||
<channel id="mem-used-percent" typeId="usage-type-percent">
|
||||
<label>Used Memory</label>
|
||||
<description>Used memory in %</description>
|
||||
</channel>
|
||||
<channel id="cpu-used-percent" typeId="usage-type-percent">
|
||||
<label>Total CPU Usage</label>
|
||||
<description>Total CPU usage in percent over all cores</description>
|
||||
</channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<!-- Clients -->
|
||||
<channel-group-type id="client-list-group">
|
||||
<label>Clients</label>
|
||||
<description>Clients connected to router</description>
|
||||
<channels>
|
||||
<channel id="known-clients" typeId="clients-online-type">
|
||||
<label>Known Clients</label>
|
||||
<description>Known clients with name and MAC addresses</description>
|
||||
</channel>
|
||||
<channel id="online-clients" typeId="clients-online-type">
|
||||
<description>Online clients with name and MAC addresses</description>
|
||||
</channel>
|
||||
<channel id="online-macs" typeId="clients-online-mac-type"></channel>
|
||||
<channel id="online-clients-count" typeId="clients-online-count-type"></channel>
|
||||
<channel id="client-online-event" typeId="client-online-event-type"></channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
@ -60,6 +60,7 @@
|
||||
<module>org.openhab.binding.anel</module>
|
||||
<module>org.openhab.binding.anthem</module>
|
||||
<module>org.openhab.binding.astro</module>
|
||||
<module>org.openhab.binding.asuswrt</module>
|
||||
<module>org.openhab.binding.atlona</module>
|
||||
<module>org.openhab.binding.autelis</module>
|
||||
<module>org.openhab.binding.automower</module>
|
||||
|
Loading…
Reference in New Issue
Block a user