[TapoControl] Adding P300 to the list of supported equipments (#14364)

* Adding P300 to the list of supported equipments

Signed-off-by: clinique <gael@lhopital.org>
This commit is contained in:
Gaël L'hopital 2023-02-14 12:09:31 +01:00 committed by GitHub
parent bbb4c3e474
commit 7820c2daa2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 490 additions and 97 deletions

View File

@ -12,6 +12,7 @@ The following Tapo-Devices are supported. For precise channel-description look a
| | P105 | Smart Mini Socket |
| EnergyMonitoring SmartPlug (Wi-Fi) | P110 | Energy Monitoring Smart Socket |
| | P115 | Energy Monitoring Mini Smart Socket |
| Power Strip (Wi-Fi) | P300 | Smart Wi-Fi Power Strip - 3 sockets |
| Dimmable SmartBulb (Wi-Fi) | L510 | Dimmable White-Light Smart-Bulb (E27) |
| | L610 | Dimmable White-Light Smart-Spot (GU10) |
| MultiColor SmartBulb (Wi-Fi) | L530 | Multicolor Smart-Bulb (E27) |
@ -66,6 +67,9 @@ 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, P110, P115, L510, L530, L610, L630, L900, L920, L930 |
| | output1 | Switch | Power socket 1 on or off | P300 |
| | output2 | Switch | Power socket 2 on or off | P300 |
| | output3 | Switch | Power socket 3 on or off | P300 |
| | brightness | Dimmer | Brightness 0-100% | L510, L530, L610, L630, L900 |
| | colorTemperature | Number | White-Color-Temp 2500-6500K | L510, L530, L610, L630, L900 |
| | color | Color | Color | L530, L630, L900 |
@ -94,7 +98,7 @@ tapocontrol:L530:myTapoBridge:colorBulb "color-light" (tapocontrol:bri
tapocontrol:L900:myTapoBridge:myLightStrip "light-strip" (tapocontrol:bridge:myTapoBridge) [ ipAddress="192.168.178.153", pollingInterval=30 ]
Bridge tapocontrol:bridge:secondBridgeExample "Cloud-Login" [ username="youtoo@anyprovider.com", password="verysecret" ] {
Thing tapocontrol:P110:secondBridgeExample:mySocket "My-Socket" [ ipAddress="192.168.101.51", pollingInterval=30 ]
Thing P110 mySocket "My-Socket" [ ipAddress="192.168.101.51", pollingInterval=30 ]
}
```

View File

@ -15,22 +15,26 @@ package org.openhab.binding.tapocontrol.internal.api;
import static org.openhab.binding.tapocontrol.internal.constants.TapoBindingSettings.*;
import static org.openhab.binding.tapocontrol.internal.constants.TapoErrorConstants.*;
import static org.openhab.binding.tapocontrol.internal.constants.TapoThingConstants.*;
import static org.openhab.binding.tapocontrol.internal.helpers.TapoUtils.*;
import static org.openhab.binding.tapocontrol.internal.helpers.TapoUtils.jsonObjectToInt;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Objects;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.tapocontrol.internal.device.TapoBridgeHandler;
import org.openhab.binding.tapocontrol.internal.device.TapoDevice;
import org.openhab.binding.tapocontrol.internal.helpers.PayloadBuilder;
import org.openhab.binding.tapocontrol.internal.helpers.TapoErrorHandler;
import org.openhab.binding.tapocontrol.internal.structures.TapoChild;
import org.openhab.binding.tapocontrol.internal.structures.TapoChildData;
import org.openhab.binding.tapocontrol.internal.structures.TapoDeviceInfo;
import org.openhab.binding.tapocontrol.internal.structures.TapoEnergyData;
import org.openhab.binding.tapocontrol.internal.structures.TapoSubRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
/**
@ -41,12 +45,12 @@ import com.google.gson.JsonObject;
*/
@NonNullByDefault
public class TapoDeviceConnector extends TapoDeviceHttpApi {
private final Logger logger = LoggerFactory.getLogger(TapoDeviceConnector.class);
private final String uid;
private final TapoDevice device;
private TapoDeviceInfo deviceInfo;
private TapoEnergyData energyData;
private Gson gson;
private TapoDeviceInfo deviceInfo = new TapoDeviceInfo();
private TapoEnergyData energyData = new TapoEnergyData();
private TapoChildData childData = new TapoChildData();
private long lastQuery = 0L;
private long lastSent = 0L;
private long lastLogin = 0L;
@ -58,11 +62,6 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
*/
public TapoDeviceConnector(TapoDevice device, TapoBridgeHandler bridgeThingHandler) {
super(device, bridgeThingHandler);
this.device = device;
this.gson = new Gson();
this.deviceInfo = new TapoDeviceInfo();
this.energyData = new TapoEnergyData();
this.uid = device.getThingUID().getAsString();
}
/***********************************
@ -159,6 +158,27 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
}
}
/**
* send "set_device_info" command to child's device
*
* @param index of the child
* @param childProperty to modify
* @param value for the property
*/
public void sendChildCommand(Integer index, String childProperty, Object value) {
long now = System.currentTimeMillis();
if (now > this.lastSent + TAPO_SEND_MIN_GAP_MS) {
this.lastSent = now;
getChild(index).ifPresent(child -> {
child.setDeviceOn(Boolean.valueOf((Boolean) value));
TapoSubRequest request = new TapoSubRequest(child.getDeviceId(), DEVICE_CMD_SETINFO, child);
sendSecurePasstrhroug(GSON.toJson(request), request.method());
});
} else {
logger.debug("({}) command not sent because of min_gap: {}", uid, now + " <- " + lastSent);
}
}
/**
* send multiple "set_device_info" commands to device
*
@ -184,14 +204,15 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
}
/**
* Query Info from Device adn refresh deviceInfo
* Query Info from Device and refresh deviceInfo
*/
public void queryInfo() {
queryInfo(false);
queryChildDevices();
}
/**
* Query Info from Device adn refresh deviceInfo
* Query Info from Device and refresh deviceInfo
*
* @param ignoreGap ignore gap to last query. query anyway
*/
@ -212,6 +233,21 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
}
}
/**
* Query Info from Child Devices and refresh deviceInfo
*/
@Override
public void queryChildDevices() {
logger.trace("({}) DeviceConnetor_queryChildDevices from '{}'", uid, deviceURL);
/* create payload */
PayloadBuilder plBuilder = new PayloadBuilder();
plBuilder.method = DEVICE_CMD_CHILD_DEVICE_LIST;
String payload = plBuilder.getPayload();
sendSecurePasstrhroug(payload, DEVICE_CMD_CHILD_DEVICE_LIST);
}
/**
* Get energy usage from device
*/
@ -305,6 +341,23 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
this.device.responsePasstrough(responseBody);
}
/**
* handle JsonResponse (getChildDeviceList)
*
* @param responseBody String with responseBody from device
*/
@Override
protected void handleChildDevices(String responseBody) {
JsonObject jsnResult = getJsonFromResponse(responseBody);
if (jsnResult.has(CHILD_PROPERTY_START_INDEX)) {
this.childData = Objects.requireNonNull(GSON.fromJson(jsnResult, TapoChildData.class));
this.device.setChildData(childData);
} else {
this.childData = new TapoChildData();
}
this.device.responsePasstrough(responseBody);
}
/**
* handle custom response
*
@ -332,13 +385,13 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
* @return JsonObject with result
*/
private JsonObject getJsonFromResponse(String responseBody) {
JsonObject jsonObject = gson.fromJson(responseBody, JsonObject.class);
JsonObject jsonObject = GSON.fromJson(responseBody, JsonObject.class);
/* get errocode (0=success) */
if (jsonObject != null) {
Integer errorCode = jsonObjectToInt(jsonObject, "error_code");
if (errorCode == 0) {
/* decrypt response */
jsonObject = gson.fromJson(responseBody, JsonObject.class);
jsonObject = GSON.fromJson(responseBody, JsonObject.class);
logger.trace("({}) received result: {}", uid, responseBody);
if (jsonObject != null) {
/* return result if set / else request was successful */
@ -418,4 +471,8 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
return false;
}
}
private Optional<TapoChild> getChild(int position) {
return childData.getChildDeviceList().stream().filter(child -> child.getPosition() == position).findFirst();
}
}

View File

@ -36,7 +36,9 @@ import org.openhab.binding.tapocontrol.internal.helpers.TapoErrorHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
/**
@ -47,11 +49,15 @@ import com.google.gson.JsonObject;
*/
@NonNullByDefault
public class TapoDeviceHttpApi {
protected static final Gson GSON = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
private final Logger logger = LoggerFactory.getLogger(TapoDeviceHttpApi.class);
private final String uid;
private final TapoCipher tapoCipher;
private final TapoBridgeHandler bridge;
private Gson gson;
protected final String uid;
protected final TapoDevice device;
private String token = "";
private String cookie = "";
protected String deviceURL = "";
@ -65,10 +71,9 @@ public class TapoDeviceHttpApi {
public TapoDeviceHttpApi(TapoDevice device, TapoBridgeHandler bridgeThingHandler) {
this.bridge = bridgeThingHandler;
this.tapoCipher = new TapoCipher();
this.gson = new Gson();
this.device = device;
this.uid = device.getThingUID().getAsString();
String ipAddress = device.getIpAddress();
setDeviceURL(ipAddress);
setDeviceURL(device.getIpAddress());
}
/***********************************
@ -109,6 +114,14 @@ public class TapoDeviceHttpApi {
protected void handleCustomResponse(String responseBody) {
}
/**
* handle JsonResponse (getChildDevices)
*
* @param responseBody String with responseBody from device
*/
protected void handleChildDevices(String responseBody) {
}
/**
* handle error
*
@ -117,6 +130,13 @@ public class TapoDeviceHttpApi {
protected void handleError(TapoErrorHandler tapoError) {
}
/**
* refresh the list of child devices
*
*/
protected void queryChildDevices() {
}
/***********************************
*
* LOGIN FUNCTIONS
@ -160,7 +180,7 @@ public class TapoDeviceHttpApi {
*/
private String getKeyFromResponse(ContentResponse response) {
String rBody = response.getContentAsString();
JsonObject jsonObj = gson.fromJson(rBody, JsonObject.class);
JsonObject jsonObj = GSON.fromJson(rBody, JsonObject.class);
if (jsonObj != null) {
logger.trace("({}) received awnser: {}", uid, rBody);
return jsonObjectToString(jsonObj.getAsJsonObject("result"), "key");
@ -236,7 +256,7 @@ public class TapoDeviceHttpApi {
logger.trace("({}) received result: {}", uid, decryptedResponse);
/* get errocode (0=success) */
JsonObject jsonObject = gson.fromJson(decryptedResponse, JsonObject.class);
JsonObject jsonObject = GSON.fromJson(decryptedResponse, JsonObject.class);
if (jsonObject != null) {
Integer errorCode = jsonObjectToInt(jsonObject, "error_code", ERR_JSON_DECODE_FAIL);
if (errorCode == 0) {
@ -364,6 +384,9 @@ public class TapoDeviceHttpApi {
case DEVICE_CMD_CUSTOM:
handleCustomResponse(rBody);
break;
case DEVICE_CMD_CHILD_DEVICE_LIST:
handleChildDevices(rBody);
break;
}
} else {
getErrorCode(rBody);
@ -403,7 +426,7 @@ public class TapoDeviceHttpApi {
*/
protected Integer getErrorCode(String responseBody) {
try {
JsonObject jsonObject = gson.fromJson(responseBody, JsonObject.class);
JsonObject jsonObject = GSON.fromJson(responseBody, JsonObject.class);
/* get errocode (0=success) */
Integer errorCode = jsonObjectToInt(jsonObject, "error_code", ERR_JSON_DECODE_FAIL);
if (errorCode == 0) {
@ -426,7 +449,7 @@ public class TapoDeviceHttpApi {
*/
protected Boolean hasErrorCode(String responseBody) {
if (isValidJson(responseBody)) {
JsonObject jsonObject = gson.fromJson(responseBody, JsonObject.class);
JsonObject jsonObject = GSON.fromJson(responseBody, JsonObject.class);
/* get errocode (0=success) */
Integer errorCode = jsonObjectToInt(jsonObject, "error_code", ERR_JSON_DECODE_FAIL);
if (errorCode > 0) {
@ -463,7 +486,7 @@ public class TapoDeviceHttpApi {
*/
protected String decryptResponse(String responseBody) {
try {
JsonObject jsonObject = gson.fromJson(responseBody, JsonObject.class);
JsonObject jsonObject = GSON.fromJson(responseBody, JsonObject.class);
if (jsonObject != null) {
String encryptedResponse = jsonObjectToString(jsonObject.getAsJsonObject("result"), "response");
return tapoCipher.decode(encryptedResponse);

View File

@ -52,5 +52,8 @@ public class TapoBindingSettings {
public static final String DEVICE_CMD_GETINFO = "get_device_info";
public static final String DEVICE_CMD_SETINFO = "set_device_info";
public static final String DEVICE_CMD_GETENERGY = "get_energy_usage";
public static final String DEVICE_CMD_CHILD_DEVICE_LIST = "get_child_device_list";
public static final String DEVICE_CMD_CONTROL_CHILD = "control_child";
public static final String DEVICE_CMD_MULTIPLE_REQ = "multipleRequest";
public static final String DEVICE_CMD_CUSTOM = "custom_command";
}

View File

@ -12,7 +12,7 @@
*/
package org.openhab.binding.tapocontrol.internal.constants;
import static org.openhab.binding.tapocontrol.internal.constants.TapoBindingSettings.*;
import static org.openhab.binding.tapocontrol.internal.constants.TapoBindingSettings.BINDING_ID;
import java.util.Collections;
import java.util.Set;
@ -38,6 +38,7 @@ public class TapoThingConstants {
public static final String DEVICE_P105 = "P105";
public static final String DEVICE_P110 = "P110";
public static final String DEVICE_P115 = "P115";
public static final String DEVICE_P300 = "P300";
public static final String DEVICE_L510 = "L510";
public static final String DEVICE_L530 = "L530";
public static final String DEVICE_L610 = "L610";
@ -50,6 +51,7 @@ public class TapoThingConstants {
/*** LIST OF SUPPORTED DEVICE DESCRIPTIONS ***/
public static final String DEVICE_DESCRIPTION_BRIDGE = "TapoControl Cloud-Login";
public static final String DEVICE_DESCRIPTION_SMART_PLUG = "SmartPlug";
public static final String DEVICE_DESCRIPTION_POWER_STRIP = "PowerStrip";
public static final String DEVICE_DESCRIPTION_WHITE_BULB = "White-Light-Bulb";
public static final String DEVICE_DESCRIPTION_COLOR_BULB = "Color-Light-Bulb";
public static final String DEVICE_DESCRIPTION_LIGHTSTRIP = "LightStrip";
@ -60,6 +62,7 @@ public class TapoThingConstants {
public static final ThingTypeUID P105_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_P105);
public static final ThingTypeUID P110_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_P110);
public static final ThingTypeUID P115_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_P115);
public static final ThingTypeUID P300_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_P300);
public static final ThingTypeUID L510_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_L510);
public static final ThingTypeUID L530_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_L530);
public static final ThingTypeUID L610_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_L610);
@ -72,7 +75,7 @@ public class TapoThingConstants {
/*** SET OF SUPPORTED UIDS ***/
public static final Set<ThingTypeUID> SUPPORTED_BRIDGE_UIDS = Set.of(BRIDGE_THING_TYPE);
public static final Set<ThingTypeUID> SUPPORTED_SMART_PLUG_UIDS = Set.of(P100_THING_TYPE, P105_THING_TYPE,
P110_THING_TYPE, P115_THING_TYPE);
P110_THING_TYPE, P115_THING_TYPE, P300_THING_TYPE);
public static final Set<ThingTypeUID> SUPPORTED_WHITE_BULB_UIDS = Set.of(L510_THING_TYPE, L610_THING_TYPE);
public static final Set<ThingTypeUID> SUPPORTED_COLOR_BULB_UIDS = Set.of(L530_THING_TYPE, L630_THING_TYPE);
public static final Set<ThingTypeUID> SUPPORTED_LIGHT_STRIP_UIDS = Set.of(L900_THING_TYPE, L920_THING_TYPE,
@ -85,6 +88,9 @@ public class TapoThingConstants {
/*** THINGS WITH ENERGY DATA ***/
public static final Set<ThingTypeUID> SUPPORTED_ENERGY_DATA_UIDS = Set.of(P110_THING_TYPE, P115_THING_TYPE);
/*** THINGS WITH CHILDS DATA ***/
public static final Set<ThingTypeUID> SUPPORTED_CHILDS_DATA_UIDS = Set.of(P300_THING_TYPE);
/*** THINGS WITH CHANNEL GROUPS ***/
public static final Set<ThingTypeUID> CHANNEL_GROUP_THING_SET = Collections
.unmodifiableSet(Stream
@ -146,6 +152,8 @@ public class TapoThingConstants {
public static final String ENERGY_PROPERTY_PAST7D = "past7d";
public static final String ENERGY_PROPERTY_PAST30D = "past30d";
public static final String ENERGY_PROPERTY_PAST1Y = "past1y";
// childs management
public static final String CHILD_PROPERTY_START_INDEX = "start_index";
/*** DEVICE SETTINGS ***/
public static final Integer BULB_MIN_COLORTEMP = 2500;

View File

@ -26,6 +26,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.tapocontrol.internal.api.TapoDeviceConnector;
import org.openhab.binding.tapocontrol.internal.helpers.TapoErrorHandler;
import org.openhab.binding.tapocontrol.internal.structures.TapoChildData;
import org.openhab.binding.tapocontrol.internal.structures.TapoDeviceConfiguration;
import org.openhab.binding.tapocontrol.internal.structures.TapoDeviceInfo;
import org.openhab.binding.tapocontrol.internal.structures.TapoEnergyData;
@ -326,6 +327,10 @@ public abstract class TapoDevice extends BaseThingHandler {
if (SUPPORTED_ENERGY_DATA_UIDS.contains(getThing().getThingTypeUID())) {
connector.getEnergyUsage();
}
// query childs data
if (SUPPORTED_CHILDS_DATA_UIDS.contains(getThing().getThingTypeUID())) {
connector.queryChildDevices();
}
} else {
logger.debug("({}) tried to query DeviceInfo but not loggedIn", uid);
connect();
@ -363,6 +368,18 @@ public abstract class TapoDevice extends BaseThingHandler {
getTimeType(energyData.getTodayRuntime(), Units.MINUTE));
}
/**
* Set Device Child data to device
*
* @param energyData
*/
public void setChildData(TapoChildData hostData) {
hostData.getChildDeviceList().forEach(child -> {
publishState(getChannelID(CHANNEL_GROUP_ACTUATOR, CHANNEL_OUTPUT + Integer.toString(child.getPosition())),
getOnOffType(child.getDeviceOn()));
});
}
/**
* Handle full responsebody received from connector
*

View File

@ -52,20 +52,24 @@ public class TapoSmartPlug extends TapoDevice {
*/
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
Boolean refreshInfo = false;
boolean refreshInfo = false;
String id = channelUID.getIdWithoutGroup();
/* perform actions */
if (command instanceof RefreshType) {
refreshInfo = true;
} else if (command == OnOffType.ON) {
connector.sendDeviceCommand(DEVICE_PROPERTY_ON, true);
refreshInfo = true;
} else if (command == OnOffType.OFF) {
connector.sendDeviceCommand(DEVICE_PROPERTY_ON, false);
refreshInfo = true;
} else if (command instanceof OnOffType) {
Boolean targetState = command == OnOffType.ON ? Boolean.TRUE : Boolean.FALSE;
if (CHANNEL_OUTPUT.equals(id)) { // Command is sent to the device output
connector.sendDeviceCommand(DEVICE_PROPERTY_ON, targetState);
refreshInfo = true;
} else if (id.startsWith(CHANNEL_OUTPUT)) { // Command is sent to a child's device output
Integer index = Integer.valueOf(id.replace(CHANNEL_OUTPUT, ""));
connector.sendChildCommand(index, DEVICE_PROPERTY_ON, targetState);
refreshInfo = true;
}
} else {
logger.warn("({}) command type '{}' not supported for channel '{}'", uid, command.toString(),
channelUID.getId());
logger.warn("({}) command type '{}' not supported for channel '{}'", uid, command, channelUID.getId());
}
/* refreshInfo */

View File

@ -87,6 +87,6 @@ public class PayloadBuilder {
* remove all parameters
*/
public void flushParameters(String command) {
this.parameters = new JsonObject();
parameters = new JsonObject();
}
}

View File

@ -0,0 +1,140 @@
/**
* 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.tapocontrol.internal.structures;
import static org.openhab.binding.tapocontrol.internal.constants.TapoBindingSettings.MAC_DIVISION_CHAR;
import static org.openhab.binding.tapocontrol.internal.helpers.TapoUtils.formatMac;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Tapo Child Device Information class
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class TapoChild {
private String fwVer = "";
private String hwVer = "";
private String type = "";
private String model = "";
private String mac = "";
private String category = "";
private String deviceId = "";
private boolean overheatStatus = false;
private int bindCount = 0;
private long onTime = 0;
private int slotNumber = 0;
private int position = 0;
private String nickname = "";
private boolean deviceOn = false;
private String region = "";
/***********************************
*
* GET VALUES
*
************************************/
public String getFirmwareVersion() {
return fwVer;
}
public String getHardwareVersion() {
return hwVer;
}
public Boolean isOff() {
return !deviceOn;
}
public Boolean isOn() {
return deviceOn;
}
public String getMAC() {
return formatMac(mac, MAC_DIVISION_CHAR);
}
public String getModel() {
return model.replace(" Series", "");
}
public String getNickname() {
return nickname;
}
public Number getOnTime() {
return onTime;
}
public String getRegion() {
return region;
}
public String getRepresentationProperty() {
return getMAC();
}
public String getSerial() {
return deviceId;
}
public String getType() {
return type;
}
public String getFwVer() {
return fwVer;
}
public String getHwVer() {
return hwVer;
}
public String getMac() {
return mac;
}
public String getCategory() {
return category;
}
public String getDeviceId() {
return deviceId;
}
public Boolean getOverheatStatus() {
return overheatStatus;
}
public Integer getBindCount() {
return bindCount;
}
public Integer getSlotNumber() {
return slotNumber;
}
public Integer getPosition() {
return position;
}
public Boolean getDeviceOn() {
return deviceOn;
}
public void setDeviceOn(Boolean deviceOn) {
this.deviceOn = deviceOn;
}
}

View File

@ -0,0 +1,41 @@
/**
* 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.tapocontrol.internal.structures;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Tapo-Child Structure Class
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class TapoChildData {
private int startIndex = 0;
private int sum = 0;
private List<TapoChild> childDeviceList = List.of();
public int getStartIndex() {
return startIndex;
}
public int getSum() {
return sum;
}
public List<TapoChild> getChildDeviceList() {
return childDeviceList;
}
}

View File

@ -0,0 +1,44 @@
/**
* 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.tapocontrol.internal.structures;
import static org.openhab.binding.tapocontrol.internal.constants.TapoBindingSettings.*;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import com.google.gson.annotations.SerializedName;
/**
* {@TapoSubRequest} holds data sent to device in order to act on a child
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public record TapoSubRequest(String method, Object params) {
private record ChildRequest(String device_id, @SerializedName("requestData") TapoSubRequest requestData) {
}
private record SubMultiple(List<TapoSubRequest> requests) {
private SubMultiple(String method, TapoChild params) {
this(List.of(new TapoSubRequest(method, params)));
}
}
public TapoSubRequest(String deviceId, String method, TapoChild params) {
this(DEVICE_CMD_CONTROL_CHILD, new ChildRequest(deviceId,
new TapoSubRequest(DEVICE_CMD_MULTIPLE_REQ, new SubMultiple(method, params))));
}
}

View File

@ -27,6 +27,8 @@ thing-type.tapocontrol.P110.label = P110 SmartPlug
thing-type.tapocontrol.P110.description = Tapo Smart Monitoring Wifi Plug
thing-type.tapocontrol.P115.label = P115 SmartPlug
thing-type.tapocontrol.P115.description = Tapo Smart Monitoring Wifi Plug
thing-type.tapocontrol.P300.label = P300 Power Strip
thing-type.tapocontrol.P300.description = Tapo Smart Wi-Fi Power Strip
thing-type.tapocontrol.bridge.label = Cloud-Login
thing-type.tapocontrol.bridge.description = Cloud Connector. Acts as device-bridge
@ -60,6 +62,14 @@ channel-group-type.tapocontrol.lightEffect.label = Lightning Effect
channel-group-type.tapocontrol.lightEffect.description = Tapo Lightning Effects
channel-group-type.tapocontrol.lightStrip.label = Color Light Strip
channel-group-type.tapocontrol.lightStrip.description = Tapo Multicolor Smart Light Strip
channel-group-type.tapocontrol.powerStrip.label = SmartPlug
channel-group-type.tapocontrol.powerStrip.description = Tapo Smart Plug Power Outlet
channel-group-type.tapocontrol.powerStrip.channel.output1.label = Output Switch 1
channel-group-type.tapocontrol.powerStrip.channel.output1.description = Switches the power state on/off of the first socket
channel-group-type.tapocontrol.powerStrip.channel.output2.label = Output Switch 2
channel-group-type.tapocontrol.powerStrip.channel.output2.description = Switches the power state on/off of the second socket
channel-group-type.tapocontrol.powerStrip.channel.output3.label = Output Switch 3
channel-group-type.tapocontrol.powerStrip.channel.output3.description = Switches the power state on/off of the third socket
channel-group-type.tapocontrol.smartPlug.label = SmartPlug
channel-group-type.tapocontrol.smartPlug.description = Tapo Smart Plug Power Outlet

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="tapocontrol"
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">
<!-- P300 THING-TYPE (POWER STRIP) -->
<thing-type id="P300">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>
<label>P300 Power Strip</label>
<description>Tapo Smart Wi-Fi Power Strip</description>
<channel-groups>
<channel-group id="actuator" typeId="powerStrip"/>
<channel-group id="device" typeId="deviceState"/>
</channel-groups>
<representation-property>macAddress</representation-property>
<config-description-ref uri="thing-type:tapo:device"/>
</thing-type>
</thing:thing-descriptions>

View File

@ -37,6 +37,25 @@
</channels>
</channel-group-type>
<channel-group-type id="powerStrip">
<label>SmartPlug</label>
<description>Tapo Smart Plug Power Outlet</description>
<channels>
<channel id="output1" typeId="outputChannel">
<label>Output Switch 1</label>
<description>Switches the power state on/off of the first socket</description>
</channel>
<channel id="output2" typeId="outputChannel">
<label>Output Switch 2</label>
<description>Switches the power state on/off of the second socket</description>
</channel>
<channel id="output3" typeId="outputChannel">
<label>Output Switch 3</label>
<description>Switches the power state on/off of the third socket</description>
</channel>
</channels>
</channel-group-type>
<!--Light-Bulb Channel Type -->
<channel-group-type id="lightBulb">
<label>Light Bulb</label>