]> git.basschouten.com Git - openhab-addons.git/commitdiff
[TapoControl] Adding P300 to the list of supported equipments (#14364)
authorGaël L'hopital <gael@lhopital.org>
Tue, 14 Feb 2023 11:09:31 +0000 (12:09 +0100)
committerGitHub <noreply@github.com>
Tue, 14 Feb 2023 11:09:31 +0000 (12:09 +0100)
* Adding P300 to the list of supported equipments

Signed-off-by: clinique <gael@lhopital.org>
14 files changed:
bundles/org.openhab.binding.tapocontrol/README.md
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/TapoDeviceConnector.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/TapoDeviceHttpApi.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoBindingSettings.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoThingConstants.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/device/TapoDevice.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/device/TapoSmartPlug.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/helpers/PayloadBuilder.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoChild.java [new file with mode: 0644]
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoChildData.java [new file with mode: 0644]
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoSubRequest.java [new file with mode: 0644]
bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/i18n/tapocontrol.properties
bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/P300.xml [new file with mode: 0644]
bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/channels.xml

index 4df37cd0989d1439388f00b217bfff7a66d8f81c..640285fcbc119e4ef8f085224ca84fffe9bab3a9 100644 (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 ]
 }
 ```
 
index a466e2d98525ecc17a3db03532955fd3454381ac..c1c992338bdb6a69b585e5fbdca8603ac37e2e18 100644 (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();
     }
 
     /***********************************
@@ -111,7 +110,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
 
     /**
      * send custom command to device
-     * 
+     *
      * @param plBuilder Payloadbuilder with unencrypted payload
      */
     public void sendCustomQuery(String queryMethod) {
@@ -123,7 +122,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
 
     /**
      * send custom command to device
-     * 
+     *
      * @param plBuilder Payloadbuilder with unencrypted payload
      */
     public void sendCustomPayload(PayloadBuilder plBuilder) {
@@ -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,15 +204,16 @@ 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
      */
     public void queryInfo(boolean ignoreGap) {
@@ -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
      */
@@ -229,7 +265,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
     /**
      * SEND SECUREPASSTHROUGH
      * encprypt payload and send to device
-     * 
+     *
      * @param payload payload sent to device
      * @param command command executed - this will handle result
      */
@@ -255,7 +291,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
 
     /**
      * Handle SuccessResponse (setDeviceInfo)
-     * 
+     *
      * @param responseBody String with responseBody from device
      */
     @Override
@@ -270,9 +306,9 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
     }
 
     /**
-     * 
+     *
      * handle JsonResponse (getDeviceInfo)
-     * 
+     *
      * @param responseBody String with responseBody from device
      */
     @Override
@@ -290,7 +326,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
 
     /**
      * handle JsonResponse (getEnergyData)
-     * 
+     *
      * @param responseBody String with responseBody from device
      */
     @Override
@@ -305,9 +341,26 @@ 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
-     * 
+     *
      * @param responseBody String with responseBody from device
      */
     @Override
@@ -317,7 +370,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
 
     /**
      * handle error
-     * 
+     *
      * @param te TapoErrorHandler
      */
     @Override
@@ -327,18 +380,18 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
 
     /**
      * get Json from response
-     * 
+     *
      * @param responseBody
      * @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 */
@@ -369,7 +422,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
 
     /**
      * Check if device is online
-     * 
+     *
      * @return true if device is online
      */
     public Boolean isOnline() {
@@ -378,7 +431,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
 
     /**
      * Check if device is online
-     * 
+     *
      * @param raiseError if true
      * @return true if device is online
      */
@@ -397,7 +450,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
 
     /**
      * IP-Adress
-     * 
+     *
      * @return String ipAdress
      */
     public String getIP() {
@@ -406,7 +459,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
 
     /**
      * PING IP Adress
-     * 
+     *
      * @return true if ping successfull
      */
     public Boolean pingDevice() {
@@ -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();
+    }
 }
index 53ad49a378672c3d0083422627c7dab16357cc87..3e58ead0d8b1b4ffe9527c1197c6c2a3fa698137 100644 (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());
     }
 
     /***********************************
@@ -79,7 +84,7 @@ public class TapoDeviceHttpApi {
      ************************************/
     /**
      * handle SuccessResponse (setDeviceInfo)
-     * 
+     *
      * @param responseBody String with responseBody from device
      */
     protected void handleSuccessResponse(String responseBody) {
@@ -87,7 +92,7 @@ public class TapoDeviceHttpApi {
 
     /**
      * handle JsonResponse (getDeviceInfo)
-     * 
+     *
      * @param responseBody String with responseBody from device
      */
     protected void handleDeviceResult(String responseBody) {
@@ -95,7 +100,7 @@ public class TapoDeviceHttpApi {
 
     /**
      * handle JsonResponse (getEnergyData)
-     * 
+     *
      * @param responseBody String with responseBody from device
      */
     protected void handleEnergyResult(String responseBody) {
@@ -103,20 +108,35 @@ public class TapoDeviceHttpApi {
 
     /**
      * handle custom response
-     * 
+     *
      * @param responseBody String with responseBody from device
      */
     protected void handleCustomResponse(String responseBody) {
     }
 
+    /**
+     * handle JsonResponse (getChildDevices)
+     *
+     * @param responseBody String with responseBody from device
+     */
+    protected void handleChildDevices(String responseBody) {
+    }
+
     /**
      * handle error
-     * 
+     *
      * @param te TapoErrorHandler
      */
     protected void handleError(TapoErrorHandler tapoError) {
     }
 
+    /**
+     * refresh the list of child devices
+     *
+     */
+    protected void queryChildDevices() {
+    }
+
     /***********************************
      *
      * LOGIN FUNCTIONS
@@ -154,13 +174,13 @@ public class TapoDeviceHttpApi {
 
     /**
      * return encrypted key from 'handshake' request
-     * 
+     *
      * @param response ContentResponse from "handshake" method
      * @return
      */
     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");
@@ -173,7 +193,7 @@ public class TapoDeviceHttpApi {
 
     /**
      * return cookie from 'handshake' request
-     * 
+     *
      * @param response ContentResponse from "handshake" metho
      * @return
      */
@@ -191,7 +211,7 @@ public class TapoDeviceHttpApi {
 
     /**
      * Query Token from device
-     * 
+     *
      * @return String with token returned from device
      */
     protected String queryToken() {
@@ -223,7 +243,7 @@ public class TapoDeviceHttpApi {
 
     /**
      * get Token from "login"-request
-     * 
+     *
      * @param response
      * @return
      */
@@ -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) {
@@ -269,7 +289,7 @@ public class TapoDeviceHttpApi {
      ************************************/
     /**
      * SEND SYNCHRON HTTP-REQUEST
-     * 
+     *
      * @param url url request is sent to
      * @param payload payload (String) to send
      * @return ContentResponse of request
@@ -306,7 +326,7 @@ public class TapoDeviceHttpApi {
     /**
      * SEND ASYNCHRONOUS HTTP-REQUEST
      * (don't wait for awnser with programm code)
-     * 
+     *
      * @param url string url request is sent to
      * @param payload data-payload
      * @param command command executed - this will handle RepsonseType
@@ -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);
@@ -378,7 +401,7 @@ public class TapoDeviceHttpApi {
 
     /**
      * return error code from response
-     * 
+     *
      * @param response
      * @return 0 if request was successfull
      */
@@ -397,13 +420,13 @@ public class TapoDeviceHttpApi {
 
     /**
      * return error code from responseBody
-     * 
+     *
      * @param responseBody
      * @return 0 if request was successfull
      */
     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) {
@@ -420,13 +443,13 @@ public class TapoDeviceHttpApi {
 
     /**
      * Check for JsonObject "errorcode" and if this is > 0 (no Error)
-     * 
+     *
      * @param responseBody
      * @return true if is js errorcode > 0; false if there is no "errorcode"
      */
     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) {
@@ -457,13 +480,13 @@ public class TapoDeviceHttpApi {
 
     /**
      * Decrypt Response
-     * 
+     *
      * @param responseBody encrypted string from response-body
      * @return String decrypted responseBody
      */
     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);
@@ -478,7 +501,7 @@ public class TapoDeviceHttpApi {
 
     /**
      * encrypt payload
-     * 
+     *
      * @param payload
      * @return encrypted payload
      */
@@ -507,7 +530,7 @@ public class TapoDeviceHttpApi {
      ************************************/
     /**
      * Logged In
-     * 
+     *
      * @return true if logged in
      */
     public Boolean loggedIn() {
@@ -516,7 +539,7 @@ public class TapoDeviceHttpApi {
 
     /**
      * Logged In
-     * 
+     *
      * @param raiseError if true
      * @return true if logged in
      */
@@ -540,7 +563,7 @@ public class TapoDeviceHttpApi {
 
     /**
      * Set new ipAddress
-     * 
+     *
      * @param new ipAdress
      */
     public void setDeviceURL(String ipAddress) {
@@ -550,7 +573,7 @@ public class TapoDeviceHttpApi {
 
     /**
      * Set new ipAdresss with token
-     * 
+     *
      * @param ipAddress ipAddres of device
      * @param token token from login-ressult
      */
@@ -561,7 +584,7 @@ public class TapoDeviceHttpApi {
 
     /**
      * Set new token
-     * 
+     *
      * @param deviceURL
      * @param token
      */
@@ -583,7 +606,7 @@ public class TapoDeviceHttpApi {
 
     /**
      * Set new cookie
-     * 
+     *
      * @param cookie
      */
     protected void setCookie(String cookie) {
index 7440ac7e080b333f2db5fadb97779cd74d10ee21..59c95b5d41c2deca4fbfc9dffeba56cce8ed617d 100644 (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";
 }
index 57c9219440e819a2e168d79575bdc1e5bb2bd937..d10f51cefefb7d763fdda6246669f914649551c2 100644 (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;
index 28b375e9d2f3e4b2dca9565274cf2b08c2116b65..d169c0fd055c526d2405a7aed5394a6e2db843ca 100644 (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;
@@ -131,7 +132,7 @@ public abstract class TapoDevice extends BaseThingHandler {
 
     /**
      * CHECK SETTINGS
-     * 
+     *
      * @return TapoErrorHandler with configuration-errors
      */
     protected TapoErrorHandler checkSettings() {
@@ -203,7 +204,7 @@ public abstract class TapoDevice extends BaseThingHandler {
 
     /**
      * Stop scheduler
-     * 
+     *
      * @param scheduler ScheduledFeature<?> which schould be stopped
      */
     protected void stopScheduler(@Nullable ScheduledFuture<?> scheduler) {
@@ -228,7 +229,7 @@ public abstract class TapoDevice extends BaseThingHandler {
      ************************************/
     /**
      * return device Error
-     * 
+     *
      * @return
      */
     public TapoErrorHandler getError() {
@@ -237,7 +238,7 @@ public abstract class TapoDevice extends BaseThingHandler {
 
     /**
      * set device error
-     * 
+     *
      * @param tapoError TapoErrorHandler-Object
      */
     public void setError(TapoErrorHandler tapoError) {
@@ -253,7 +254,7 @@ public abstract class TapoDevice extends BaseThingHandler {
 
     /***
      * Check if ThingType is model
-     * 
+     *
      * @param model
      * @return
      */
@@ -271,7 +272,7 @@ public abstract class TapoDevice extends BaseThingHandler {
     /**
      * CHECK IF RECEIVED DATA ARE FROM THE EXPECTED DEVICE
      * Compare MAC-Adress
-     * 
+     *
      * @param deviceInfo
      * @return true if is the expected device
      */
@@ -315,7 +316,7 @@ public abstract class TapoDevice extends BaseThingHandler {
 
     /**
      * query device Properties
-     * 
+     *
      * @param ignoreGap ignore gap to last query. query anyway (force)
      */
     public void queryDeviceInfo(boolean ignoreGap) {
@@ -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();
@@ -334,7 +339,7 @@ public abstract class TapoDevice extends BaseThingHandler {
 
     /**
      * SET DEVICE INFOs to device
-     * 
+     *
      * @param deviceInfo
      */
     public void setDeviceInfo(TapoDeviceInfo deviceInfo) {
@@ -351,7 +356,7 @@ public abstract class TapoDevice extends BaseThingHandler {
 
     /**
      * Set Device EnergyData to device
-     * 
+     *
      * @param energyData
      */
     public void setEnergyData(TapoEnergyData energyData) {
@@ -363,9 +368,21 @@ 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
-     * 
+     *
      * @param responseBody
      */
     public void responsePasstrough(String responseBody) {
@@ -373,10 +390,10 @@ public abstract class TapoDevice extends BaseThingHandler {
 
     /**
      * UPDATE PROPERTIES
-     * 
+     *
      * If only one property must be changed, there is also a convenient method
      * updateProperty(String name, String value).
-     * 
+     *
      * @param TapoDeviceInfo
      */
     protected void devicePropertiesChanged(TapoDeviceInfo deviceInfo) {
@@ -392,7 +409,7 @@ public abstract class TapoDevice extends BaseThingHandler {
 
     /**
      * update channel state
-     * 
+     *
      * @param channelID
      * @param value
      */
@@ -408,7 +425,7 @@ public abstract class TapoDevice extends BaseThingHandler {
 
     /**
      * Connect (login) to device
-     * 
+     *
      */
     public Boolean connect() {
         deviceError.reset();
@@ -471,7 +488,7 @@ public abstract class TapoDevice extends BaseThingHandler {
      ************************************/
     /**
      * Get ChannelID including group
-     * 
+     *
      * @param group String channel-group
      * @param channel String channel-name
      * @return String channelID
@@ -486,7 +503,7 @@ public abstract class TapoDevice extends BaseThingHandler {
 
     /**
      * Get Channel from ChannelID
-     * 
+     *
      * @param channelID String channelID
      * @return String channel-name
      */
index e6acff23df9f46a19661330e8f136070fd72035c..50e09ab5fe4d9e2d51bb0de3b93e0d5d6fc66968 100644 (file)
@@ -37,7 +37,7 @@ public class TapoSmartPlug extends TapoDevice {
 
     /**
      * Constructor
-     * 
+     *
      * @param thing Thing object representing device
      */
     public TapoSmartPlug(Thing thing) {
@@ -46,26 +46,30 @@ public class TapoSmartPlug extends TapoDevice {
 
     /**
      * 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) {
-        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 */
@@ -76,7 +80,7 @@ public class TapoSmartPlug extends TapoDevice {
 
     /**
      * UPDATE PROPERTIES
-     * 
+     *
      * @param TapoDeviceInfo
      */
     @Override
index fbb9d34d4784fb9edc3d0754d7821401d7339156..810347e2a7c51bfd21d4056bfee76de2f85dacf9 100644 (file)
@@ -55,7 +55,7 @@ public class PayloadBuilder {
 
     /**
      * Get JSON Payload (STRING)
-     * 
+     *
      * @return String JSON-Payload
      */
     public String getPayload() {
@@ -66,7 +66,7 @@ public class PayloadBuilder {
 
     /**
      * Get JSON Payload (JSON-Object)
-     * 
+     *
      * @return JsonObject JSON-Payload
      */
     public JsonObject getJsonPayload() {
@@ -87,6 +87,6 @@ public class PayloadBuilder {
      * remove all parameters
      */
     public void flushParameters(String command) {
-        this.parameters = new JsonObject();
+        parameters = new JsonObject();
     }
 }
diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoChild.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoChild.java
new file mode 100644 (file)
index 0000000..d32f6a5
--- /dev/null
@@ -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;
+    }
+}
diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoChildData.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoChildData.java
new file mode 100644 (file)
index 0000000..457f026
--- /dev/null
@@ -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;
+    }
+}
diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoSubRequest.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoSubRequest.java
new file mode 100644 (file)
index 0000000..ef022c6
--- /dev/null
@@ -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))));
+    }
+}
index 784f9e610f9d5163fcac035facbd03fec6603dab..8517d6ef6f00829d2f8f8574d64607a547e35202 100644 (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
 
diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/P300.xml b/bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/P300.xml
new file mode 100644 (file)
index 0000000..4eb2d68
--- /dev/null
@@ -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>
index 009179a5f4810ecce0ee43f3d715cfca3b4ed9bc..c4c3c49b63eab5c95e357d87a713ce3c8a8a226a 100644 (file)
                </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>