Skip to content

Commit 2f2cf22

Browse files
authored
[tapocontrol] Add Smart Switches S210 and S220 (openhab#17927)
* Tapo Smart Switches S210 and S220 added Signed-off-by: mkmannmanny <[email protected]> Signed-off-by: Manfred Krämer <[email protected]>
1 parent 0e5e48f commit 2f2cf22

File tree

9 files changed

+156
-17
lines changed

9 files changed

+156
-17
lines changed

bundles/org.openhab.binding.tapocontrol/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ The following Tapo-Devices are supported. For precise channel-description look a
2424
| Smart Contact Sensor (RF) | T110 | Window/Door Smart Contact Sensor |
2525
| Smart Temperature Sensor (RF) | T310 | Temperature and Humidity Sensor |
2626
| | T315 | Temperature and Humidity Sensor with Display |
27+
| Smart Switch (RF) | S210 | Wall switch with 1 contact |
28+
| Smart Switch (RF) | S220 | Wall switch with 2 contacts |
2729

2830
## Prerequisites
2931

bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoControlHandlerFactory.java

+3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.eclipse.jetty.util.ssl.SslContextFactory;
2525
import org.openhab.binding.tapocontrol.internal.devices.bridge.TapoBridgeHandler;
2626
import org.openhab.binding.tapocontrol.internal.devices.rf.smartcontact.TapoSmartContactHandler;
27+
import org.openhab.binding.tapocontrol.internal.devices.rf.smartswitch.TapoSmartSwitchHandler;
2728
import org.openhab.binding.tapocontrol.internal.devices.rf.weathersensor.TapoWeatherSensorHandler;
2829
import org.openhab.binding.tapocontrol.internal.devices.wifi.TapoUniversalDeviceHandler;
2930
import org.openhab.binding.tapocontrol.internal.devices.wifi.bulb.TapoBulbHandler;
@@ -130,6 +131,8 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
130131
return new TapoSmartContactHandler(thing);
131132
} else if (SUPPORTED_WEATHER_SENSORS.contains(thingTypeUID)) {
132133
return new TapoWeatherSensorHandler(thing);
134+
} else if (SUPPORTED_SMART_SWITCHES.contains(thingTypeUID)) {
135+
return new TapoSmartSwitchHandler(thing);
133136
} else if (thingTypeUID.equals(UNIVERSAL_THING_TYPE)) {
134137
return new TapoUniversalDeviceHandler(thing);
135138
}

bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoThingConstants.java

+15-9
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ public class TapoThingConstants {
5050
public static final String DEVICE_T110 = "T110";
5151
public static final String DEVICE_T310 = "T310";
5252
public static final String DEVICE_T315 = "T315";
53+
public static final String DEVICE_S210 = "S210";
54+
public static final String DEVICE_S220 = "S220";
5355
public static final String DEVICE_UNIVERSAL = "Test_Device";
5456

5557
/*** LIST OF SUPPORTED DEVICE DESCRIPTIONS ***/
@@ -63,6 +65,7 @@ public class TapoThingConstants {
6365
public static final String DEVICE_DESCRIPTION_SMART_CONTACT = "Smart-Contact-Sensor";
6466
public static final String DEVICE_DESCRIPTION_MOTION_SENSOR = "Motion-Sensor";
6567
public static final String DEVICE_DESCRIPTION_TEMP_SENSOR = "Temperature-Sensor";
68+
public static final String DEVICE_DESCRIPTION_SMART_SWITCH = "Smart-Switch";
6669

6770
/*** LIST OF SUPPORTED THING UIDS ***/
6871
public static final ThingTypeUID BRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_BRIDGE);
@@ -85,6 +88,8 @@ public class TapoThingConstants {
8588
public static final ThingTypeUID T110_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_T110);
8689
public static final ThingTypeUID T310_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_T310);
8790
public static final ThingTypeUID T315_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_T315);
91+
public static final ThingTypeUID S210_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_S210);
92+
public static final ThingTypeUID S220_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_S220);
8893

