Skip to content

Commit

Permalink
[Tapocontrol] Binding to control Tapo (by TP-Link) Devices (openhab#1…
Browse files Browse the repository at this point in the history
…1111)

* [tapocontrol] New Source Upload

Signed-off-by: Christian Wild <christian@wild-bw.de>

* [tapocontrol] Delete bundles/org.openhab.binding.tapocontrol directory

Signed-off-by: Christian Wild <christian@wild-bw.de>

* [tapocontrol] Snapshot 3.2

Signed-off-by: Christian Wild <christian@wild-bw.de>

* [tapocontrol] Update CODEOWNERS

Fixed bindingname

Signed-off-by: Christian Wild <christian@wild-bw.de>

* [tapocontrol] Update README.md

Signed-off-by: Christian Wild <christian@wild-bw.de>

* [tapocontrol] new "Bridge-Version"

Credentials (TapoCloud) where now set in a bridge device.
Things now had to be attached to a bridge.

Signed-off-by: Christian Wild <christian@wild-bw.de>

* [tapocontrol] fixed device discovery bug

fixed device discovery bug
added bridge to thing-types.xml

Signed-off-by: Christian Wild <christian@wild-bw.de>

* [tapocontrol] Update bundles/org.openhab.binding.tapocontrol/README.md

Co-authored-by: Fabian Wolter <github@fabian-wolter.de>
Signed-off-by: Christian Wild <christian@wild-bw.de>

* [tapocontrol] code cleanup and optimization

- general code cleanup and optimization
- limited max connections and queued requests to 10 per destination
- device error handling revised
- review remarks of pull request processed

Signed-off-by: Christian Wild <christian@wild-bw.de>

* [tapocontrol] solved review requests

Signed-off-by: Christian Wild <christian@wild-bw.de>

* [tapocontrol] LightStrip L900 basicly supported

Signed-off-by: Christian Wild <christian@wild-bw.de>

* [tapocontrol] fixed review requests

Signed-off-by: Christian Wild <christian@wild-bw.de>

* [tapocontrol] fixed compiler warnings

Signed-off-by: Christian Wild <christian@wild-bw.de>

Co-authored-by: Fabian Wolter <github@fabian-wolter.de>
  • Loading branch information
2 people authored and andan67 committed Nov 5, 2022
1 parent e2bd5e8 commit 5a39c6d
Show file tree
Hide file tree
Showing 48 changed files with 6,820 additions and 0 deletions.
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@
/bundles/org.openhab.binding.tacmi/ @twendt @Wolfgang1966 @marvkis
/bundles/org.openhab.binding.tado/ @dfrommi
/bundles/org.openhab.binding.tankerkoenig/ @dolic @JueBag
/bundles/org.openhab.binding.tapocontrol/ @wildcs
/bundles/org.openhab.binding.telegram/ @ZzetT
/bundles/org.openhab.binding.teleinfo/ @Nokyyz @olivierkeke
/bundles/org.openhab.binding.tellstick/ @openhab/add-ons-maintainers
Expand Down
5 changes: 5 additions & 0 deletions bom/openhab-addons/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1476,6 +1476,11 @@
<artifactId>org.openhab.binding.tankerkoenig</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.tapocontrol</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.telegram</artifactId>
Expand Down
13 changes: 13 additions & 0 deletions bundles/org.openhab.binding.tapocontrol/NOTICE
Original file line number Diff line number Diff line change
@@ -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
114 changes: 114 additions & 0 deletions bundles/org.openhab.binding.tapocontrol/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# TapoControl Binding

This binding adds support to control Tapo (Copyright © TP-Link Corporation Limited) Smart Home Devices from your local openHAB system.

## Supported Things

The following Tapo-Devices are supported

### P100/P105 SmartPlug (WiFi)

* Power On/Off
* Wi-Fi signal (SignalStrength)
* On-Time (Time in seconds device is switched on)

### L510_Series dimmable SmartBulb (WiFi)

* Light On/Off
* Brightnes (Dimmer) 0-100 %
* ColorTemperature (Number) 2500-6500 K
* Wi-Fi signal (SignalStrength)
* On-Time (Time in seconds device is switched on)

### L530_Series MultiColor SmartBulb (WiFi)

* Light On/Off
* Brightnes (Dimmer) 0-100 %
* ColorTemperature (Number) 2500-6500 K
* Color (Color)
* Wi-Fi signal (SignalStrength)
* On-Time (Time in seconds device is switched on)

### L900 MultiColor LightStrip (WiFi)

* Light On/Off
* Brightnes (Dimmer) 0-100 %
* ColorTemperature (Number) 2500-6500 K
* Color (Color)
* Wi-Fi signal (SignalStrength)
* On-Time (Time in seconds device is switched on)


## Prerequisites

Before using Smart Plugs with openHAB the devices must be connected to the Wi-Fi network.
This can be done using the Tapo provided mobile app.
You need to setup a bridge (Cloud-Login) to commiunicate with your devices.

## Discovery

Discovery is done by connecting to the Tapo-Cloud Service.
All devices stored in your cloud account will be detected even if they are not in your network.
You need to know the IP-Adress of your device. This must be set manually in the thing configuration

## Bridge Configuration

The bridge needs to be configured with by `username` and `password` (Tapo-Cloud login) .
This is used for device discovery and to create a handshake (cookie) to act with your devices over the local network.

The thing has the following configuration parameters:

| Parameter | Description |
|--------------------|----------------------------------------------------------------------|
| username | Username (eMail) of your Tapo-Cloud |
| password | Password of your Tapo-Cloud |

## Thing Configuration

The thing needs to be configured with `ipAddress`.

The thing has the following configuration parameters:

