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
| | 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
### 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:
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;
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;
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;
this.device = device;
this.gson = new Gson();
this.deviceInfo = new TapoDeviceInfo();
+ this.energyData = new TapoEnergyData();
this.uid = device.getThingUID().getAsString();
}
}
}
+ /**
+ * 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
}
/**
+ *
* handle JsonResponse (getDeviceInfo)
*
* @param responseBody String with responseBody from device
@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 {
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
*
protected void handleDeviceResult(String responseBody) {
}
+ /**
+ * handle JsonResponse (getEnergyData)
+ *
+ * @param responseBody String with responseBody from device
+ */
+ protected void handleEnergyResult(String responseBody) {
+ }
+
/**
* handle custom response
*
case DEVICE_CMD_GETINFO:
handleDeviceResult(rBody);
break;
+ case DEVICE_CMD_GETENERGY:
+ handleEnergyResult(rBody);
+ break;
case DEVICE_CMD_CUSTOM:
handleCustomResponse(rBody);
break;
// 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";
}
// 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
.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
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;
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";
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;
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();
}
}
+ /**
+ * 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
*
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;
}
}
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),
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()));
}
}
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()));
}
}
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));
}
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;
*
* @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);
}
}
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);
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);
}
/***********************************
--- /dev/null
+/**
+ * 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;
+ }
+}
*/
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();
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
# 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
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)
+
+
<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>
</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>
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));
}