8994
/*** SET OF SUPPORTED UIDS ***/
9095
public static final Set<ThingTypeUID> SUPPORTED_BRIDGE_UIDS = Set.of(BRIDGE_THING_TYPE);
@@ -97,27 +102,28 @@ public class TapoThingConstants {
97102
public static final Set<ThingTypeUID> SUPPORTED_LIGHT_STRIP_UIDS = Set.of(L900_THING_TYPE, L920_THING_TYPE,
98103
L930_THING_TYPE);
99104
public static final Set<ThingTypeUID> SUPPORTED_HUB_CHILD_TYPES_UIDS = Set.of(T110_THING_TYPE, T310_THING_TYPE,
100-
T315_THING_TYPE);
105+
T315_THING_TYPE, S210_THING_TYPE, S220_THING_TYPE);
101106
public static final Set<ThingTypeUID> SUPPORTED_SMART_CONTACTS = Set.of(T110_THING_TYPE);
102107
public static final Set<ThingTypeUID> SUPPORTED_MOTION_SENSORS = Set.of();
103108
public static final Set<ThingTypeUID> SUPPORTED_WEATHER_SENSORS = Set.of(T310_THING_TYPE, T315_THING_TYPE);
109+
public static final Set<ThingTypeUID> SUPPORTED_SMART_SWITCHES = Set.of(S210_THING_TYPE, S220_THING_TYPE);
104110

105111
/*** SET OF ALL SUPPORTED THINGS ***/
106-
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(Stream
107-
.of(SUPPORTED_BRIDGE_UIDS, SUPPORTED_HUB_UIDS, SUPPORTED_SOCKET_UIDS, SUPPORTED_SOCKET_STRIP_UIDS,
112+
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(
113+
Stream.of(SUPPORTED_BRIDGE_UIDS, SUPPORTED_HUB_UIDS, SUPPORTED_SOCKET_UIDS, SUPPORTED_SOCKET_STRIP_UIDS,
108114
SUPPORTED_WHITE_BULB_UIDS, SUPPORTED_COLOR_BULB_UIDS, SUPPORTED_LIGHT_STRIP_UIDS,
109-
SUPPORTED_SMART_CONTACTS, SUPPORTED_MOTION_SENSORS, SUPPORTED_WEATHER_SENSORS)
110-
.flatMap(Set::stream).collect(Collectors.toSet()));
115+
SUPPORTED_SMART_CONTACTS, SUPPORTED_MOTION_SENSORS, SUPPORTED_WEATHER_SENSORS,
116+
SUPPORTED_SMART_SWITCHES).flatMap(Set::stream).collect(Collectors.toSet()));
111117

112118
/*** THINGS WITH ENERGY DATA ***/
113119
public static final Set<ThingTypeUID> SUPPORTED_ENERGY_DATA_UIDS = Set.of(P110_THING_TYPE, P115_THING_TYPE);
114120

115121
/*** THINGS WITH CHANNEL GROUPS ***/
116-
public static final Set<ThingTypeUID> CHANNEL_GROUP_THING_SET = Collections.unmodifiableSet(Stream
117-
.of(SUPPORTED_BRIDGE_UIDS, SUPPORTED_HUB_UIDS, SUPPORTED_SOCKET_UIDS, SUPPORTED_SOCKET_STRIP_UIDS,
122+
public static final Set<ThingTypeUID> CHANNEL_GROUP_THING_SET = Collections.unmodifiableSet(
123+
Stream.of(SUPPORTED_BRIDGE_UIDS, SUPPORTED_HUB_UIDS, SUPPORTED_SOCKET_UIDS, SUPPORTED_SOCKET_STRIP_UIDS,
118124
SUPPORTED_WHITE_BULB_UIDS, SUPPORTED_COLOR_BULB_UIDS, SUPPORTED_LIGHT_STRIP_UIDS,
119-
SUPPORTED_SMART_CONTACTS, SUPPORTED_MOTION_SENSORS, SUPPORTED_WEATHER_SENSORS)
120-
.flatMap(Set::stream).collect(Collectors.toSet()));
125+
SUPPORTED_SMART_CONTACTS, SUPPORTED_MOTION_SENSORS, SUPPORTED_WEATHER_SENSORS,
126+
SUPPORTED_SMART_SWITCHES).flatMap(Set::stream).collect(Collectors.toSet()));
121127

122128
public static final String CHILD_REPRESENTATION_PROPERTY = "serialNumber";
123129

bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/rf/TapoChildDeviceHandler.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
*/
1313
package org.openhab.binding.tapocontrol.internal.devices.rf;
1414