| Parameter | Description |
|--------------------|----------------------------------------------------------------------|
| ipAddress | IP Address of the device. |
| pollingInterval | Refresh interval in seconds. Optional. The default is 30 seconds |


## Channels

All devices support some of the following channels:

| group | channel |type | description | things supporting this channel |
|-----------|----------------- |------------------------|------------------------------|---------------------------------|
| actuator | output | Switch | Power device on or off | P100, P105,L510, L530, L900 |
| | brightness | Dimmer | Brightness 0-100% | L510, L530, L900 |
| | colorTemperature | Number | White-Color-Temp 2500-6500K | L510, L530, L900 |
| | color | Color | Color | L530, L900 |
| device | wifiSignal | system.signal-strength | WiFi-quality-level | P100, P105, L510, L530, L900 |
| | onTime | Number:Time | seconds output is on | P100, P105, L510, L530, L900 |


## Channel Refresh

When the thing receives a `RefreshType` command the thing will send a new refreshRequest over http.
To minimize network traffic the default refresh-rate is set to 30 seconds. This can be reduced down to 10 seconds in advanced settings of the device. If any command was sent to a channel, it will do an immediately refresh of the whole device.


## Full Example

### tapocontrol.things:

```
tapocontrol:bridge:myTapoBridge "Cloud-Login" [ username="you@yourpovider.com", password="verysecret" ]
tapocontrol:P100:myTapoBridge:mySocket "My-Socket" [ ipAddress="192.168.178.150", pollingInterval=30 ]
tapocontrol:L510_Series:myTapoBridge:whiteBulb "white-light" [ ipAddress="192.168.178.151", pollingInterval=30 ]
tapocontrol:L530_Series:myTapoBridge:colorBulb "color-light" [ ipAddress="192.168.178.152", pollingInterval=30 ]
tapocontrol:L900:myTapoBridge:myLightStrip "light-strip" [ ipAddress="192.168.178.153", pollingInterval=30 ]
```

### tapocontrol.items:

```
Switch TAPO_SOCKET "socket" { channel="tapocontrol:P100:myTapoBridge:mySocket:actuator#output" }
```
15 changes: 15 additions & 0 deletions bundles/org.openhab.binding.tapocontrol/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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 http://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.2.0-SNAPSHOT</version>
</parent>

<artifactId>org.openhab.binding.tapocontrol</artifactId>
<name>openHAB Add-ons :: Bundles :: TapoControl Binding</name>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.tapocontrol-${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-tapocontrol" description="TapoControl Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.tapocontrol/${project.version}</bundle>
</feature>
</features>
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/**
* Copyright (c) 2010-2021 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.tapocontrol.internal;

import static org.openhab.binding.tapocontrol.internal.constants.TapoBindingSettings.*;
import static org.openhab.binding.tapocontrol.internal.constants.TapoThingConstants.*;

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.tapocontrol.internal.device.TapoBridgeHandler;
import org.openhab.binding.tapocontrol.internal.device.TapoLightStrip;
import org.openhab.binding.tapocontrol.internal.device.TapoSmartBulb;
import org.openhab.binding.tapocontrol.internal.device.TapoSmartPlug;
import org.openhab.binding.tapocontrol.internal.device.TapoUniversalDevice;
import org.openhab.core.thing.Bridge;
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.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* The {@link TapoControlHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Christian Wild - Initial contribution
*/
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.tapocontrol")
@NonNullByDefault
public class TapoControlHandlerFactory extends BaseThingHandlerFactory {
private final Logger logger = LoggerFactory.getLogger(TapoControlHandlerFactory.class);
private final Set<TapoBridgeHandler> accountHandlers = new HashSet<>();
private final HttpClient httpClient;

@Activate
public TapoControlHandlerFactory() {
// create new httpClient
httpClient = new HttpClient(new SslContextFactory.Client());
httpClient.setFollowRedirects(false);
httpClient.setMaxConnectionsPerDestination(HTTP_MAX_CONNECTIONS);
httpClient.setMaxRequestsQueuedPerDestination(HTTP_MAX_QUEUED_REQUESTS);
try {
httpClient.start();
} catch (Exception e) {
logger.error("cannot start httpClient");
}
}

@Deactivate
@Override
protected void deactivate(ComponentContext componentContext) {
super.deactivate(componentContext);
try {
httpClient.stop();
} catch (Exception e) {
logger.debug("unable to stop httpClient");
}
}

/**
* Provides the supported thing types
*/
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
if (thingTypeUID.equals(UNIVERSAL_THING_TYPE)) {
return true;
}
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
}

/**
* Create handler of things.
*/
@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();

if (SUPPORTED_BRIDGE_UIDS.contains(thingTypeUID)) {
TapoBridgeHandler bridgeHandler = new TapoBridgeHandler((Bridge) thing, httpClient);
accountHandlers.add(bridgeHandler);
return bridgeHandler;
} else if (SUPPORTED_SMART_PLUG_UIDS.contains(thingTypeUID)) {
return new TapoSmartPlug(thing);
} else if (SUPPORTED_WHITE_BULB_UIDS.contains(thingTypeUID)) {
return new TapoSmartBulb(thing);
} else if (SUPPORTED_COLOR_BULB_UIDS.contains(thingTypeUID)) {
return new TapoSmartBulb(thing);
} else if (SUPPORTED_LIGHT_STRIP_UIDS.contains(thingTypeUID)) {
return new TapoLightStrip(thing);
} else if (thingTypeUID.equals(UNIVERSAL_THING_TYPE)) {
return new TapoUniversalDevice(thing);
}
return null;
}
}
Loading

0 comments on commit 5a39c6d

Please sign in to comment.