]> git.basschouten.com Git - openhab-addons.git/commitdiff
[tapocontrol] now supports energy monitoring of P110 device (#12017)
authorChristian Wild <40909464+wildcs@users.noreply.github.com>
Thu, 27 Jan 2022 07:46:30 +0000 (08:46 +0100)
committerGitHub <noreply@github.com>
Thu, 27 Jan 2022 07:46:30 +0000 (08:46 +0100)
* [tapocontrol] added energy monitoring for P110
* [tapocontrol] corrected textual thing configuration in readme

Signed-off-by: Christian Wild <christian@wild-bw.de>
19 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/TapoErrorConstants.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/TapoLightStrip.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/device/TapoSmartBulb.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/device/TapoUniversalDevice.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/helpers/TapoUtils.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoDeviceInfo.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoEnergyData.java [new file with mode: 0644]
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoLightEffect.java
bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/i18n/tapocontrol.properties
bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/P110.xml
bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/thing/channels.xml
bundles/org.openhab.binding.tapocontrol/src/test/java/org/openhab/binding/tapocontrol/internal/device/TapoUniversalDevice.java

index 843f7cc584863745177701378ebb5f89c39dde07..cd19010bcdf89c510b7116c1d831adb7015eda63 100644 (file)
@@ -6,12 +6,21 @@ This binding adds support to control Tapo (Copyright © TP-Link Corporation Limi
 
 The following Tapo-Devices are supported
 
-### P100/P105/P110 SmartPlug (WiFi)
+### P100/P105 SmartPlug (WiFi)
 
 * Power On/Off
 * Wi-Fi signal (SignalStrength)
 * On-Time (Time in seconds device is switched on)
 
+### P110 EnergyMonitoring SmartPlug (WiFi)
+
+* Power On/Off
+* Wi-Fi signal (SignalStrength)
+* On-Time (Time in seconds device is switched on)
+* actual PowerUsage (Watt)
+* today EnergyUsage (Wh)
+* today Runtime (Time in seconds device was on today)
+
 ### L510(Series) dimmable SmartBulb (WiFi)
 
 * Light On/Off
@@ -87,6 +96,9 @@ All devices support some of the following channels:
 |           | color            | Color                  | Color                        | L530, L900                                  |
 | device    | wifiSignal       | system.signal-strength | WiFi-quality-level           | P100, P105, P110, L510, L530, L900, L920    |
 |           | onTime           | Number:Time            | seconds output is on         | P100, P105, P110, L510, L530, L900, L920    |
+| energy    | actualPower      | Number:Power           | actual Power (Watt)          | P110                                        |
+|           | todayEnergyUsage | Number:Energy          | used energy today (Wh)       | P110                                        |
+|           | todayRuntime      | Number:Time            | seconds output was on today  | P110                                        |
 
 
 ## Channel Refresh
@@ -100,12 +112,16 @@ To minimize network traffic the default refresh-rate is set to 30 seconds. This
 ### tapocontrol.things:
 
 ```
-tapocontrol:bridge:myTapoBridge                     "Cloud-Login"               [ username="you@yourpovider.com", password="verysecret" ]
-tapocontrol:P100:myTapoBridge:mySocket              "My-Socket"                 [ ipAddress="192.168.178.150", pollingInterval=30 ]
-tapocontrol:L510:myTapoBridge:whiteBulb                "white-light"               [ ipAddress="192.168.178.151", pollingInterval=30 ]
-tapocontrol:L530:myTapoBridge:colorBulb                "color-light"               [ ipAddress="192.168.178.152", pollingInterval=30 ]
-tapocontrol:L900:myTapoBridge:myLightStrip          "light-strip"               [ ipAddress="192.168.178.153", pollingInterval=30 ]
-``` 
+tapocontrol:bridge:myTapoBridge                 "Cloud-Login"               [ username="you@yourpovider.com", password="verysecret" ]
+tapocontrol:P100:myTapoBridge:mySocket          "My-Socket"     (tapocontrol:bridge:myTapoBridge)   [ ipAddress="192.168.178.150", pollingInterval=30 ]
+tapocontrol:L510:myTapoBridge:whiteBulb         "white-light"   (tapocontrol:bridge:myTapoBridge)   [ ipAddress="192.168.178.151", pollingInterval=30 ]
+tapocontrol:L530:myTapoBridge:colorBulb         "color-light"   (tapocontrol:bridge:myTapoBridge)   [ ipAddress="192.168.178.152", pollingInterval=30 ]
+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 ]
+}
+```
 
 ### tapocontrol.items:
 
index ca3c000a002e89d9c0d318b6b8a92f2b00dba87b..55f82ff1507445c2dba7eccac8344bd0708591f4 100644 (file)
@@ -14,6 +14,7 @@ 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 java.net.InetAddress;
@@ -25,6 +26,7 @@ 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.TapoDeviceInfo;
+import org.openhab.binding.tapocontrol.internal.structures.TapoEnergyData;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -43,6 +45,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
     private final String uid;
     private final TapoDevice device;
     private TapoDeviceInfo deviceInfo;
+    private TapoEnergyData energyData;
     private Gson gson;
     private long lastQuery = 0L;
     private long lastSent = 0L;
@@ -58,6 +61,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
         this.device = device;
         this.gson = new Gson();
         this.deviceInfo = new TapoDeviceInfo();
+        this.energyData = new TapoEnergyData();
         this.uid = device.getThingUID().getAsString();
     }
 
@@ -208,6 +212,20 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
         }
     }
 
+    /**
+     * Get energy usage from device
+     */
+    public void getEnergyUsage() {
+        logger.trace("({}) DeviceConnetor_getEnergyUsage from '{}'", uid, deviceURL);
+
+        /* create payload */
+        PayloadBuilder plBuilder = new PayloadBuilder();
+        plBuilder.method = DEVICE_CMD_GETENERGY;
+        String payload = plBuilder.getPayload();
+
+        sendSecurePasstrhroug(payload, DEVICE_CMD_GETENERGY);
+    }
+
     /**
      * SEND SECUREPASSTHROUGH
      * encprypt payload and send to device
@@ -251,6 +269,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
     }
 
     /**
+     * 
      * handle JsonResponse (getDeviceInfo)
      * 
      * @param responseBody String with responseBody from device
@@ -258,7 +277,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
     @Override
     protected void handleDeviceResult(String responseBody) {
         JsonObject jsnResult = getJsonFromResponse(responseBody);
-        if (jsnResult.has("device_id")) {
+        if (jsnResult.has(DEVICE_PROPERTY_ID)) {
             this.deviceInfo = new TapoDeviceInfo(jsnResult);
             this.device.setDeviceInfo(deviceInfo);
         } else {
@@ -268,6 +287,23 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
         this.device.responsePasstrough(responseBody);
     }
 
+    /**
+     * handle JsonResponse (getEnergyData)
+     * 
+     * @param responseBody String with responseBody from device
+     */
+    @Override
+    protected void handleEnergyResult(String responseBody) {
+        JsonObject jsnResult = getJsonFromResponse(responseBody);
+        if (jsnResult.has(ENERGY_PROPERTY_POWER)) {
+            this.energyData = new TapoEnergyData(jsnResult);
+            this.device.setEnergyData(energyData);
+        } else {
+            this.energyData = new TapoEnergyData();
+        }
+        this.device.responsePasstrough(responseBody);
+    }
+
     /**
      * handle custom response
      * 
index 90b15db2b80cd6fe56b6fce42eb941b72a359811..eb4966f16203e990ae200c7ccdf684912c97d0fe 100644 (file)
@@ -93,6 +93,14 @@ public class TapoDeviceHttpApi {
     protected void handleDeviceResult(String responseBody) {
     }
 
+    /**
+     * handle JsonResponse (getEnergyData)
+     * 
+     * @param responseBody String with responseBody from device
+     */
+    protected void handleEnergyResult(String responseBody) {
+    }
+
     /**
      * handle custom response
      * 
@@ -346,6 +354,9 @@ public class TapoDeviceHttpApi {
                             case DEVICE_CMD_GETINFO:
                                 handleDeviceResult(rBody);
                                 break;
+                            case DEVICE_CMD_GETENERGY:
+                                handleEnergyResult(rBody);
+                                break;
                             case DEVICE_CMD_CUSTOM:
                                 handleCustomResponse(rBody);
                                 break;
index 8cccffca6553e44141f6f32000adb6038e2a28c0..08f97e56ab4712b7b22f375997261d7d7839c3fd 100644 (file)
@@ -52,5 +52,6 @@ public class TapoBindingSettings {
     // LIST OF DEVICE-COMMANDS
     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_CUSTOM = "custom_command";
 }
index f2f2a64322a7388f2400921d94278deb4a31c3a5..12a00dc8bcad78d61b96d16a40ad770c0ae5ca0d 100644 (file)
@@ -142,7 +142,7 @@ public class TapoErrorConstants {
     // List of Config-Error-Messages
     public static final String ERR_CONF_IP_MSG = "IP-Address not valid"; // 10001;
     public static final String ERR_CONF_CREDENTIALS_MSG = "credentials not set (bridge)"; // 10002;
-    public static final String ERR_NO_BRIDGE_MSG = "no brigde configured"; // 10003;
+    public static final String ERR_NO_BRIDGE_MSG = "no bridge configured"; // 10003;
 
     /****************************************
      * ErrorTypes
index 32c1f36ad1034207f73e452d7ddcd2fddaa46c00..1d7cbbd25ef1e9aff9fd2c79497d13f6022f5b0c 100644 (file)
@@ -73,6 +73,8 @@ public class TapoThingConstants {
                     .of(SUPPORTED_BRIDGE_UIDS, SUPPORTED_SMART_PLUG_UIDS, SUPPORTED_WHITE_BULB_UIDS,
                             SUPPORTED_COLOR_BULB_UIDS, SUPPORTED_LIGHT_STRIP_UIDS)
                     .flatMap(Set::stream).collect(Collectors.toSet()));
+    /*** THINGS WITH ENERGY DATA ***/
+    public static final Set<ThingTypeUID> SUPPORTED_ENERGY_DATA_UIDS = Set.of(P110_THING_TYPE);
 
     /*** THINGS WITH CHANNEL GROUPS ***/
     public static final Set<ThingTypeUID> CHANNEL_GROUP_THING_SET = Collections
@@ -125,6 +127,16 @@ public class TapoThingConstants {
     public static final String PROPERTY_LIGHTNING_EFFECT_ENABLE = "enable";
     public static final String PROPERTY_LIGHTNING_EFFECT_ID = "id";
     public static final String PROPERTY_LIGHTNING_EFFECT_NAME = "name";
+    // energy monitoring
+    public static final String ENERGY_PROPERTY_POWER = "current_power";
+    public static final String ENERGY_PROPERTY_RUNTIME_TODAY = "today_runtime";
+    public static final String ENERGY_PROPERTY_RUNTIME_MONTH = "month_runtime";
+    public static final String ENERGY_PROPERTY_ENERGY_TODAY = "today_energy";
+    public static final String ENERGY_PROPERTY_ENERGY_MONTH = "month_energy";
+    public static final String ENERGY_PROPERTY_PAST24H = "past24h";
+    public static final String ENERGY_PROPERTY_PAST7D = "past7d";
+    public static final String ENERGY_PROPERTY_PAST30D = "past30d";
+    public static final String ENERGY_PROPERTY_PAST1Y = "past1y";
 
     /*** DEVICE SETTINGS ***/
     public static final Integer BULB_MIN_COLORTEMP = 2500;
@@ -143,6 +155,11 @@ public class TapoThingConstants {
     public static final String CHANNEL_ONTIME = "onTime";
     public static final String CHANNEL_OVERHEAT = "overheated";
     public static final String CHANNEL_WIFI_STRENGTH = "wifiSignal";
+    // channel group energy monitor
+    public static final String CHANNEL_GROUP_ENERGY = "energy";
+    public static final String CHANNEL_NRG_POWER = "actualPower";
+    public static final String CHANNEL_NRG_USAGE_TODAY = "todayEnergyUsage";
+    public static final String CHANNEL_NRG_RUNTIME_TODAY = "todayRuntime";
     // channel group effect
     public static final String CHANNEL_GROUP_EFFECTS = "effect";
     public static final String CHANNEL_FX_BRIGHTNESS = "brightness";
index 784f5b2d9cd187f725cdc18e87c5581ab861f410..eb46638f7cc8ed4471ed084091cf0c4309c57d7a 100644 (file)
@@ -28,6 +28,8 @@ import org.openhab.binding.tapocontrol.internal.api.TapoDeviceConnector;
 import org.openhab.binding.tapocontrol.internal.helpers.TapoErrorHandler;
 import org.openhab.binding.tapocontrol.internal.structures.TapoDeviceConfiguration;
 import org.openhab.binding.tapocontrol.internal.structures.TapoDeviceInfo;
+import org.openhab.binding.tapocontrol.internal.structures.TapoEnergyData;
+import org.openhab.core.library.unit.Units;
 import org.openhab.core.thing.Bridge;
 import org.openhab.core.thing.ChannelUID;
 import org.openhab.core.thing.Thing;
@@ -319,6 +321,10 @@ public abstract class TapoDevice extends BaseThingHandler {
         deviceError.reset();
         if (connector.loggedIn()) {
             connector.queryInfo(ignoreGap);
+            // query energy usage
+            if (SUPPORTED_ENERGY_DATA_UIDS.contains(getThing().getThingTypeUID())) {
+                connector.getEnergyUsage();
+            }
         } else {
             logger.debug("({}) tried to query DeviceInfo but not loggedIn", uid);
             connect();
@@ -342,6 +348,20 @@ public abstract class TapoDevice extends BaseThingHandler {
         }
     }
 
+    /**
+     * Set Device EnergyData to device
+     * 
+     * @param energyData
+     */
+    public void setEnergyData(TapoEnergyData energyData) {
+        publishState(getChannelID(CHANNEL_GROUP_ENERGY, CHANNEL_NRG_POWER),
+                getPowerType(energyData.getCurrentPower(), Units.WATT));
+        publishState(getChannelID(CHANNEL_GROUP_ENERGY, CHANNEL_NRG_USAGE_TODAY),
+                getEnergyType(energyData.getTodayEnergy(), Units.WATT_HOUR));
+        publishState(getChannelID(CHANNEL_GROUP_ENERGY, CHANNEL_NRG_RUNTIME_TODAY),
+                getTimeType(energyData.getTodayRuntime(), Units.MINUTE));
+    }
+
     /**
      * Handle full responsebody received from connector
      * 
@@ -474,6 +494,7 @@ public abstract class TapoDevice extends BaseThingHandler {
         channel = channel.replace(CHANNEL_GROUP_ACTUATOR + "#", "");
         channel = channel.replace(CHANNEL_GROUP_DEVICE + "#", "");
         channel = channel.replace(CHANNEL_GROUP_EFFECTS + "#", "");
+        channel = channel.replace(CHANNEL_GROUP_ENERGY + "#", "");
         return channel;
     }
 }
index 0d8b06f7326cd5fbfc4eb0a4a600a62341ca76e2..6f55e143e79aa248d58fd9c19185726590ff72a8 100644 (file)
@@ -218,7 +218,7 @@ public class TapoLightStrip extends TapoDevice {
         publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_WIFI_STRENGTH),
                 getDecimalType(deviceInfo.getSignalLevel()));
         publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_ONTIME),
-                getQuantityType(deviceInfo.getOnTime(), Units.SECOND));
+                getTimeType(deviceInfo.getOnTime(), Units.SECOND));
         publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_OVERHEAT), getOnOffType(deviceInfo.isOverheated()));
         // light effect
         publishState(getChannelID(CHANNEL_GROUP_EFFECTS, CHANNEL_FX_BRIGHTNESS),
index c4af02651ea3096eea002d6cab356ce60dea2a95..985c005144b5176614d870fb6b4263e318b201a2 100644 (file)
@@ -163,7 +163,7 @@ public class TapoSmartBulb extends TapoDevice {
         publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_WIFI_STRENGTH),
                 getDecimalType(deviceInfo.getSignalLevel()));
         publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_ONTIME),
-                getQuantityType(deviceInfo.getOnTime(), Units.SECOND));
+                getTimeType(deviceInfo.getOnTime(), Units.SECOND));
         publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_OVERHEAT), getOnOffType(deviceInfo.isOverheated()));
     }
 }
index 10a5fef5cc4fa0622533617702e1b7bb282e821d..f96bcacb074a53002b1558411a0a210cfa41ea30 100644 (file)
@@ -86,7 +86,7 @@ public class TapoSmartPlug extends TapoDevice {
         publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_WIFI_STRENGTH),
                 getDecimalType(deviceInfo.getSignalLevel()));
         publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_ONTIME),
-                getQuantityType(deviceInfo.getOnTime(), Units.SECOND));
+                getTimeType(deviceInfo.getOnTime(), Units.SECOND));
         publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_OVERHEAT), getOnOffType(deviceInfo.isOverheated()));
     }
 }
index 3fcf88ddf2ddf9ad2e4726010b8a34d7d1498116..3b518106e4d07cf6d5adc4744601ee7f9116b3fa 100644 (file)
@@ -196,7 +196,7 @@ public class TapoUniversalDevice extends TapoDevice {
         publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_WIFI_STRENGTH),
                 getDecimalType(deviceInfo.getSignalLevel()));
         publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_ONTIME),
-                getQuantityType(deviceInfo.getOnTime(), Units.SECOND));
+                getTimeType(deviceInfo.getOnTime(), Units.SECOND));
         publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_OVERHEAT),
                 getDecimalType(deviceInfo.isOverheated() ? 1 : 0));
     }
index 04ba34e3bacbef2a54f4079366a4c93163a6ad18..90cd888f56a1ce75f9ae41612cf7ebfde7ee6dae 100644 (file)
@@ -13,6 +13,8 @@
 package org.openhab.binding.tapocontrol.internal.helpers;
 
 import javax.measure.Unit;
+import javax.measure.quantity.Energy;
+import javax.measure.quantity.Power;
 import javax.measure.quantity.Time;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -340,9 +342,31 @@ public class TapoUtils {
      * 
      * @param numVal Number with value
      * @param unit TimeUnit (Unit<Time>)
-     * @return QuantityTime<Time>
+     * @return QuantityType<Time>
      */
-    public static QuantityType<Time> getQuantityType(@Nullable Number numVal, Unit<Time> unit) {
+    public static QuantityType<Time> getTimeType(@Nullable Number numVal, Unit<Time> unit) {
+        return new QuantityType<>((numVal != null ? numVal : 0), unit);
+    }
+
+    /**
+     * Return QuantityType with Power
+     * 
+     * @param numVal Number with value
+     * @param unit PowerUnit (Unit<Power>)
+     * @return QuantityType<Power>
+     */
+    public static QuantityType<Power> getPowerType(@Nullable Number numVal, Unit<Power> unit) {
+        return new QuantityType<>((numVal != null ? numVal : 0), unit);
+    }
+
+    /**
+     * Return QuantityType with Energy
+     * 
+     * @param numVal Number with value
+     * @param unit PowerUnit (Unit<Power>)
+     * @return QuantityType<Energy>
+     */
+    public static QuantityType<Energy> getEnergyType(@Nullable Number numVal, Unit<Energy> unit) {
         return new QuantityType<>((numVal != null ? numVal : 0), unit);
     }
 }
index 345fc4f48f70efebfc3607645acb391c88c242b1..c34c7f8beb67e3d954ccfa026189d78e23585f7b 100644 (file)
@@ -92,7 +92,6 @@ public class TapoDeviceInfo {
         this.hue = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_HUE);
         this.hwVer = jsonObjectToString(jsonObject, DEVICE_PROPERTY_HW);
         this.ip = jsonObjectToString(jsonObject, DEVICE_PROPERTY_IP);
-        this.lightEffect = lightEffect.setData(jsonObject);
         this.mac = jsonObjectToString(jsonObject, DEVICE_PROPERTY_MAC);
         this.model = jsonObjectToString(jsonObject, DEVICE_PROPERTY_MODEL);
         this.nickname = jsonObjectToString(jsonObject, DEVICE_PROPERTY_NICKNAME);
@@ -106,6 +105,19 @@ public class TapoDeviceInfo {
         this.timeUsagePast30 = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_USAGE_30);
         this.timeUsageToday = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_USAGE_TODAY);
         this.type = jsonObjectToString(jsonObject, DEVICE_PROPERTY_TYPE);
+
+        if (this.hasLightEffect()) {
+            this.lightEffect = lightEffect.setData(jsonObject);
+        }
+    }
+
+    /***********************************
+     *
+     * CHECK FOR CHILD TYPES
+     *
+     ************************************/
+    public Boolean hasLightEffect() {
+        return this.jsonObject.has(DEVICE_PROPERTY_EFFECT);
     }
 
     /***********************************
diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoEnergyData.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoEnergyData.java
new file mode 100644 (file)
index 0000000..7ec4ce8
--- /dev/null
@@ -0,0 +1,129 @@
+/**
+ * Copyright (c) 2010-2022 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.TapoThingConstants.*;
+import static org.openhab.binding.tapocontrol.internal.helpers.TapoUtils.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+import com.google.gson.JsonObject;
+
+/**
+ * Tapo-Energy-Monitor Structure Class
+ *
+ * @author Christian Wild - Initial contribution
+ */
+@NonNullByDefault
+public class TapoEnergyData {
+    private Number currentPower = 0;
+    private Number todayEnergy = 0;
+    private Number monthEnergy = 0;
+    private Number todayRuntime = 0;
+    private Number monthRuntime = 0;
+    private Number[] past24h = new Number[24];
+    private Number[] past30d = new Number[30];
+    private Number[] past1y = new Number[12];
+
+    private JsonObject jsonObject = new JsonObject();
+
+    /**
+     * INIT
+     */
+    public TapoEnergyData() {
+        setData();
+    }
+
+    /**
+     * Init DeviceInfo with new Data;
+     * 
+     * @param jso JsonObject new Data
+     */
+    public TapoEnergyData(JsonObject jso) {
+        setData(jso);
+    }
+
+    /**
+     * Set Data (new JsonObject)
+     * 
+     * @param jso JsonObject new Data
+     */
+    public TapoEnergyData setData(JsonObject jso) {
+        /* create empty jsonObject to set efault values if has no energydata */
+        if (jso.has(ENERGY_PROPERTY_POWER)) {
+            this.jsonObject = jso;
+        } else {
+            jsonObject = new JsonObject();
+        }
+        setData();
+        return this;
+    }
+
+    private void setData() {
+        this.currentPower = (float) jsonObjectToInt(jsonObject, ENERGY_PROPERTY_POWER) / 1000;
+
+        this.todayEnergy = jsonObjectToInt(jsonObject, ENERGY_PROPERTY_ENERGY_TODAY);
+        this.monthEnergy = jsonObjectToInt(jsonObject, ENERGY_PROPERTY_ENERGY_MONTH);
+        this.todayRuntime = jsonObjectToInt(jsonObject, ENERGY_PROPERTY_RUNTIME_TODAY);
+        this.monthRuntime = jsonObjectToInt(jsonObject, ENERGY_PROPERTY_RUNTIME_MONTH);
+        this.past24h = new Number[24];
+        this.past30d = new Number[30];
+        this.past1y = new Number[12];
+    }
+
+    /***********************************
+     *
+     * GET VALUES
+     *
+     ************************************/
+
+    public Number getCurrentPower() {
+        return this.currentPower;
+    }
+
+    public Number getTodayEnergy() {
+        return this.todayEnergy;
+    }
+
+    public Number getMonthEnergy() {
+        return this.monthEnergy;
+    }
+
+    public Number getYearEnergy() {
+        int sum = 0;
+        for (int i = 0; i < this.past1y.length; i++) {
+            sum += this.past1y[i].intValue();
+        }
+        return sum;
+    }
+
+    public Number getTodayRuntime() {
+        return this.todayRuntime;
+    }
+
+    public Number getMonthRuntime() {
+        return this.monthRuntime;
+    }
+
+    public Number[] getPast24hUsage() {
+        return this.past24h;
+    }
+
+    public Number[] getPast30dUsage() {
+        return this.past30d;
+    }
+
+    public Number[] getPast1yUsage() {
+        return this.past1y;
+    }
+}
index 671fb08edc3791cd7124b50a4b8615002fd8006c..dd9c829cace6a0e1a8803e7574efa5f9f5857516 100644 (file)
@@ -61,7 +61,7 @@ public class TapoLightEffect {
      */
     public TapoLightEffect setData(JsonObject jso) {
         /* create empty jsonObject to set efault values if has no lighning effect */
-        if (jsonObject.has(DEVICE_PROPERTY_EFFECT)) {
+        if (jso.has(DEVICE_PROPERTY_EFFECT)) {
             this.jsonObject = jso;
         } else {
             jsonObject = new JsonObject();
index b0586bc6b9ef568465d31bcf0fe72b0be9a663a7..a669aa035160bcdefe6b4bd38d63e48c06cbb629 100644 (file)
@@ -42,6 +42,8 @@ channel-group-type.tapocontrol.colorBulb.label = Color Light Bulb
 channel-group-type.tapocontrol.colorBulb.description = Tapo Multicolor Smart Light Bulb
 channel-group-type.tapocontrol.deviceState.label = Device State
 channel-group-type.tapocontrol.deviceState.description = Information about the device
+channel-group-type.tapocontrol.energyMonitor.label = Energy Usage
+channel-group-type.tapocontrol.energyMonitor.description = Energy and Power usage
 channel-group-type.tapocontrol.lightBulb.label = Light Bulb
 channel-group-type.tapocontrol.lightBulb.description = Tapo Smart Light Bulb
 channel-group-type.tapocontrol.lightEffect.label = Lightning Effect
@@ -53,6 +55,8 @@ channel-group-type.tapocontrol.smartPlug.description = Tapo Smart Plug Power Out
 
 # channel types
 
+channel-type.tapocontrol.actualPowerChannel.label = Power
+channel-type.tapocontrol.actualPowerChannel.description = Actual power usage
 channel-type.tapocontrol.colorChannel.label = Color
 channel-type.tapocontrol.colorChannel.description = Color
 channel-type.tapocontrol.colorTemperature.label = Color Temperature
@@ -77,3 +81,9 @@ channel-type.tapocontrol.outputChannel.label = Output Switch
 channel-type.tapocontrol.outputChannel.description = Switches the power state on/off
 channel-type.tapocontrol.overheated.label = Device Overheated
 channel-type.tapocontrol.overheated.description = ON if device is overheated
+channel-type.tapocontrol.todayEnergyUsageChannel.label = Today Usage
+channel-type.tapocontrol.todayEnergyUsageChannel.description = Today energy usage
+channel-type.tapocontrol.todayRuntimeChannel.label = Today Runtime
+channel-type.tapocontrol.todayRuntimeChannel.description = Today runtime (On-Time)
+
+
index 7eb4bff2c0b54c890148274364244be33089757a..4db27ada208346e7023ef9a240d0945c486b8141 100644 (file)
@@ -15,6 +15,7 @@
                <channel-groups>
                        <channel-group id="actuator" typeId="smartPlug"/>
                        <channel-group id="device" typeId="deviceState"/>
+                       <channel-group id="energy" typeId="energyMonitor"/>
                </channel-groups>
                <representation-property>macAddress</representation-property>
 
index ac305ed295bc067e86318232d69cf0f25cae708e..04e6226ddadb72efe8779516b963d6586ef4ac13 100644 (file)
                </channels>
        </channel-group-type>
 
+       <!-- Energy Monitor -->
+       <channel-group-type id="energyMonitor">
+               <label>Energy Usage</label>
+               <description>Energy and Power usage</description>
+               <channels>
+                       <channel id="actualPower" typeId="actualPowerChannel"></channel>
+                       <channel id="todayEnergyUsage" typeId="todayEnergyUsageChannel"></channel>
+                       <channel id="todayRuntime" typeId="todayRuntimeChannel"></channel>
+               </channels>
+       </channel-group-type>
+
        <!-- Lightning Effect -->
        <channel-group-type id="lightEffect">
                <label>Lightning Effect</label>
        </channel-type>
 
 
+       <!-- DEVICE-STATE CHANNEL TYPES -->
+       <!-- actual power usage -->
+       <channel-type id="actualPowerChannel">
+               <item-type>Number:Power</item-type>
+               <label>Power</label>
+               <description>Actual power usage</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.1f %unit%"></state>
+       </channel-type>
+
+       <!-- today energy usage -->
+       <channel-type id="todayEnergyUsageChannel">
+               <item-type>Number:Energy</item-type>
+               <label>Today Usage</label>
+               <description>Today energy usage</description>
+               <category>Energy</category>
+               <state readOnly="true" pattern="%.2f %unit%"></state>
+       </channel-type>
+
+       <!-- today runtime -->
+       <channel-type id="todayRuntimeChannel">
+               <item-type>Number:Time</item-type>
+               <label>Today Runtime</label>
+               <description>Today runtime (On-Time)</description>
+               <category>Time</category>
+               <state readOnly="true" pattern="%.0f %unit%"></state>
+       </channel-type>
+
 
-       <!-- LightningEffect Channel Type -->
+       <!-- LIGHTNING EFFECT CHANNEL TYPES -->
        <!-- effect on -->
        <channel-type id="effectOn">
                <item-type>Switch</item-type>
index 83eca4abda398ab1669588757a46a096fc9998ca..c0e1651e38e9d8578f443af206f10a42b601c9f8 100644 (file)
@@ -196,7 +196,7 @@ public class TapoUniversalDevice extends TapoDevice {
         publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_WIFI_STRENGTH),
                 getDecimalType(deviceInfo.getSignalLevel()));
         publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_ONTIME),
-                getQuantityType(deviceInfo.getOnTime(), Units.SECOND));
+                getTimeType(deviceInfo.getOnTime(), Units.SECOND));
         publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_OVERHEAT),
                 getDecimalType(deviceInfo.isOverheated() ? 1 : 0));
     }