15-
import static org.openhab.binding.tapocontrol.internal.constants.TapoErrorCode.*;
15+
import static org.openhab.binding.tapocontrol.internal.constants.TapoErrorCode.ERR_CONFIG_NO_BRIDGE;
1616
import static org.openhab.binding.tapocontrol.internal.constants.TapoThingConstants.*;
17-
import static org.openhab.binding.tapocontrol.internal.helpers.utils.TapoUtils.*;
17+
import static org.openhab.binding.tapocontrol.internal.helpers.utils.TapoUtils.getValueOrDefault;
1818
import static org.openhab.binding.tapocontrol.internal.helpers.utils.TypeUtils.*;
1919

2020
import java.util.HashMap;
@@ -48,7 +48,7 @@ public abstract class TapoChildDeviceHandler extends BaseThingHandler {
4848
protected final String uid;
4949
protected final String deviceId;
5050
protected @NonNullByDefault({}) TapoHubHandler hub;
51-
private TapoChildDeviceData deviceInfo = new TapoChildDeviceData();
51+
protected TapoChildDeviceData deviceInfo = new TapoChildDeviceData();
5252
private Map<String, Object> oldStates = new HashMap<>();
5353

5454
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/**
2+
* Copyright (c) 2010-2024 Contributors to the openHAB project
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0
10+
*
11+
* SPDX-License-Identifier: EPL-2.0
12+
*/
13+
package org.openhab.binding.tapocontrol.internal.devices.rf.smartswitch;
14+
15+
import static org.openhab.binding.tapocontrol.internal.constants.TapoThingConstants.*;
16+
import static org.openhab.binding.tapocontrol.internal.helpers.utils.TypeUtils.getOnOffType;
17+
18+
import org.eclipse.jdt.annotation.NonNullByDefault;
19+
import org.openhab.binding.tapocontrol.internal.devices.dto.TapoChildDeviceData;
20+
import org.openhab.binding.tapocontrol.internal.devices.rf.TapoChildDeviceHandler;
21+
import org.openhab.core.library.types.OnOffType;
22+
import org.openhab.core.thing.ChannelUID;
23+
import org.openhab.core.thing.Thing;
24+
import org.openhab.core.types.Command;
25+
import org.openhab.core.types.RefreshType;
26+
import org.slf4j.Logger;
27+
import org.slf4j.LoggerFactory;
28+
29+
/**
30+
* TAPO Smart-Contact-Device.
31+
*
32+
* @author Manfred Krämer - Initial contribution
33+
*/
34+
35+
@NonNullByDefault
36+
public class TapoSmartSwitchHandler extends TapoChildDeviceHandler {
37+
38+
private final Logger logger = LoggerFactory.getLogger(TapoSmartSwitchHandler.class);
39+
40+
/**
41+
* Constructor
42+
*
43+
* @param thing Thing object representing device
44+
*/
45+
public TapoSmartSwitchHandler(Thing thing) {
46+
super(thing);
47+
}
48+
49+
/**
50+
* Update properties
51+
*/
52+
@Override
53+
protected void devicePropertiesChanged(TapoChildDeviceData deviceInfo) {
54+
super.devicePropertiesChanged(deviceInfo);
55+
updateState(getChannelID(CHANNEL_GROUP_ACTUATOR, CHANNEL_OUTPUT), getOnOffType(deviceInfo.isOn()));
56+
}
57+
58+
/**
59+
* handle command sent to device
60+
*
61+
* @param channelUID channelUID command is sent to
62+
* @param command command to be sent
63+
*/
64+
@Override
65+
public void handleCommand(ChannelUID channelUID, Command command) {
66+
/* perform actions */
67+
if (command instanceof RefreshType) {
68+
setDeviceData();
69+
} else if (command instanceof OnOffType onOffCommand) {
70+
deviceInfo.setDeviceOn(OnOffType.ON.equals(onOffCommand));
71+
72+
hub.sendCommandToChild(deviceInfo);
73+
} else {
74+
logger.warn("({}) command type '{}' not supported for channel '{}'", uid, command, channelUID.getId());
75+
}
76+
}
77+
}

bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/wifi/hub/TapoHubHandler.java

+10-3
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public Collection<Class<? extends ThingHandlerService>> getServices() {
111111

112112
/**
113113
* Set DiscoveryService
114-
*
114+
*
115115
* @param discoveryService
116116
*/
117117
public void setDiscoveryService(TapoChildDiscoveryService discoveryService) {
@@ -140,7 +140,7 @@ public void queryDeviceData() {
140140
/**
141141
* Function called by {@link org.openhab.binding.tapocontrol.internal.api.TapoDeviceConnector} if new data were
142142
* received
143-
*
143+
*
144144
* @param queryCommand command where new data belong to
145145
*/
146146
@Override
@@ -165,6 +165,13 @@ public void newDataResult(String queryCommand) {
165165
* CHILD THINGS
166166
****************************/
167167

168+
/****************************
169+
* Send Command to Child
170+
*/
171+
public void sendCommandToChild(TapoChildDeviceData childData) {
172+
connector.sendChildCommand(childData, false);
173+
}
174+
168175
/**
169176
* Update all Child-Things
170177
*/
@@ -276,7 +283,7 @@ public List<TapoChildDeviceData> getChildDevices() {
276283

277284
public TapoChildDeviceData getChild(String deviceSerial) {
278285
List<TapoChildDeviceData> childDeviceList = tapoChildsList.getChildDeviceList();
279-
for (int i = 0; i <= childDeviceList.size(); i++) {
286+
for (int i = 0; i < childDeviceList.size(); i++) {
280287
TapoChildDeviceData child = childDeviceList.get(i);
281288
if (child.getDeviceId().equals(deviceSerial)) {
282289
return child;

bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/discovery/TapoChildDiscoveryService.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
import static org.openhab.binding.tapocontrol.internal.constants.TapoBindingSettings.*;
1616
import static org.openhab.binding.tapocontrol.internal.constants.TapoThingConstants.*;
17-
import static org.openhab.binding.tapocontrol.internal.helpers.utils.TapoUtils.*;
17+
import static org.openhab.binding.tapocontrol.internal.helpers.utils.TapoUtils.formatMac;
1818

1919
import java.util.HashMap;
2020
import java.util.List;
@@ -55,7 +55,7 @@ public class TapoChildDiscoveryService extends AbstractDiscoveryService implemen
5555

5656
/**
5757
* INIT CLASS
58-
*
58+
*
5959
*/
6060
public TapoChildDiscoveryService() {
6161
super(SUPPORTED_HUB_CHILD_TYPES_UIDS, TAPO_DISCOVERY_TIMEOUT_S, false);
@@ -195,6 +195,8 @@ protected String getDeviceLabel(TapoChildDeviceData child) {
195195
deviceLabel = DEVICE_DESCRIPTION_SMART_CONTACT;
196196
} else if (SUPPORTED_MOTION_SENSORS.contains(deviceUID)) {
197197
deviceLabel = DEVICE_DESCRIPTION_MOTION_SENSOR;
198+
} else if (SUPPORTED_SMART_SWITCHES.contains(deviceUID)) {
199+
deviceLabel = DEVICE_DESCRIPTION_SMART_SWITCH;
198200
}
199201
return DEVICE_VENDOR + " " + deviceModel + " " + deviceLabel;
200202
} catch (Exception e) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<thing:thing-descriptions bindingId="tapocontrol"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
5+
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
6+
7+
<!--S210 THING-TYPE (SMART SWITCH) -->
8+
<thing-type id="S210">
9+
<supported-bridge-type-refs>
10+
<bridge-type-ref id="H100"/>
11+
</supported-bridge-type-refs>
12+
13+
<label>S210 Smart Switch</label>
14+
<description>Tapo Smart Switch</description>
15+
<channel-groups>
16+
<channel-group id="actuator" typeId="smartPlug"/>
17+
<channel-group id="device" typeId="childDeviceState"/>
18+
</channel-groups>
19+
<representation-property>serialNumber</representation-property>
20+
</thing-type>
21+
</thing:thing-descriptions>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<thing:thing-descriptions bindingId="tapocontrol"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
5+
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
6+
7+
<!--S220 THING-TYPE (SMART SWITCH) -->
8+
<thing-type id="S220">
9+
<supported-bridge-type-refs>
10+
<bridge-type-ref id="H100"/>
11+
</supported-bridge-type-refs>
12+
13+
<label>S220 Smart Switch</label>
14+
<description>Tapo Smart Switch</description>
15+
<channel-groups>
16+
<channel-group id="actuator" typeId="smartPlug"/>
17+
<channel-group id="device" typeId="childDeviceState"/>
18+
</channel-groups>
19+
<representation-property>serialNumber</representation-property>
20+
</thing-type>
21+
</thing:thing-descriptions>

0 commit comments

Comments
 (0)