[tplinkrouter] Initial contribution (#13369)

* Initial commit

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>
This commit is contained in:
Olivier 2022-10-15 21:52:33 +02:00 committed by GitHub
parent 19b4c95103
commit 73e18424b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 875 additions and 0 deletions

View File

@ -329,6 +329,7 @@
/bundles/org.openhab.binding.tibber/ @kjoglum
/bundles/org.openhab.binding.tivo/ @mlobstein
/bundles/org.openhab.binding.touchwand/ @roieg
/bundles/org.openhab.binding.tplinkrouter/ @olivierkeke
/bundles/org.openhab.binding.tplinksmarthome/ @Hilbrand
/bundles/org.openhab.binding.tr064/ @openhab/add-ons-maintainers
/bundles/org.openhab.binding.tradfri/ @cweitkamp @kaikreuzer

View File

@ -1651,6 +1651,11 @@
<artifactId>org.openhab.binding.touchwand</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.tplinkrouter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.tplinksmarthome</artifactId>

View 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

View File

@ -0,0 +1,57 @@
# tplinkrouter Binding
The tplinkrouter Binding allows monitoring and controlling TP-Link routers.
The binding uses a telnet connection to communicate with the router.
At the moment only wifi part is supported and `TD-W9970` is the only model tested.
This binding may work with other TP-Link router provided that they use the same telnet API.
## Supported Things
This binding provides only the `router` Thing.
## Thing Configuration
### `router` Thing Configuration
| Name | Type | Description | Default | Required | Advanced |
|-----------------|---------|-----------------------------------------------|---------|----------|----------|
| hostname | text | Hostname or IP address of the device | N/A | yes | no |
| port | integer | Port for telnet connection | 23 | no | no |
| username | text | Username to access the router (same as WebUI) | N/A | yes | no |
| password | text | Password to access the device (same as WebUI) | N/A | yes | no |
| refreshInterval | integer | Interval the device is polled in sec. | 60 | no | yes |
## Channels
| Channel | Type | Read/Write | Description |
|-----------------------|--------|------------|------------------------------------------|
| `wifi#status` | Switch | RW | State of the wifi |
| `wifi#ssid` | String | R | SSID of the wifi network |
| `wifi#bandwidth` | String | R | Bandwidth of the wifi network |
| `wifi#qss` | Switch | RW | Quick Security Setup of the wifi network |
| `wifi#secMode` | String | R | Security Mode of the wifi network |
| `wifi#authentication` | String | R | Authentication Mode of the wifi network |
| `wifi#encryption` | String | R | Encryption Mode of the wifi network |
| `wifi#key` | String | R | Password of the wifi network |
## Full Example
`.things` configuration file:
```
Thing tplinkrouter:router:myRouter [hostname="192.168.0.1", username="admin", password="myPassword"]
```
`.items` configuration file:
```
Switch Wifi "Wifi" <QualityOfService> {channel="tplinkrouter:router:myRouter:wifi#status", autoupdate="false"}
String WifiSSID "Wifi SSID" <QualityOfService> {channel="tplinkrouter:router:myRouter:wifi#ssid"}
String BandWidth "Wifi Bandwidth" <QualityOfService> {channel="tplinkrouter:router:myRouter:wifi#bandwidth"}
Switch QSS "Wifi QSS" <QualityOfService> {channel="tplinkrouter:router:myRouter:wifi#qss", autoupdate="false"}
String SecMode "Wifi Security Mode" <QualityOfService> {channel="tplinkrouter:router:myRouter:wifi#secMode"}
String Authentication "Wifi Authentication Mode" <QualityOfService> {channel="tplinkrouter:router:myRouter:wifi#authentication"}
String Encryption "Wifi Encryption Mode" <QualityOfService> {channel="tplinkrouter:router:myRouter:wifi#encryption"}
```

View 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>3.4.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.binding.tplinkrouter</artifactId>
<name>openHAB Add-ons :: Bundles :: TpLinkRouter Binding</name>
</project>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.tplinkrouter-${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-tplinkrouter" description="TpLinkRouter Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.tplinkrouter/${project.version}</bundle>
</feature>
</features>

View File

@ -0,0 +1,41 @@
/**
* Copyright (c) 2010-2022 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.tplinkrouter.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
/**
* The {@link TpLinkRouterBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Olivier Marceau - Initial contribution
*/
@NonNullByDefault
public class TpLinkRouterBindingConstants {
private static final String BINDING_ID = "tplinkrouter";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_ROUTER = new ThingTypeUID(BINDING_ID, "router");
// List of all Channel ids
public static final String WIFI_STATUS = "wifi#status";
public static final String WIFI_SSID = "wifi#ssid";
public static final String WIFI_BANDWIDTH = "wifi#bandwidth";
public static final String WIFI_QSS = "wifi#qss";
public static final String WIFI_SECMODE = "wifi#secMode";
public static final String WIFI_AUTHENTICATION = "wifi#authentication";
public static final String WIFI_ENCRYPTION = "wifi#encryption";
public static final String WIFI_KEY = "wifi#key";
}

View File

@ -0,0 +1,30 @@
/**
* Copyright (c) 2010-2022 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.tplinkrouter.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link TpLinkRouterConfiguration} class contains fields mapping thing configuration parameters.
*
* @author Olivier Marceau - Initial contribution
*/
@NonNullByDefault
public class TpLinkRouterConfiguration {
public String hostname = "";
public int port = 23;
public String username = "";
public String password = "";
public int refreshInterval = 60;
}

View File

@ -0,0 +1,239 @@
/**
* Copyright (c) 2010-2022 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.tplinkrouter.internal;
import static org.openhab.binding.tplinkrouter.internal.TpLinkRouterBindingConstants.*;
import java.io.IOException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.StringType;
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.binding.BaseThingHandler;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link TpLinkRouterHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Olivier Marceau - Initial contribution
*/
@NonNullByDefault
public class TpLinkRouterHandler extends BaseThingHandler implements TpLinkRouterTelenetListener {
private static final long RECONNECT_DELAY = TimeUnit.MINUTES.toMillis(1);
private static final String REFRESH_CMD = "wlctl show";
private static final String WIFI_ON_CMD = "wlctl set --switch on";
private static final String WIFI_OFF_CMD = "wlctl set --switch off";
private static final String QSS_ON_CMD = "wlctl set --qss on";
private static final String QSS_OFF_CMD = "wlctl set --qss off";
private final Logger logger = LoggerFactory.getLogger(TpLinkRouterHandler.class);
private final TpLinkRouterTelnetConnector connector = new TpLinkRouterTelnetConnector();
private final BlockingQueue<ChannelUIDCommand> commandQueue = new ArrayBlockingQueue<>(1);
private TpLinkRouterConfiguration config = new TpLinkRouterConfiguration();
private @Nullable ScheduledFuture<?> scheduledFuture;
public TpLinkRouterHandler(Thing thing) {
super(thing);
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (WIFI_STATUS.equals(channelUID.getId())) {
try {
commandQueue.put(new ChannelUIDCommand(channelUID, command));
} catch (InterruptedException e) {
logger.warn("Got exception", e);
Thread.currentThread().interrupt();
}
if (command instanceof RefreshType) {
connector.sendCommand(REFRESH_CMD);
} else if (command == OnOffType.ON) {
connector.sendCommand(WIFI_ON_CMD);
} else if (command == OnOffType.OFF) {
connector.sendCommand(WIFI_OFF_CMD);
}
} else if (WIFI_QSS.equals(channelUID.getId())) {
try {
commandQueue.put(new ChannelUIDCommand(channelUID, command));
} catch (InterruptedException e) {
logger.warn("Got exception", e);
Thread.currentThread().interrupt();
}
if (command instanceof RefreshType) {
connector.sendCommand(REFRESH_CMD);
} else if (command == OnOffType.ON) {
connector.sendCommand(QSS_ON_CMD);
} else if (command == OnOffType.OFF) {
connector.sendCommand(QSS_OFF_CMD);
}
}
}
@Override
public void initialize() {
config = getConfigAs(TpLinkRouterConfiguration.class);
updateStatus(ThingStatus.UNKNOWN);
scheduler.execute(this::createConnection);
}
@Override
public void dispose() {
ScheduledFuture<?> scheduledFutureLocal = scheduledFuture;
if (scheduledFutureLocal != null) {
scheduledFutureLocal.cancel(true);
scheduledFuture = null;
}
commandQueue.clear();
connector.dispose();
super.dispose();
}
private void createConnection() {
connector.dispose();
try {
connector.connect(this, config, this.getThing().getUID().getAsString());
} catch (IOException e) {
logger.debug("Error while connecting, will retry in {} ms", RECONNECT_DELAY);
scheduler.schedule(this::createConnection, RECONNECT_DELAY, TimeUnit.MILLISECONDS);
}
}
@Override
public void receivedLine(String line) {
logger.debug("Received line: {}", line);
Pattern pattern = Pattern.compile("(\\w+)=(.+)");
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
String label = matcher.group(1);
String value = matcher.group(2);
switch (label) {
case "Status":
if ("Disabled".equals(value)) {
updateState(WIFI_STATUS, OnOffType.OFF);
} else if ("Up".equals(value)) {
updateState(WIFI_STATUS, OnOffType.ON);
} else {
logger.warn("Unsupported value {} for label {}", value, label);
}
break;
case "SSID":
updateState(WIFI_SSID, StringType.valueOf(value));
break;
case "bandWidth":
updateState(WIFI_BANDWIDTH, StringType.valueOf(value));
break;
case "QSS":
if ("Disabled".equals(value)) {
updateState(WIFI_QSS, OnOffType.OFF);
} else if ("Enable".equals(value)) {
updateState(WIFI_QSS, OnOffType.ON);
} else {
logger.warn("Unsupported value {} for label {}", value, label);
}
break;
case "SecMode":
String[] parts = value.split("\\s|-");
updateState(WIFI_SECMODE, StringType.valueOf(parts[0]));
updateState(WIFI_AUTHENTICATION, StringType.valueOf(parts[1]));
if (parts.length >= 3) {
updateState(WIFI_ENCRYPTION, StringType.valueOf(parts[2]));
} else {
updateState(WIFI_ENCRYPTION, StringType.EMPTY);
}
break;
case "Key":
updateState(WIFI_KEY, StringType.valueOf(value));
break;
default:
logger.debug("Unrecognized label {}", label);
}
} else if ("cmd:SUCC".equals(line)) {
ChannelUIDCommand channelUIDCommand = commandQueue.poll();
if (channelUIDCommand != null && channelUIDCommand.getCommand() instanceof State) {
updateState(channelUIDCommand.getChannelUID(), (State) channelUIDCommand.getCommand());
}
} else if ("Login incorrect. Try again.".equals(line)) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Login or password incorrect");
}
}
@Override
public void onReaderThreadStopped() {
updateStatus(ThingStatus.OFFLINE);
logger.debug("try to reconnect in {} ms", RECONNECT_DELAY);
scheduler.schedule(this::createConnection, RECONNECT_DELAY, TimeUnit.MILLISECONDS);
}
@Override
public void onReaderThreadInterrupted() {
updateStatus(ThingStatus.OFFLINE);
}
@Override
public void onReaderThreadStarted() {
scheduledFuture = scheduler.scheduleWithFixedDelay(() -> {
handleCommand(new ChannelUID(getThing().getUID(), WIFI_STATUS), RefreshType.REFRESH);
}, 0, config.refreshInterval, TimeUnit.SECONDS);
updateStatus(ThingStatus.ONLINE);
}
@Override
public void onCommunicationUnavailable() {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
"Connection not available. Check if there is not another open connection.");
}
}
/**
* Stores a command with associated channel
*
* @author Olivier Marceau - Initial contribution
*/
@NonNullByDefault
class ChannelUIDCommand {
private final ChannelUID channelUID;
private final Command command;
public ChannelUIDCommand(ChannelUID channelUID, Command command) {
this.channelUID = channelUID;
this.command = command;
}
public ChannelUID getChannelUID() {
return channelUID;
}
public Command getCommand() {
return command;
}
}

