diff --git a/bundles/org.openhab.binding.tapocontrol/README.md b/bundles/org.openhab.binding.tapocontrol/README.md index 5c335bd77b62f..6e4a516fe9f51 100644 --- a/bundles/org.openhab.binding.tapocontrol/README.md +++ b/bundles/org.openhab.binding.tapocontrol/README.md @@ -24,6 +24,8 @@ The following Tapo-Devices are supported. For precise channel-description look a | Smart Contact Sensor (RF) | T110 | Window/Door Smart Contact Sensor | | Smart Temperature Sensor (RF) | T310 | Temperature and Humidity Sensor | | | T315 | Temperature and Humidity Sensor with Display | +| Smart Switch (RF) | S210 | Wall switch with 1 contact | +| Smart Switch (RF) | S220 | Wall switch with 2 contacts | ## Prerequisites diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoControlHandlerFactory.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoControlHandlerFactory.java index 8725f7a8b7210..5f496d692b2da 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoControlHandlerFactory.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/TapoControlHandlerFactory.java @@ -24,6 +24,7 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; import org.openhab.binding.tapocontrol.internal.devices.bridge.TapoBridgeHandler; import org.openhab.binding.tapocontrol.internal.devices.rf.smartcontact.TapoSmartContactHandler; +import org.openhab.binding.tapocontrol.internal.devices.rf.smartswitch.TapoSmartSwitchHandler; import org.openhab.binding.tapocontrol.internal.devices.rf.weathersensor.TapoWeatherSensorHandler; import org.openhab.binding.tapocontrol.internal.devices.wifi.TapoUniversalDeviceHandler; import org.openhab.binding.tapocontrol.internal.devices.wifi.bulb.TapoBulbHandler; @@ -130,6 +131,8 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { return new TapoSmartContactHandler(thing); } else if (SUPPORTED_WEATHER_SENSORS.contains(thingTypeUID)) { return new TapoWeatherSensorHandler(thing); + } else if (SUPPORTED_SMART_SWITCHES.contains(thingTypeUID)) { + return new TapoSmartSwitchHandler(thing); } else if (thingTypeUID.equals(UNIVERSAL_THING_TYPE)) { return new TapoUniversalDeviceHandler(thing); } diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoThingConstants.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoThingConstants.java index 73bf50bb22ae0..7db0caebb7018 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoThingConstants.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoThingConstants.java @@ -50,6 +50,8 @@ public class TapoThingConstants { public static final String DEVICE_T110 = "T110"; public static final String DEVICE_T310 = "T310"; public static final String DEVICE_T315 = "T315"; + public static final String DEVICE_S210 = "S210"; + public static final String DEVICE_S220 = "S220"; public static final String DEVICE_UNIVERSAL = "Test_Device"; /*** LIST OF SUPPORTED DEVICE DESCRIPTIONS ***/ @@ -63,6 +65,7 @@ public class TapoThingConstants { public static final String DEVICE_DESCRIPTION_SMART_CONTACT = "Smart-Contact-Sensor"; public static final String DEVICE_DESCRIPTION_MOTION_SENSOR = "Motion-Sensor"; public static final String DEVICE_DESCRIPTION_TEMP_SENSOR = "Temperature-Sensor"; + public static final String DEVICE_DESCRIPTION_SMART_SWITCH = "Smart-Switch"; /*** LIST OF SUPPORTED THING UIDS ***/ public static final ThingTypeUID BRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_BRIDGE); @@ -85,6 +88,8 @@ public class TapoThingConstants { public static final ThingTypeUID T110_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_T110); public static final ThingTypeUID T310_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_T310); public static final ThingTypeUID T315_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_T315); + public static final ThingTypeUID S210_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_S210); + public static final ThingTypeUID S220_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_S220); /*** SET OF SUPPORTED UIDS ***/ public static final Set SUPPORTED_BRIDGE_UIDS = Set.of(BRIDGE_THING_TYPE); @@ -97,27 +102,28 @@ public class TapoThingConstants { public static final Set SUPPORTED_LIGHT_STRIP_UIDS = Set.of(L900_THING_TYPE, L920_THING_TYPE, L930_THING_TYPE); public static final Set SUPPORTED_HUB_CHILD_TYPES_UIDS = Set.of(T110_THING_TYPE, T310_THING_TYPE, - T315_THING_TYPE); + T315_THING_TYPE, S210_THING_TYPE, S220_THING_TYPE); public static final Set SUPPORTED_SMART_CONTACTS = Set.of(T110_THING_TYPE); public static final Set SUPPORTED_MOTION_SENSORS = Set.of(); public static final Set SUPPORTED_WEATHER_SENSORS = Set.of(T310_THING_TYPE, T315_THING_TYPE); + public static final Set SUPPORTED_SMART_SWITCHES = Set.of(S210_THING_TYPE, S220_THING_TYPE); /*** SET OF ALL SUPPORTED THINGS ***/ - public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(Stream - .of(SUPPORTED_BRIDGE_UIDS, SUPPORTED_HUB_UIDS, SUPPORTED_SOCKET_UIDS, SUPPORTED_SOCKET_STRIP_UIDS, + public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet( + Stream.of(SUPPORTED_BRIDGE_UIDS, SUPPORTED_HUB_UIDS, SUPPORTED_SOCKET_UIDS, SUPPORTED_SOCKET_STRIP_UIDS, SUPPORTED_WHITE_BULB_UIDS, SUPPORTED_COLOR_BULB_UIDS, SUPPORTED_LIGHT_STRIP_UIDS, - SUPPORTED_SMART_CONTACTS, SUPPORTED_MOTION_SENSORS, SUPPORTED_WEATHER_SENSORS) - .flatMap(Set::stream).collect(Collectors.toSet())); + SUPPORTED_SMART_CONTACTS, SUPPORTED_MOTION_SENSORS, SUPPORTED_WEATHER_SENSORS, + SUPPORTED_SMART_SWITCHES).flatMap(Set::stream).collect(Collectors.toSet())); /*** THINGS WITH ENERGY DATA ***/ public static final Set SUPPORTED_ENERGY_DATA_UIDS = Set.of(P110_THING_TYPE, P115_THING_TYPE); /*** THINGS WITH CHANNEL GROUPS ***/ - public static final Set CHANNEL_GROUP_THING_SET = Collections.unmodifiableSet(Stream - .of(SUPPORTED_BRIDGE_UIDS, SUPPORTED_HUB_UIDS, SUPPORTED_SOCKET_UIDS, SUPPORTED_SOCKET_STRIP_UIDS, + public static final Set CHANNEL_GROUP_THING_SET = Collections.unmodifiableSet( + Stream.of(SUPPORTED_BRIDGE_UIDS, SUPPORTED_HUB_UIDS, SUPPORTED_SOCKET_UIDS, SUPPORTED_SOCKET_STRIP_UIDS, SUPPORTED_WHITE_BULB_UIDS, SUPPORTED_COLOR_BULB_UIDS, SUPPORTED_LIGHT_STRIP_UIDS, - SUPPORTED_SMART_CONTACTS, SUPPORTED_MOTION_SENSORS, SUPPORTED_WEATHER_SENSORS) - .flatMap(Set::stream).collect(Collectors.toSet())); + SUPPORTED_SMART_CONTACTS, SUPPORTED_MOTION_SENSORS, SUPPORTED_WEATHER_SENSORS, + SUPPORTED_SMART_SWITCHES).flatMap(Set::stream).collect(Collectors.toSet())); public static final String CHILD_REPRESENTATION_PROPERTY = "serialNumber"; diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/rf/TapoChildDeviceHandler.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/rf/TapoChildDeviceHandler.java index 6ec04a8374f06..3f7990cd493b9 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/rf/TapoChildDeviceHandler.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/rf/TapoChildDeviceHandler.java @@ -12,9 +12,9 @@ */ package org.openhab.binding.tapocontrol.internal.devices.rf; -import static org.openhab.binding.tapocontrol.internal.constants.TapoErrorCode.*; +import static org.openhab.binding.tapocontrol.internal.constants.TapoErrorCode.ERR_CONFIG_NO_BRIDGE; import static org.openhab.binding.tapocontrol.internal.constants.TapoThingConstants.*; -import static org.openhab.binding.tapocontrol.internal.helpers.utils.TapoUtils.*; +import static org.openhab.binding.tapocontrol.internal.helpers.utils.TapoUtils.getValueOrDefault; import static org.openhab.binding.tapocontrol.internal.helpers.utils.TypeUtils.*; import java.util.HashMap; @@ -48,7 +48,7 @@ public abstract class TapoChildDeviceHandler extends BaseThingHandler { protected final String uid; protected final String deviceId; protected @NonNullByDefault({}) TapoHubHandler hub; - private TapoChildDeviceData deviceInfo = new TapoChildDeviceData(); + protected TapoChildDeviceData deviceInfo = new TapoChildDeviceData(); private Map oldStates = new HashMap<>(); /** diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/rf/smartswitch/TapoSmartSwitchHandler.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/rf/smartswitch/TapoSmartSwitchHandler.java new file mode 100644 index 0000000000000..bde3026939a44 --- /dev/null +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/rf/smartswitch/TapoSmartSwitchHandler.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2010-2024 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.devices.rf.smartswitch; + +import static org.openhab.binding.tapocontrol.internal.constants.TapoThingConstants.*; +import static org.openhab.binding.tapocontrol.internal.helpers.utils.TypeUtils.getOnOffType; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.tapocontrol.internal.devices.dto.TapoChildDeviceData; +import org.openhab.binding.tapocontrol.internal.devices.rf.TapoChildDeviceHandler; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.Thing; +import org.openhab.core.types.Command; +import org.openhab.core.types.RefreshType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * TAPO Smart-Contact-Device. + * + * @author Manfred Krämer - Initial contribution + */ + +@NonNullByDefault +public class TapoSmartSwitchHandler extends TapoChildDeviceHandler { + + private final Logger logger = LoggerFactory.getLogger(TapoSmartSwitchHandler.class); + + /** + * Constructor + * + * @param thing Thing object representing device + */ + public TapoSmartSwitchHandler(Thing thing) { + super(thing); + } + + /** + * Update properties + */ + @Override + protected void devicePropertiesChanged(TapoChildDeviceData deviceInfo) { + super.devicePropertiesChanged(deviceInfo); + updateState(getChannelID(CHANNEL_GROUP_ACTUATOR, CHANNEL_OUTPUT), getOnOffType(deviceInfo.isOn())); + } + + /** + * handle command sent to device + * + * @param channelUID channelUID command is sent to + * @param command command to be sent + */ + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + /* perform actions */ + if (command instanceof RefreshType) { + setDeviceData(); + } else if (command instanceof OnOffType onOffCommand) { + deviceInfo.setDeviceOn(OnOffType.ON.equals(onOffCommand)); + + hub.sendCommandToChild(deviceInfo); + } else { + logger.warn("({}) command type '{}' not supported for channel '{}'", uid, command, channelUID.getId()); + } + } +} diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/wifi/hub/TapoHubHandler.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/wifi/hub/TapoHubHandler.java index 7575d58f60d95..a72fb0d1758f6 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/wifi/hub/TapoHubHandler.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/devices/wifi/hub/TapoHubHandler.java @@ -111,7 +111,7 @@ public Collection> getServices() { /** * Set DiscoveryService - * + * * @param discoveryService */ public void setDiscoveryService(TapoChildDiscoveryService discoveryService) { @@ -140,7 +140,7 @@ public void queryDeviceData() { /** * Function called by {@link org.openhab.binding.tapocontrol.internal.api.TapoDeviceConnector} if new data were * received - * + * * @param queryCommand command where new data belong to */ @Override @@ -165,6 +165,13 @@ public void newDataResult(String queryCommand) { * CHILD THINGS ****************************/ + /**************************** + * Send Command to Child + */ + public void sendCommandToChild(TapoChildDeviceData childData) { + connector.sendChildCommand(childData, false); + } + /** * Update all Child-Things */ @@ -276,7 +283,7 @@ public List getChildDevices() { public TapoChildDeviceData getChild(String deviceSerial) { List childDeviceList = tapoChildsList.getChildDeviceList(); - for (int i = 0; i <= childDeviceList.size(); i++) { + for (int i = 0; i < childDeviceList.size(); i++) { TapoChildDeviceData child = childDeviceList.get(i); if (child.getDeviceId().equals(deviceSerial)) { return child; diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/discovery/TapoChildDiscoveryService.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/discovery/TapoChildDiscoveryService.java index b641fb6ec8ec0..affbc0b6ce07b 100644 --- a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/discovery/TapoChildDiscoveryService.java +++ b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/discovery/TapoChildDiscoveryService.java @@ -14,7 +14,7 @@ import static org.openhab.binding.tapocontrol.internal.constants.TapoBindingSettings.*; import static org.openhab.binding.tapocontrol.internal.constants.TapoThingConstants.*; -import static org.openhab.binding.tapocontrol.internal.helpers.utils.TapoUtils.*; +import static org.openhab.binding.tapocontrol.internal.helpers.utils.TapoUtils.formatMac; import java.util.HashMap; import java.util.List; @@ -55,7 +55,7 @@ public class TapoChildDiscoveryService extends AbstractDiscoveryService implemen /** * INIT CLASS - * + * */ public TapoChildDiscoveryService() { super(SUPPORTED_HUB_CHILD_TYPES_UIDS, TAPO_DISCOVERY_TIMEOUT_S, false); @@ -195,6 +195,8 @@ protected String getDeviceLabel(TapoChildDeviceData child) { deviceLabel = DEVICE_DESCRIPTION_SMART_CONTACT; } else if (SUPPORTED_MOTION_SENSORS.contains(deviceUID)) { deviceLabel = DEVICE_DESCRIPTION_MOTION_SENSOR; + } else if (SUPPORTED_SMART_SWITCHES.contains(deviceUID)) { + deviceLabel = DEVICE_DESCRIPTION_SMART_SWITCH; } return DEVICE_VENDOR + " " + deviceModel + " " + deviceLabel; } catch (Exception e) { diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/S210.xml b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/S210.xml new file mode 100644 index 0000000000000..1b2bbbfa8d3be --- /dev/null +++ b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/S210.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + Tapo Smart Switch + + + + + serialNumber + + diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/S220.xml b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/S220.xml new file mode 100644 index 0000000000000..2d0be894fdca6 --- /dev/null +++ b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/S220.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + Tapo Smart Switch + + + + + serialNumber + +