View File

@ -0,0 +1,55 @@
/**
* Copyright (c) 2010-2022 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.tplinkrouter.internal;
import static org.openhab.binding.tplinkrouter.internal.TpLinkRouterBindingConstants.*;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
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.annotations.Component;
/**
* The {@link TpLinkRouterHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Olivier Marceau - Initial contribution
*/
@NonNullByDefault
@Component(configurationPid = "binding.tplinkrouter", service = ThingHandlerFactory.class)
public class TpLinkRouterHandlerFactory extends BaseThingHandlerFactory {
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_ROUTER);
@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)) {
return new TpLinkRouterHandler(thing);
}
return null;
}
}

View File

@ -0,0 +1,51 @@
/**
* Copyright (c) 2010-2022 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.tplinkrouter.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link TpLinkRouterTelenetListener} defines listener for telnet events.
*
* @author Olivier Marceau - Initial contribution
*/
@NonNullByDefault
public interface TpLinkRouterTelenetListener {
/**
* The telnet client has received a line.
*
* @param line the received line
*/
void receivedLine(String line);
/**
* The telnet client encountered an IO error.
*/
void onReaderThreadStopped();
/**
* The telnet client has been interrupted.
*/
void onReaderThreadInterrupted();
/**
* The telnet client has successfully connected to the receiver.
*/
void onReaderThreadStarted();
/**
* The telnet socket is unavailable.
*/
void onCommunicationUnavailable();
}

View File

@ -0,0 +1,164 @@
/**
* Copyright (c) 2010-2022 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.tplinkrouter.internal;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link TpLinkRouterTelnetConnector} is responsible for the telnet connection.
*
* @author Olivier Marceau - Initial contribution
*/
@NonNullByDefault
public class TpLinkRouterTelnetConnector {
private static final int TIMEOUT_MS = (int) TimeUnit.MINUTES.toMillis(1);
private final Logger logger = LoggerFactory.getLogger(TpLinkRouterTelnetConnector.class);
private @Nullable Thread telnetClientThread;
private @Nullable Socket socket; // use raw socket since commons net usage seems discouraged
private @Nullable OutputStreamWriter out;
public void connect(TpLinkRouterTelenetListener listener, TpLinkRouterConfiguration config, String thingUID)
throws IOException {
logger.debug("Connecting to {}", config.hostname);
Socket socketLocal = new Socket();
socketLocal.connect(new InetSocketAddress(config.hostname, config.port));
socketLocal.setSoTimeout(TIMEOUT_MS);
socketLocal.setKeepAlive(true);
InputStreamReader inputStream = new InputStreamReader(socketLocal.getInputStream());
this.out = new OutputStreamWriter(socketLocal.getOutputStream());
this.socket = socketLocal;
loginAttempt(listener, inputStream, config);
Thread clientThread = new Thread(() -> listenInputStream(listener, inputStream, config));
clientThread.setName("OH-binding-" + thingUID);
this.telnetClientThread = clientThread;
clientThread.start();
logger.debug("TP-Link router telnet client connected to {}", config.hostname);
}
public void dispose() {
logger.debug("disposing connector");
Thread clientThread = telnetClientThread;
if (clientThread != null) {
clientThread.interrupt();
telnetClientThread = null;
}
Socket socketLocal = socket;
if (socketLocal != null) {
try {
socketLocal.close();
} catch (IOException e) {
logger.debug("Error while disconnecting telnet client", e);
}
socket = null;
}
}
public void sendCommand(String command) {
logger.debug("sending command: {}", command);
OutputStreamWriter output = out;
if (output != null) {
try {
output.write(command + '\n');
output.flush();
} catch (IOException e) {
logger.warn("Error sending command", e);
}
} else {
logger.debug("Cannot send command, no telnet connection");
}
}
private void listenInputStream(TpLinkRouterTelenetListener listener, InputStreamReader inputStream,
TpLinkRouterConfiguration config) {
listener.onReaderThreadStarted();
BufferedReader in = new BufferedReader(inputStream);
try {
while (!Thread.currentThread().isInterrupted()) {
try {
String line = in.readLine();
if (line != null && !line.isBlank()) {
listener.receivedLine(line);
if ("CLI exited after timing out".equals(line)) {
OutputStreamWriter output = out;
if (output != null) {
output.write("\n"); // trigger a "username:" prompt
output.flush();
loginAttempt(listener, inputStream, config);
}
}
}
} catch (SocketTimeoutException e) {
logger.trace("Socket timeout");
}
}
} catch (InterruptedIOException e) {
logger.debug("Error in telnet connection ", e);
} catch (IOException e) {
if (!Thread.currentThread().isInterrupted()) {
logger.debug("Error in telnet connection ", e);
listener.onReaderThreadStopped();
}
}
if (Thread.currentThread().isInterrupted()) {
logger.debug("Interrupted client thread");
listener.onReaderThreadInterrupted();
}
}
private void loginAttempt(TpLinkRouterTelenetListener listener, InputStreamReader inputStreamReader,
TpLinkRouterConfiguration config) throws IOException {
int charInt;
StringBuilder word = new StringBuilder();
OutputStreamWriter output = out;
if (output != null) {
try {
while ((charInt = inputStreamReader.read()) != -1) {
word.append((char) charInt);
logger.trace("received char: {}", (char) charInt);
if (word.toString().contains("username:")) {
logger.debug("Sending username");
output.write(config.username + '\n');
output.flush();
word = new StringBuilder();
}
if (word.toString().contains("password:")) {
logger.debug("Sending password");
output.write(config.password + '\n');
output.flush();
break;
}
}
} catch (SocketTimeoutException e) {
listener.onCommunicationUnavailable();
}
}
}
}

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="tplinkrouter" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
<name>TpLinkRouter Binding</name>
<description>This is the binding for controlling a TP-Link router with telnet.</description>
</binding:binding>

View File

@ -0,0 +1,52 @@
# binding
binding.tplinkrouter.name = TpLinkRouter Binding
binding.tplinkrouter.description = This is the binding for controlling a TP-Link router with telnet.
# thing types
thing-type.tplinkrouter.router.label = Router
thing-type.tplinkrouter.router.description = Router device monitored and controlled by telnet connection
# thing types config
thing-type.config.tplinkrouter.router.hostname.label = Hostname
thing-type.config.tplinkrouter.router.hostname.description = Hostname or IP address of the device
thing-type.config.tplinkrouter.router.password.label = Password
thing-type.config.tplinkrouter.router.password.description = Password to access the device
thing-type.config.tplinkrouter.router.port.label = Port
thing-type.config.tplinkrouter.router.port.description = Port for telnet connection
thing-type.config.tplinkrouter.router.refreshInterval.label = Refresh Interval
thing-type.config.tplinkrouter.router.refreshInterval.description = Interval the device is polled in sec.
thing-type.config.tplinkrouter.router.username.label = Username
thing-type.config.tplinkrouter.router.username.description = User to access the device
# channel group types
channel-group-type.tplinkrouter.wifiGroupType.label = Wifi
channel-group-type.tplinkrouter.wifiGroupType.description = Wifi channels
# channel types
channel-type.tplinkrouter.authentication.label = Wifi Authentication Mode
channel-type.tplinkrouter.authentication.state.option.AUTO = AUTO
channel-type.tplinkrouter.authentication.state.option.OPEN = OPEN
channel-type.tplinkrouter.authentication.state.option.SHARED = SHARED
channel-type.tplinkrouter.authentication.state.option.WPA = WPA
channel-type.tplinkrouter.authentication.state.option.WPA2 = WPA2
channel-type.tplinkrouter.bandwidth.label = Wifi BandWidth
channel-type.tplinkrouter.bandwidth.state.option.Auto = Auto
channel-type.tplinkrouter.bandwidth.state.option.20M = 20 MHz
channel-type.tplinkrouter.bandwidth.state.option.40M = 40 MHz
channel-type.tplinkrouter.encryption.label = Wifi Encryption Mode
channel-type.tplinkrouter.encryption.description = Wifi Encryption Mode (only for PSK security mode)
channel-type.tplinkrouter.encryption.state.option.AUTO = AUTO
channel-type.tplinkrouter.encryption.state.option.TKIP = TKIP
channel-type.tplinkrouter.encryption.state.option.AES = AES
channel-type.tplinkrouter.key.label = Wifi Key
channel-type.tplinkrouter.qss.label = Wifi QSS
channel-type.tplinkrouter.security-mode.label = Wifi Security Mode
channel-type.tplinkrouter.security-mode.state.option.WEP = WEP
channel-type.tplinkrouter.security-mode.state.option.WPA = PSK
channel-type.tplinkrouter.ssid.label = Wifi SSID
channel-type.tplinkrouter.status.label = Wifi Status

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="tplinkrouter"
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">
<channel-group-type id="wifiGroupType">
<label>Wifi</label>
<description>Wifi channels</description>
<channels>
<channel id="status" typeId="status"/>
<channel id="ssid" typeId="ssid"/>
<channel id="bandwidth" typeId="bandwidth"/>
<channel id="qss" typeId="qss"/>
<channel id="secMode" typeId="security-mode"/>
<channel id="authentication" typeId="authentication"/>
<channel id="encryption" typeId="encryption"/>
<channel id="key" typeId="key"/>
</channels>
</channel-group-type>
<channel-type id="qss">
<item-type>Switch</item-type>
<label>Wifi QSS</label>
</channel-type>
<channel-type id="status">
<item-type>Switch</item-type>
<label>Wifi Status</label>
</channel-type>
<channel-type id="ssid">
<item-type>String</item-type>
<label>Wifi SSID</label>
<state pattern="%s" readOnly="true"/>
</channel-type>
<channel-type id="key">
<item-type>String</item-type>
<label>Wifi Key</label>
<state pattern="%s" readOnly="true"/>
</channel-type>
<channel-type id="security-mode">
<item-type>String</item-type>
<label>Wifi Security Mode</label>
<state readOnly="true">
<options>
<option value="WEP">WEP</option>
<option value="WPA">PSK</option>
</options>
</state>
</channel-type>
<channel-type id="authentication">
<item-type>String</item-type>
<label>Wifi Authentication Mode</label>
<state readOnly="true">
<options>
<option value="AUTO">AUTO</option>
<option value="OPEN">OPEN</option>
<option value="SHARED">SHARED</option>
<option value="WPA">WPA</option>
<option value="WPA2">WPA2</option>
</options>
</state>
</channel-type>
<channel-type id="encryption">
<item-type>String</item-type>
<label>Wifi Encryption Mode</label>
<description>Wifi Encryption Mode (only for PSK security mode)</description>
<state readOnly="true">
<options>
<option value="AUTO">AUTO</option>
<option value="TKIP">TKIP</option>
<option value="AES">AES</option>
</options>
</state>
</channel-type>
<channel-type id="bandwidth">
<item-type>String</item-type>
<label>Wifi BandWidth</label>
<state readOnly="true">
<options>
<option value="Auto">Auto</option>
<option value="20M">20 MHz</option>
<option value="40M">40 MHz</option>
</options>
</state>
</channel-type>
</thing:thing-descriptions>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="tplinkrouter"
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">
<thing-type id="router">
<label>Router</label>
<description>Router device monitored and controlled by telnet connection</description>
<channel-groups>
<channel-group id="wifi" typeId="wifiGroupType"/>
</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>
</parameter>
<parameter name="port" type="integer">
<label>Port</label>
<description>Port for telnet connection</description>
<default>23</default>
</parameter>
<parameter name="username" type="text" required="true">
<label>Username</label>
<description>User 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="refreshInterval" type="integer" unit="s" min="1">
<label>Refresh Interval</label>
<description>Interval the device is polled in sec.</description>
<default>60</default>
<advanced>true</advanced>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@ -364,6 +364,7 @@
<module>org.openhab.binding.tibber</module>
<module>org.openhab.binding.tivo</module>
<module>org.openhab.binding.touchwand</module>
<module>org.openhab.binding.tplinkrouter</module>
<module>org.openhab.binding.tplinksmarthome</module>
<module>org.openhab.binding.tr064</module>
<module>org.openhab.binding.tradfri</module>