mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[tapocontrol] Support display light effects for L530 (#14596)
* [tapocontrol] support display light effects for L530 color change is now possible if effect was already enabled by app Signed-off-by: Christian Wild <christian@wildclan.de>
This commit is contained in:
parent
279374a14b
commit
983efd76ea
@ -64,20 +64,21 @@ The thing has the following configuration parameters:
|
|||||||
|
|
||||||
All devices support some of the following channels:
|
All devices support some of the following channels:
|
||||||
|
|
||||||
| group | channel | type | description | things supporting this channel |
|
| 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 |
|
| 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 |
|
| | output1 | Switch | Power socket 1 on or off | P300 |
|
||||||
| | output2 | Switch | Power socket 2 on or off | P300 |
|
| | output2 | Switch | Power socket 2 on or off | P300 |
|
||||||
| | output3 | Switch | Power socket 3 on or off | P300 |
|
| | output3 | Switch | Power socket 3 on or off | P300 |
|
||||||
| | brightness | Dimmer | Brightness 0-100% | L510, L530, L610, L630, L900 |
|
| | brightness | Dimmer | Brightness 0-100% | L510, L530, L610, L630, L900 |
|
||||||
| | colorTemperature | Number | White-Color-Temp 2500-6500K | L510, L530, L610, L630, L900 |
|
| | colorTemperature | Number | White-Color-Temp 2500-6500K | L510, L530, L610, L630, L900 |
|
||||||
| | color | Color | Color | L530, L630, L900 |
|
| | color | Color | Color | L530, L630, L900 |
|
||||||
| device | wifiSignal | Number | WiFi-quality-level | P100, P105, P110, P115, L510, L530, L610, L630, L900, L920, L930 |
|
| effects | fxName | String | Active lightning effect (readonly) | L530 |
|
||||||
| | onTime | Number:Time | seconds output is on | P100, P105, P110, P115, L510, L530, L900, L920, L930 |
|
| device | wifiSignal | Number | WiFi-quality-level | P100, P105, P110, P115, L510, L530, L610, L630, L900, L920, L930 |
|
||||||
| energy | actualPower | Number:Power | actual Power (Watt) | P110, P115 |
|
| | onTime | Number:Time | seconds output is on | P100, P105, P110, P115, L510, L530, L900, L920, L930 |
|
||||||
| | todayEnergyUsage | Number:Energy | used energy today (Wh) | P110, P115 |
|
| energy | actualPower | Number:Power | actual Power (Watt) | P110, P115 |
|
||||||
| | todayRuntime | Number:Time | seconds output was on today | P110, P115 |
|
| | todayEnergyUsage | Number:Energy | used energy today (Wh) | P110, P115 |
|
||||||
|
| | todayRuntime | Number:Time | seconds output was on today | P110, P115 |
|
||||||
|
|
||||||
|
|
||||||
## Channel Refresh
|
## Channel Refresh
|
||||||
|
@ -131,17 +131,17 @@ public class TapoDiscoveryService extends AbstractDiscoveryService implements Th
|
|||||||
TapoBridgeHandler tapoBridge = this.bridge;
|
TapoBridgeHandler tapoBridge = this.bridge;
|
||||||
String deviceModel = getDeviceModel(device);
|
String deviceModel = getDeviceModel(device);
|
||||||
String label = getDeviceLabel(device);
|
String label = getDeviceLabel(device);
|
||||||
String deviceMAC = device.get(CLOUD_PROPERTY_MAC).getAsString();
|
String deviceMAC = device.get(CLOUD_JSON_KEY_MAC).getAsString();
|
||||||
ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, deviceModel);
|
ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, deviceModel);
|
||||||
|
|
||||||
/* create properties */
|
/* create properties */
|
||||||
Map<String, Object> properties = new HashMap<>();
|
Map<String, Object> properties = new HashMap<>();
|
||||||
properties.put(Thing.PROPERTY_VENDOR, DEVICE_VENDOR);
|
properties.put(Thing.PROPERTY_VENDOR, DEVICE_VENDOR);
|
||||||
properties.put(Thing.PROPERTY_MAC_ADDRESS, formatMac(deviceMAC, MAC_DIVISION_CHAR));
|
properties.put(Thing.PROPERTY_MAC_ADDRESS, formatMac(deviceMAC, MAC_DIVISION_CHAR));
|
||||||
properties.put(Thing.PROPERTY_FIRMWARE_VERSION, device.get(CLOUD_PROPERTY_FW).getAsString());
|
properties.put(Thing.PROPERTY_FIRMWARE_VERSION, device.get(CLOUD_JSON_KEY_FW).getAsString());
|
||||||
properties.put(Thing.PROPERTY_HARDWARE_VERSION, device.get(CLOUD_PROPERTY_HW).getAsString());
|
properties.put(Thing.PROPERTY_HARDWARE_VERSION, device.get(CLOUD_JSON_KEY_HW).getAsString());
|
||||||
properties.put(Thing.PROPERTY_MODEL_ID, deviceModel);
|
properties.put(Thing.PROPERTY_MODEL_ID, deviceModel);
|
||||||
properties.put(Thing.PROPERTY_SERIAL_NUMBER, device.get(CLOUD_PROPERTY_ID).getAsString());
|
properties.put(Thing.PROPERTY_SERIAL_NUMBER, device.get(CLOUD_JSON_KEY_ID).getAsString());
|
||||||
|
|
||||||
logger.debug("device {} discovered", deviceModel);
|
logger.debug("device {} discovered", deviceModel);
|
||||||
if (tapoBridge != null) {
|
if (tapoBridge != null) {
|
||||||
@ -190,7 +190,7 @@ public class TapoDiscoveryService extends AbstractDiscoveryService implements Th
|
|||||||
*/
|
*/
|
||||||
protected String getDeviceModel(JsonObject device) {
|
protected String getDeviceModel(JsonObject device) {
|
||||||
try {
|
try {
|
||||||
String deviceModel = device.get(CLOUD_PROPERTY_MODEL).getAsString();
|
String deviceModel = device.get(CLOUD_JSON_KEY_MODEL).getAsString();
|
||||||
deviceModel = deviceModel.replaceAll("\\(.*\\)", ""); // replace (DE)
|
deviceModel = deviceModel.replaceAll("\\(.*\\)", ""); // replace (DE)
|
||||||
deviceModel = deviceModel.replace("Tapo", "");
|
deviceModel = deviceModel.replace("Tapo", "");
|
||||||
deviceModel = deviceModel.replace("Series", "");
|
deviceModel = deviceModel.replace("Series", "");
|
||||||
|
@ -214,23 +214,12 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
|
|||||||
/**
|
/**
|
||||||
* Query Info from Device and refresh deviceInfo
|
* Query Info from Device and refresh deviceInfo
|
||||||
*
|
*
|
||||||
|
*
|
||||||
* @param ignoreGap ignore gap to last query. query anyway
|
* @param ignoreGap ignore gap to last query. query anyway
|
||||||
*/
|
*/
|
||||||
public void queryInfo(boolean ignoreGap) {
|
public void queryInfo(boolean ignoreGap) {
|
||||||
logger.trace("({}) DeviceConnetor_queryInfo from '{}'", uid, deviceURL);
|
logger.trace("({}) DeviceConnetor_queryInfo from '{}'", uid, deviceURL);
|
||||||
long now = System.currentTimeMillis();
|
queryCommand(DEVICE_CMD_GETINFO, ignoreGap);
|
||||||
if (ignoreGap || now > this.lastQuery + TAPO_SEND_MIN_GAP_MS) {
|
|
||||||
this.lastQuery = now;
|
|
||||||
|
|
||||||
/* create payload */
|
|
||||||
PayloadBuilder plBuilder = new PayloadBuilder();
|
|
||||||
plBuilder.method = DEVICE_CMD_GETINFO;
|
|
||||||
String payload = plBuilder.getPayload();
|
|
||||||
|
|
||||||
sendSecurePasstrhroug(payload, DEVICE_CMD_GETINFO);
|
|
||||||
} else {
|
|
||||||
logger.debug("({}) command not sent becauso of min_gap: {}", uid, now + " <- " + lastQuery);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -239,27 +228,37 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
|
|||||||
@Override
|
@Override
|
||||||
public void queryChildDevices() {
|
public void queryChildDevices() {
|
||||||
logger.trace("({}) DeviceConnetor_queryChildDevices from '{}'", uid, deviceURL);
|
logger.trace("({}) DeviceConnetor_queryChildDevices from '{}'", uid, deviceURL);
|
||||||
|
queryCommand(DEVICE_CMD_CHILD_DEVICE_LIST, false);
|
||||||
/* 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
|
* Get energy usage from device
|
||||||
*/
|
*/
|
||||||
public void getEnergyUsage() {
|
public void getEnergyUsage() {
|
||||||
logger.trace("({}) DeviceConnetor_getEnergyUsage from '{}'", uid, deviceURL);
|
queryCommand(DEVICE_CMD_GETENERGY, true);
|
||||||
|
}
|
||||||
|
|
||||||
/* create payload */
|
/**
|
||||||
PayloadBuilder plBuilder = new PayloadBuilder();
|
* Send Custom DeviceQuery
|
||||||
plBuilder.method = DEVICE_CMD_GETENERGY;
|
*
|
||||||
String payload = plBuilder.getPayload();
|
* @param queryCommand Command to be queried
|
||||||
|
* @param ignoreGap ignore gap to last query. query anyway
|
||||||
|
*/
|
||||||
|
public void queryCommand(String queryCommand, boolean ignoreGap) {
|
||||||
|
logger.trace("({}) DeviceConnetor_queryCommand '{}' from '{}'", uid, queryCommand, deviceURL);
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
if (ignoreGap || now > this.lastQuery + TAPO_SEND_MIN_GAP_MS) {
|
||||||
|
this.lastQuery = now;
|
||||||
|
|
||||||
sendSecurePasstrhroug(payload, DEVICE_CMD_GETENERGY);
|
/* create payload */
|
||||||
|
PayloadBuilder plBuilder = new PayloadBuilder();
|
||||||
|
plBuilder.method = queryCommand;
|
||||||
|
String payload = plBuilder.getPayload();
|
||||||
|
|
||||||
|
sendSecurePasstrhroug(payload, queryCommand);
|
||||||
|
} else {
|
||||||
|
logger.debug("({}) command not sent because of min_gap: {}", uid, now + " <- " + lastQuery);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -314,7 +313,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
|
|||||||
@Override
|
@Override
|
||||||
protected void handleDeviceResult(String responseBody) {
|
protected void handleDeviceResult(String responseBody) {
|
||||||
JsonObject jsnResult = getJsonFromResponse(responseBody);
|
JsonObject jsnResult = getJsonFromResponse(responseBody);
|
||||||
if (jsnResult.has(DEVICE_PROPERTY_ID)) {
|
if (jsnResult.has(JSON_KEY_ID)) {
|
||||||
this.deviceInfo = new TapoDeviceInfo(jsnResult);
|
this.deviceInfo = new TapoDeviceInfo(jsnResult);
|
||||||
this.device.setDeviceInfo(deviceInfo);
|
this.device.setDeviceInfo(deviceInfo);
|
||||||
} else {
|
} else {
|
||||||
@ -332,7 +331,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
|
|||||||
@Override
|
@Override
|
||||||
protected void handleEnergyResult(String responseBody) {
|
protected void handleEnergyResult(String responseBody) {
|
||||||
JsonObject jsnResult = getJsonFromResponse(responseBody);
|
JsonObject jsnResult = getJsonFromResponse(responseBody);
|
||||||
if (jsnResult.has(ENERGY_PROPERTY_POWER)) {
|
if (jsnResult.has(JSON_KEY_ENERGY_POWER)) {
|
||||||
this.energyData = new TapoEnergyData(jsnResult);
|
this.energyData = new TapoEnergyData(jsnResult);
|
||||||
this.device.setEnergyData(energyData);
|
this.device.setEnergyData(energyData);
|
||||||
} else {
|
} else {
|
||||||
@ -349,7 +348,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
|
|||||||
@Override
|
@Override
|
||||||
protected void handleChildDevices(String responseBody) {
|
protected void handleChildDevices(String responseBody) {
|
||||||
JsonObject jsnResult = getJsonFromResponse(responseBody);
|
JsonObject jsnResult = getJsonFromResponse(responseBody);
|
||||||
if (jsnResult.has(CHILD_PROPERTY_START_INDEX)) {
|
if (jsnResult.has(JSON_KEY_CHILD_START_INDEX)) {
|
||||||
this.childData = Objects.requireNonNull(GSON.fromJson(jsnResult, TapoChildData.class));
|
this.childData = Objects.requireNonNull(GSON.fromJson(jsnResult, TapoChildData.class));
|
||||||
this.device.setChildData(childData);
|
this.device.setChildData(childData);
|
||||||
} else {
|
} else {
|
||||||
|
@ -98,62 +98,64 @@ public class TapoThingConstants {
|
|||||||
SUPPORTED_COLOR_BULB_UIDS, SUPPORTED_LIGHT_STRIP_UIDS)
|
SUPPORTED_COLOR_BULB_UIDS, SUPPORTED_LIGHT_STRIP_UIDS)
|
||||||
.flatMap(Set::stream).collect(Collectors.toSet()));
|
.flatMap(Set::stream).collect(Collectors.toSet()));
|
||||||
|
|
||||||
/*** DEVICE PROPERTY STRINGS (CLOUD) ***/
|
/*** DEVICE JSON STRINGS (CLOUD) ***/
|
||||||
public static final String CLOUD_PROPERTY_ALIAS = "alias";
|
public static final String CLOUD_JSON_KEY_ALIAS = "alias";
|
||||||
public static final String CLOUD_PROPERTY_FW = "fwVer";
|
public static final String CLOUD_JSON_KEY_FW = "fwVer";
|
||||||
public static final String CLOUD_PROPERTY_HW = "deviceHwVer";
|
public static final String CLOUD_JSON_KEY_HW = "deviceHwVer";
|
||||||
public static final String CLOUD_PROPERTY_ID = "deviceId";
|
public static final String CLOUD_JSON_KEY_ID = "deviceId";
|
||||||
public static final String CLOUD_PROPERTY_MAC = "deviceMac";
|
public static final String CLOUD_JSON_KEY_MAC = "deviceMac";
|
||||||
public static final String CLOUD_PROPERTY_MODEL = "deviceName"; // use name cause modell returns different values
|
public static final String CLOUD_JSON_KEY_MODEL = "deviceName"; // use name cause modell returns different values
|
||||||
public static final String CLOUD_PROPERTY_NAME = "deviceName";
|
public static final String CLOUD_JSON_KEY_NAME = "deviceName";
|
||||||
public static final String CLOUD_PROPERTY_REGION = "deviceRegion";
|
public static final String CLOUD_JSON_KEY_REGION = "deviceRegion";
|
||||||
public static final String CLOUD_PROPERTY_SERVER_URL = "appServerUrl";
|
public static final String CLOUD_JSON_KEY_SERVER_URL = "appServerUrl";
|
||||||
public static final String CLOUD_PROPERTY_TYPE = "deviceType";
|
public static final String CLOUD_JSON_KEY_TYPE = "deviceType";
|
||||||
|
|
||||||
/*** DEVICE PROPERTY STRINGS (DEVICE) ***/
|
/*** DEVICE JSON STRINGS (DEVICE) ***/
|
||||||
public static final String DEVICE_PROPERTY_BRIGHTNES = "brightness";
|
public static final String JSON_KEY_BRIGHTNES = "brightness";
|
||||||
public static final String DEVICE_PROPERTY_COLORTEMP = "color_temp";
|
public static final String JSON_KEY_COLORTEMP = "color_temp";
|
||||||
public static final String DEVICE_PROPERTY_FW = "fw_ver";
|
public static final String JSON_KEY_FW = "fw_ver";
|
||||||
public static final String DEVICE_PROPERTY_HUE = "hue";
|
public static final String JSON_KEY_HUE = "hue";
|
||||||
public static final String DEVICE_PROPERTY_HW = "hw_ver";
|
public static final String JSON_KEY_HW_VER = "hw_ver";
|
||||||
public static final String DEVICE_PROPERTY_ID = "device_id";
|
public static final String JSON_KEY_ID = "device_id";
|
||||||
public static final String DEVICE_PROPERTY_IP = "ip";
|
public static final String JSON_KEY_IP = "ip";
|
||||||
public static final String DEVICE_PROPERTY_MAC = "mac";
|
public static final String JSON_KEY_MAC = "mac";
|
||||||
public static final String DEVICE_PROPERTY_MODEL = "model";
|
public static final String JSON_KEY_MODEL = "model";
|
||||||
public static final String DEVICE_PROPERTY_NICKNAME = "nickname";
|
public static final String JSON_KEY_NICKNAME = "nickname";
|
||||||
public static final String DEVICE_PROPERTY_ON = "device_on";
|
public static final String JSON_KEY_ON = "device_on";
|
||||||
public static final String DEVICE_PROPERTY_ONTIME = "on_time";
|
public static final String JSON_KEY_ONTIME = "on_time";
|
||||||
public static final String DEVICE_PROPERTY_OVERHEAT = "overheated";
|
public static final String JSON_KEY_OVERHEAT = "overheated";
|
||||||
public static final String DEVICE_PROPERTY_REGION = "region";
|
public static final String JSON_KEY_REGION = "region";
|
||||||
public static final String DEVICE_PROPERTY_SATURATION = "saturation";
|
public static final String JSON_KEY_SATURATION = "saturation";
|
||||||
public static final String DEVICE_PROPERTY_SIGNAL = "signal_level";
|
public static final String JSON_KEY_SIGNAL_LEVEL = "signal_level";
|
||||||
public static final String DEVICE_PROPERTY_SIGNAL_RSSI = "rssi";
|
public static final String JSON_KEY_RSSI = "rssi";
|
||||||
public static final String DEVICE_PROPERTY_TYPE = "type";
|
public static final String JSON_KEY_TYPE = "type";
|
||||||
public static final String DEVICE_PROPERTY_USAGE_7 = "time_usage_past7";
|
public static final String JSON_KEY_USAGE_7 = "time_usage_past7";
|
||||||
public static final String DEVICE_PROPERTY_USAGE_30 = "time_usage_past30";
|
public static final String JSON_KEY_USAGE_30 = "time_usage_past30";
|
||||||
public static final String DEVICE_PROPERTY_USAGE_TODAY = "time_usage_today";
|
public static final String JSON_KEY_USAGE_TODAY = "time_usage_today";
|
||||||
public static final String DEVICE_REPRESENTATION_PROPERTY = "macAddress";
|
public static final String DEVICE_REPRESENTATION_PROPERTY = "macAddress";
|
||||||
// lightning effects
|
// lightning effects
|
||||||
public static final String DEVICE_PROPERTY_EFFECT = "lighting_effect";
|
public static final String JSON_KEY_LIGHTNING_EFFECT = "lighting_effect";
|
||||||
public static final String PROPERTY_LIGHTNING_EFFECT_BRIGHNTESS = "brightness";
|
public static final String JSON_KEY_LIGHTNING_EFFECT_BRIGHNTESS = "brightness";
|
||||||
public static final String PROPERTY_LIGHTNING_EFFECT_COLORTEMPRANGE = "color_temp_range";
|
public static final String JSON_KEY_LIGHTNING_EFFECT_COLORTEMPRANGE = "color_temp_range";
|
||||||
public static final String PROPERTY_LIGHTNING_EFFECT_CUSTOM = "custom";
|
public static final String JSON_KEY_LIGHTNING_EFFECT_CUSTOM = "custom";
|
||||||
public static final String PROPERTY_LIGHTNING_EFFECT_DISPLAYCOLORS = "displayColors";
|
public static final String JSON_KEY_LIGHTNING_EFFECT_DISPLAYCOLORS = "displayColors";
|
||||||
public static final String PROPERTY_LIGHTNING_EFFECT_ENABLE = "enable";
|
public static final String JSON_KEY_LIGHTNING_EFFECT_ENABLE = "enable";
|
||||||
public static final String PROPERTY_LIGHTNING_EFFECT_ID = "id";
|
public static final String JSON_KEY_LIGHTNING_EFFECT_ID = "id";
|
||||||
public static final String PROPERTY_LIGHTNING_EFFECT_NAME = "name";
|
public static final String JSON_KEY_LIGHTNING_EFFECT_NAME = "name";
|
||||||
|
public static final String JSON_KEY_LIGHTNING_DYNAMIC_ENABLE = "dynamic_light_effect_enable";
|
||||||
|
public static final String JSON_KEY_LIGHTNING_DYNAMIC_ID = "dynamic_light_effect_id";
|
||||||
// energy monitoring
|
// energy monitoring
|
||||||
public static final String ENERGY_PROPERTY_POWER = "current_power";
|
public static final String JSON_KEY_ENERGY_POWER = "current_power";
|
||||||
public static final String ENERGY_PROPERTY_RUNTIME_TODAY = "today_runtime";
|
public static final String JSON_KEY_ENERGY_RUNTIME_TODAY = "today_runtime";
|
||||||
public static final String ENERGY_PROPERTY_RUNTIME_MONTH = "month_runtime";
|
public static final String JSON_KEY_ENERGY_RUNTIME_MONTH = "month_runtime";
|
||||||
public static final String ENERGY_PROPERTY_ENERGY_TODAY = "today_energy";
|
public static final String JSON_KEY_ENERGY_ENERGY_TODAY = "today_energy";
|
||||||
public static final String ENERGY_PROPERTY_ENERGY_MONTH = "month_energy";
|
public static final String JSON_KEY_ENERGY_ENERGY_MONTH = "month_energy";
|
||||||
public static final String ENERGY_PROPERTY_PAST24H = "past24h";
|
public static final String JSON_KEY_ENERGY_PAST24H = "past24h";
|
||||||
public static final String ENERGY_PROPERTY_PAST7D = "past7d";
|
public static final String JSON_KEY_ENERGY_PAST7D = "past7d";
|
||||||
public static final String ENERGY_PROPERTY_PAST30D = "past30d";
|
public static final String JSON_KEY_ENERGY_PAST30D = "past30d";
|
||||||
public static final String ENERGY_PROPERTY_PAST1Y = "past1y";
|
public static final String JSON_KEY_ENERGY_PAST1Y = "past1y";
|
||||||
// childs management
|
// childs management
|
||||||
public static final String CHILD_PROPERTY_START_INDEX = "start_index";
|
public static final String JSON_KEY_CHILD_START_INDEX = "start_index";
|
||||||
|
|
||||||
/*** DEVICE SETTINGS ***/
|
/*** DEVICE SETTINGS ***/
|
||||||
public static final Integer BULB_MIN_COLORTEMP = 2500;
|
public static final Integer BULB_MIN_COLORTEMP = 2500;
|
||||||
@ -178,12 +180,10 @@ public class TapoThingConstants {
|
|||||||
public static final String CHANNEL_NRG_USAGE_TODAY = "todayEnergyUsage";
|
public static final String CHANNEL_NRG_USAGE_TODAY = "todayEnergyUsage";
|
||||||
public static final String CHANNEL_NRG_RUNTIME_TODAY = "todayRuntime";
|
public static final String CHANNEL_NRG_RUNTIME_TODAY = "todayRuntime";
|
||||||
// channel group effect
|
// channel group effect
|
||||||
public static final String CHANNEL_GROUP_EFFECTS = "effect";
|
public static final String CHANNEL_GROUP_EFFECTS = "effects";
|
||||||
public static final String CHANNEL_FX_BRIGHTNESS = "brightness";
|
public static final String CHANNEL_FX_BRIGHTNESS = "fxBrightness";
|
||||||
public static final String CHANNEL_FX_COLORS = "displayColors";
|
public static final String CHANNEL_FX_COLORS = "fxColors";
|
||||||
public static final String CHANNEL_FX_CUSTOM = "custom";
|
public static final String CHANNEL_FX_NAME = "fxName";
|
||||||
public static final String CHANNEL_FX_ENABLE = "enable";
|
|
||||||
public static final String CHANNEL_FX_NAME = "name";
|
|
||||||
|
|
||||||
/*** LIST OF PROPERTY NAMES ***/
|
/*** LIST OF PROPERTY NAMES ***/
|
||||||
public static final String PROPERTY_FAMILY = "deviceFamily";
|
public static final String PROPERTY_FAMILY = "deviceFamily";
|
||||||
|
@ -72,7 +72,7 @@ public class TapoLightStrip extends TapoDevice {
|
|||||||
} else {
|
} else {
|
||||||
switch (channel) {
|
switch (channel) {
|
||||||
case CHANNEL_OUTPUT:
|
case CHANNEL_OUTPUT:
|
||||||
connector.sendDeviceCommand(DEVICE_PROPERTY_ON, command == OnOffType.ON);
|
connector.sendDeviceCommand(JSON_KEY_ON, command == OnOffType.ON);
|
||||||
refreshInfo = true;
|
refreshInfo = true;
|
||||||
break;
|
break;
|
||||||
case CHANNEL_BRIGHTNESS:
|
case CHANNEL_BRIGHTNESS:
|
||||||
@ -117,11 +117,11 @@ public class TapoLightStrip extends TapoDevice {
|
|||||||
protected void setBrightness(Integer newBrightness) {
|
protected void setBrightness(Integer newBrightness) {
|
||||||
/* switch off if 0 */
|
/* switch off if 0 */
|
||||||
if (newBrightness == 0) {
|
if (newBrightness == 0) {
|
||||||
connector.sendDeviceCommand(DEVICE_PROPERTY_ON, false);
|
connector.sendDeviceCommand(JSON_KEY_ON, false);
|
||||||
} else {
|
} else {
|
||||||
HashMap<String, Object> newState = new HashMap<>();
|
HashMap<String, Object> newState = new HashMap<>();
|
||||||
newState.put(DEVICE_PROPERTY_ON, true);
|
newState.put(JSON_KEY_ON, true);
|
||||||
newState.put(DEVICE_PROPERTY_BRIGHTNES, newBrightness);
|
newState.put(JSON_KEY_BRIGHTNES, newBrightness);
|
||||||
connector.sendDeviceCommands(newState);
|
connector.sendDeviceCommands(newState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,10 +133,10 @@ public class TapoLightStrip extends TapoDevice {
|
|||||||
*/
|
*/
|
||||||
protected void setColor(HSBType command) {
|
protected void setColor(HSBType command) {
|
||||||
HashMap<String, Object> newState = new HashMap<>();
|
HashMap<String, Object> newState = new HashMap<>();
|
||||||
newState.put(DEVICE_PROPERTY_ON, true);
|
newState.put(JSON_KEY_ON, true);
|
||||||
newState.put(DEVICE_PROPERTY_HUE, command.getHue());
|
newState.put(JSON_KEY_HUE, command.getHue());
|
||||||
newState.put(DEVICE_PROPERTY_SATURATION, command.getSaturation());
|
newState.put(JSON_KEY_SATURATION, command.getSaturation());
|
||||||
newState.put(DEVICE_PROPERTY_BRIGHTNES, command.getBrightness());
|
newState.put(JSON_KEY_BRIGHTNES, command.getBrightness());
|
||||||
connector.sendDeviceCommands(newState);
|
connector.sendDeviceCommands(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,8 +148,8 @@ public class TapoLightStrip extends TapoDevice {
|
|||||||
protected void setColorTemp(Integer colorTemp) {
|
protected void setColorTemp(Integer colorTemp) {
|
||||||
HashMap<String, Object> newState = new HashMap<>();
|
HashMap<String, Object> newState = new HashMap<>();
|
||||||
colorTemp = limitVal(colorTemp, BULB_MIN_COLORTEMP, BULB_MAX_COLORTEMP);
|
colorTemp = limitVal(colorTemp, BULB_MIN_COLORTEMP, BULB_MAX_COLORTEMP);
|
||||||
newState.put(DEVICE_PROPERTY_ON, true);
|
newState.put(JSON_KEY_ON, true);
|
||||||
newState.put(DEVICE_PROPERTY_COLORTEMP, colorTemp);
|
newState.put(JSON_KEY_COLORTEMP, colorTemp);
|
||||||
connector.sendDeviceCommands(newState);
|
connector.sendDeviceCommands(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,9 +176,6 @@ public class TapoLightStrip extends TapoDevice {
|
|||||||
case CHANNEL_FX_NAME:
|
case CHANNEL_FX_NAME:
|
||||||
lightEffect.setName(command.toString());
|
lightEffect.setName(command.toString());
|
||||||
break;
|
break;
|
||||||
case CHANNEL_FX_ENABLE:
|
|
||||||
lightEffect.setEnable(command == OnOffType.ON);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
setLightEffects(lightEffect);
|
setLightEffects(lightEffect);
|
||||||
}
|
}
|
||||||
@ -190,14 +187,14 @@ public class TapoLightStrip extends TapoDevice {
|
|||||||
*/
|
*/
|
||||||
protected void setLightEffects(TapoLightEffect lightEffect) {
|
protected void setLightEffects(TapoLightEffect lightEffect) {
|
||||||
JsonObject newEffect = new JsonObject();
|
JsonObject newEffect = new JsonObject();
|
||||||
newEffect.addProperty(PROPERTY_LIGHTNING_EFFECT_ENABLE, lightEffect.getEnable());
|
newEffect.addProperty(JSON_KEY_LIGHTNING_EFFECT_ENABLE, lightEffect.getEnable());
|
||||||
newEffect.addProperty(PROPERTY_LIGHTNING_EFFECT_NAME, lightEffect.getName());
|
newEffect.addProperty(JSON_KEY_LIGHTNING_EFFECT_NAME, lightEffect.getName());
|
||||||
newEffect.addProperty(PROPERTY_LIGHTNING_EFFECT_BRIGHNTESS, lightEffect.getBrightness());
|
newEffect.addProperty(JSON_KEY_LIGHTNING_EFFECT_BRIGHNTESS, lightEffect.getBrightness());
|
||||||
newEffect.addProperty(PROPERTY_LIGHTNING_EFFECT_COLORTEMPRANGE, lightEffect.getColorTempRange().toString());
|
newEffect.addProperty(JSON_KEY_LIGHTNING_EFFECT_COLORTEMPRANGE, lightEffect.getColorTempRange().toString());
|
||||||
newEffect.addProperty(PROPERTY_LIGHTNING_EFFECT_DISPLAYCOLORS, lightEffect.getDisplayColors().toString());
|
newEffect.addProperty(JSON_KEY_LIGHTNING_EFFECT_DISPLAYCOLORS, lightEffect.getDisplayColors().toString());
|
||||||
newEffect.addProperty(PROPERTY_LIGHTNING_EFFECT_CUSTOM, lightEffect.getCustom());
|
newEffect.addProperty(JSON_KEY_LIGHTNING_EFFECT_CUSTOM, lightEffect.getCustom());
|
||||||
|
|
||||||
connector.sendDeviceCommand(DEVICE_PROPERTY_EFFECT, newEffect.toString());
|
connector.sendDeviceCommand(JSON_KEY_LIGHTNING_EFFECT, newEffect.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -224,7 +221,5 @@ public class TapoLightStrip extends TapoDevice {
|
|||||||
publishState(getChannelID(CHANNEL_GROUP_EFFECTS, CHANNEL_FX_BRIGHTNESS),
|
publishState(getChannelID(CHANNEL_GROUP_EFFECTS, CHANNEL_FX_BRIGHTNESS),
|
||||||
getPercentType(lightEffect.getBrightness()));
|
getPercentType(lightEffect.getBrightness()));
|
||||||
publishState(getChannelID(CHANNEL_GROUP_EFFECTS, CHANNEL_FX_NAME), getStringType(lightEffect.getName()));
|
publishState(getChannelID(CHANNEL_GROUP_EFFECTS, CHANNEL_FX_NAME), getStringType(lightEffect.getName()));
|
||||||
publishState(getChannelID(CHANNEL_GROUP_EFFECTS, CHANNEL_FX_ENABLE), getOnOffType(lightEffect.getEnable()));
|
|
||||||
publishState(getChannelID(CHANNEL_GROUP_EFFECTS, CHANNEL_FX_CUSTOM), getOnOffType(lightEffect.getCustom()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import java.util.HashMap;
|
|||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.openhab.binding.tapocontrol.internal.structures.TapoDeviceInfo;
|
import org.openhab.binding.tapocontrol.internal.structures.TapoDeviceInfo;
|
||||||
|
import org.openhab.binding.tapocontrol.internal.structures.TapoLightEffect;
|
||||||
import org.openhab.core.library.types.DecimalType;
|
import org.openhab.core.library.types.DecimalType;
|
||||||
import org.openhab.core.library.types.HSBType;
|
import org.openhab.core.library.types.HSBType;
|
||||||
import org.openhab.core.library.types.OnOffType;
|
import org.openhab.core.library.types.OnOffType;
|
||||||
@ -65,7 +66,7 @@ public class TapoSmartBulb extends TapoDevice {
|
|||||||
} else {
|
} else {
|
||||||
switch (channel) {
|
switch (channel) {
|
||||||
case CHANNEL_OUTPUT:
|
case CHANNEL_OUTPUT:
|
||||||
connector.sendDeviceCommand(DEVICE_PROPERTY_ON, command == OnOffType.ON);
|
connector.sendDeviceCommand(JSON_KEY_ON, command == OnOffType.ON);
|
||||||
refreshInfo = true;
|
refreshInfo = true;
|
||||||
break;
|
break;
|
||||||
case CHANNEL_BRIGHTNESS:
|
case CHANNEL_BRIGHTNESS:
|
||||||
@ -90,6 +91,9 @@ public class TapoSmartBulb extends TapoDevice {
|
|||||||
refreshInfo = true;
|
refreshInfo = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CHANNEL_FX_NAME:
|
||||||
|
setLightEffect(command.toString());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
logger.warn("({}) command type '{}' not supported for channel '{}'", uid, command.toString(),
|
logger.warn("({}) command type '{}' not supported for channel '{}'", uid, command.toString(),
|
||||||
channelUID.getId());
|
channelUID.getId());
|
||||||
@ -110,11 +114,11 @@ public class TapoSmartBulb extends TapoDevice {
|
|||||||
protected void setBrightness(Integer newBrightness) {
|
protected void setBrightness(Integer newBrightness) {
|
||||||
/* switch off if 0 */
|
/* switch off if 0 */
|
||||||
if (newBrightness == 0) {
|
if (newBrightness == 0) {
|
||||||
connector.sendDeviceCommand(DEVICE_PROPERTY_ON, false);
|
connector.sendDeviceCommand(JSON_KEY_ON, false);
|
||||||
} else {
|
} else {
|
||||||
HashMap<String, Object> newState = new HashMap<>();
|
HashMap<String, Object> newState = new HashMap<>();
|
||||||
newState.put(DEVICE_PROPERTY_ON, true);
|
newState.put(JSON_KEY_ON, true);
|
||||||
newState.put(DEVICE_PROPERTY_BRIGHTNES, newBrightness);
|
newState.put(JSON_KEY_BRIGHTNES, newBrightness);
|
||||||
connector.sendDeviceCommands(newState);
|
connector.sendDeviceCommands(newState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,10 +130,11 @@ public class TapoSmartBulb extends TapoDevice {
|
|||||||
*/
|
*/
|
||||||
protected void setColor(HSBType command) {
|
protected void setColor(HSBType command) {
|
||||||
HashMap<String, Object> newState = new HashMap<>();
|
HashMap<String, Object> newState = new HashMap<>();
|
||||||
newState.put(DEVICE_PROPERTY_ON, true);
|
newState.put(JSON_KEY_ON, true);
|
||||||
newState.put(DEVICE_PROPERTY_HUE, command.getHue().intValue());
|
newState.put(JSON_KEY_HUE, command.getHue().intValue());
|
||||||
newState.put(DEVICE_PROPERTY_SATURATION, command.getSaturation().intValue());
|
newState.put(JSON_KEY_SATURATION, command.getSaturation().intValue());
|
||||||
newState.put(DEVICE_PROPERTY_BRIGHTNES, command.getBrightness().intValue());
|
newState.put(JSON_KEY_BRIGHTNES, command.getBrightness().intValue());
|
||||||
|
newState.put(JSON_KEY_LIGHTNING_DYNAMIC_ENABLE, false);
|
||||||
connector.sendDeviceCommands(newState);
|
connector.sendDeviceCommands(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,8 +146,26 @@ public class TapoSmartBulb extends TapoDevice {
|
|||||||
protected void setColorTemp(Integer colorTemp) {
|
protected void setColorTemp(Integer colorTemp) {
|
||||||
HashMap<String, Object> newState = new HashMap<>();
|
HashMap<String, Object> newState = new HashMap<>();
|
||||||
colorTemp = limitVal(colorTemp, BULB_MIN_COLORTEMP, BULB_MAX_COLORTEMP);
|
colorTemp = limitVal(colorTemp, BULB_MIN_COLORTEMP, BULB_MAX_COLORTEMP);
|
||||||
newState.put(DEVICE_PROPERTY_ON, true);
|
newState.put(JSON_KEY_ON, true);
|
||||||
newState.put(DEVICE_PROPERTY_COLORTEMP, colorTemp);
|
newState.put(JSON_KEY_COLORTEMP, colorTemp);
|
||||||
|
connector.sendDeviceCommands(newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set light effect
|
||||||
|
*
|
||||||
|
* @param fxName (String) id of LightEffect
|
||||||
|
*/
|
||||||
|
protected void setLightEffect(String fxName) {
|
||||||
|
HashMap<String, Object> newState = new HashMap<>();
|
||||||
|
if (fxName.length() > 0) {
|
||||||
|
newState.put(JSON_KEY_ON, true);
|
||||||
|
newState.put(JSON_KEY_LIGHTNING_DYNAMIC_ENABLE, true);
|
||||||
|
newState.put(JSON_KEY_LIGHTNING_DYNAMIC_ID, fxName);
|
||||||
|
} else {
|
||||||
|
newState.put(JSON_KEY_LIGHTNING_DYNAMIC_ENABLE, false);
|
||||||
|
newState.put(JSON_KEY_LIGHTNING_DYNAMIC_ID, "");
|
||||||
|
}
|
||||||
connector.sendDeviceCommands(newState);
|
connector.sendDeviceCommands(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,5 +188,20 @@ public class TapoSmartBulb extends TapoDevice {
|
|||||||
publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_ONTIME),
|
publishState(getChannelID(CHANNEL_GROUP_DEVICE, CHANNEL_ONTIME),
|
||||||
getTimeType(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_OVERHEAT), getOnOffType(deviceInfo.isOverheated()));
|
||||||
|
|
||||||
|
updateLightEffectChannels(deviceInfo.getLightEffect());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set light effect channels
|
||||||
|
*
|
||||||
|
* @param lightEffect
|
||||||
|
*/
|
||||||
|
protected void updateLightEffectChannels(TapoLightEffect lightEffect) {
|
||||||
|
String fxId = "";
|
||||||
|
if (lightEffect.getEnable().equals(true)) {
|
||||||
|
fxId = lightEffect.getId();
|
||||||
|
}
|
||||||
|
publishState(getChannelID(CHANNEL_GROUP_EFFECTS, CHANNEL_FX_NAME), getStringType(fxId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,11 +61,11 @@ public class TapoSmartPlug extends TapoDevice {
|
|||||||
} else if (command instanceof OnOffType) {
|
} else if (command instanceof OnOffType) {
|
||||||
Boolean targetState = command == OnOffType.ON ? Boolean.TRUE : Boolean.FALSE;
|
Boolean targetState = command == OnOffType.ON ? Boolean.TRUE : Boolean.FALSE;
|
||||||
if (CHANNEL_OUTPUT.equals(id)) { // Command is sent to the device output
|
if (CHANNEL_OUTPUT.equals(id)) { // Command is sent to the device output
|
||||||
connector.sendDeviceCommand(DEVICE_PROPERTY_ON, targetState);
|
connector.sendDeviceCommand(JSON_KEY_ON, targetState);
|
||||||
refreshInfo = true;
|
refreshInfo = true;
|
||||||
} else if (id.startsWith(CHANNEL_OUTPUT)) { // Command is sent to a child's device output
|
} else if (id.startsWith(CHANNEL_OUTPUT)) { // Command is sent to a child's device output
|
||||||
Integer index = Integer.valueOf(id.replace(CHANNEL_OUTPUT, ""));
|
Integer index = Integer.valueOf(id.replace(CHANNEL_OUTPUT, ""));
|
||||||
connector.sendChildCommand(index, DEVICE_PROPERTY_ON, targetState);
|
connector.sendChildCommand(index, JSON_KEY_ON, targetState);
|
||||||
refreshInfo = true;
|
refreshInfo = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -66,7 +66,7 @@ public class TapoUniversalDevice extends TapoDevice {
|
|||||||
} else {
|
} else {
|
||||||
switch (channel) {
|
switch (channel) {
|
||||||
case CHANNEL_OUTPUT:
|
case CHANNEL_OUTPUT:
|
||||||
connector.sendDeviceCommand(DEVICE_PROPERTY_ON, command == OnOffType.ON);
|
connector.sendDeviceCommand(JSON_KEY_ON, command == OnOffType.ON);
|
||||||
refreshInfo = true;
|
refreshInfo = true;
|
||||||
break;
|
break;
|
||||||
case CHANNEL_BRIGHTNESS:
|
case CHANNEL_BRIGHTNESS:
|
||||||
@ -121,11 +121,11 @@ public class TapoUniversalDevice extends TapoDevice {
|
|||||||
protected void setBrightness(Integer newBrightness) {
|
protected void setBrightness(Integer newBrightness) {
|
||||||
/* switch off if 0 */
|
/* switch off if 0 */
|
||||||
if (newBrightness == 0) {
|
if (newBrightness == 0) {
|
||||||
connector.sendDeviceCommand(DEVICE_PROPERTY_ON, false);
|
connector.sendDeviceCommand(JSON_KEY_ON, false);
|
||||||
} else {
|
} else {
|
||||||
HashMap<String, Object> newState = new HashMap<>();
|
HashMap<String, Object> newState = new HashMap<>();
|
||||||
newState.put(DEVICE_PROPERTY_ON, true);
|
newState.put(JSON_KEY_ON, true);
|
||||||
newState.put(DEVICE_PROPERTY_BRIGHTNES, newBrightness);
|
newState.put(JSON_KEY_BRIGHTNES, newBrightness);
|
||||||
connector.sendDeviceCommands(newState);
|
connector.sendDeviceCommands(newState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,10 +137,10 @@ public class TapoUniversalDevice extends TapoDevice {
|
|||||||
*/
|
*/
|
||||||
protected void setColor(HSBType command) {
|
protected void setColor(HSBType command) {
|
||||||
HashMap<String, Object> newState = new HashMap<>();
|
HashMap<String, Object> newState = new HashMap<>();
|
||||||
newState.put(DEVICE_PROPERTY_ON, true);
|
newState.put(JSON_KEY_ON, true);
|
||||||
newState.put(DEVICE_PROPERTY_HUE, command.getHue());
|
newState.put(JSON_KEY_HUE, command.getHue());
|
||||||
newState.put(DEVICE_PROPERTY_SATURATION, command.getSaturation());
|
newState.put(JSON_KEY_SATURATION, command.getSaturation());
|
||||||
newState.put(DEVICE_PROPERTY_BRIGHTNES, command.getBrightness());
|
newState.put(JSON_KEY_BRIGHTNES, command.getBrightness());
|
||||||
connector.sendDeviceCommands(newState);
|
connector.sendDeviceCommands(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,8 +152,8 @@ public class TapoUniversalDevice extends TapoDevice {
|
|||||||
protected void setColorTemp(Integer colorTemp) {
|
protected void setColorTemp(Integer colorTemp) {
|
||||||
HashMap<String, Object> newState = new HashMap<>();
|
HashMap<String, Object> newState = new HashMap<>();
|
||||||
colorTemp = limitVal(colorTemp, BULB_MIN_COLORTEMP, BULB_MAX_COLORTEMP);
|
colorTemp = limitVal(colorTemp, BULB_MIN_COLORTEMP, BULB_MAX_COLORTEMP);
|
||||||
newState.put(DEVICE_PROPERTY_ON, true);
|
newState.put(JSON_KEY_ON, true);
|
||||||
newState.put(DEVICE_PROPERTY_COLORTEMP, colorTemp);
|
newState.put(JSON_KEY_COLORTEMP, colorTemp);
|
||||||
connector.sendDeviceCommands(newState);
|
connector.sendDeviceCommands(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,27 +84,27 @@ public class TapoDeviceInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setData() {
|
private void setData() {
|
||||||
this.brightness = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_BRIGHTNES);
|
this.brightness = jsonObjectToInt(jsonObject, JSON_KEY_BRIGHTNES);
|
||||||
this.colorTemp = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_COLORTEMP, BULB_MIN_COLORTEMP);
|
this.colorTemp = jsonObjectToInt(jsonObject, JSON_KEY_COLORTEMP, BULB_MIN_COLORTEMP);
|
||||||
this.deviceId = jsonObjectToString(jsonObject, DEVICE_PROPERTY_ID);
|
this.deviceId = jsonObjectToString(jsonObject, JSON_KEY_ID);
|
||||||
this.deviceOn = jsonObjectToBool(jsonObject, DEVICE_PROPERTY_ON);
|
this.deviceOn = jsonObjectToBool(jsonObject, JSON_KEY_ON);
|
||||||
this.fwVer = jsonObjectToString(jsonObject, DEVICE_PROPERTY_FW);
|
this.fwVer = jsonObjectToString(jsonObject, JSON_KEY_FW);
|
||||||
this.hue = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_HUE);
|
this.hue = jsonObjectToInt(jsonObject, JSON_KEY_HUE);
|
||||||
this.hwVer = jsonObjectToString(jsonObject, DEVICE_PROPERTY_HW);
|
this.hwVer = jsonObjectToString(jsonObject, JSON_KEY_HW_VER);
|
||||||
this.ip = jsonObjectToString(jsonObject, DEVICE_PROPERTY_IP);
|
this.ip = jsonObjectToString(jsonObject, JSON_KEY_IP);
|
||||||
this.mac = jsonObjectToString(jsonObject, DEVICE_PROPERTY_MAC);
|
this.mac = jsonObjectToString(jsonObject, JSON_KEY_MAC);
|
||||||
this.model = jsonObjectToString(jsonObject, DEVICE_PROPERTY_MODEL);
|
this.model = jsonObjectToString(jsonObject, JSON_KEY_MODEL);
|
||||||
this.nickname = jsonObjectToString(jsonObject, DEVICE_PROPERTY_NICKNAME);
|
this.nickname = jsonObjectToString(jsonObject, JSON_KEY_NICKNAME);
|
||||||
this.onTime = jsonObjectToNumber(jsonObject, DEVICE_PROPERTY_ONTIME);
|
this.onTime = jsonObjectToNumber(jsonObject, JSON_KEY_ONTIME);
|
||||||
this.overheated = jsonObjectToBool(jsonObject, DEVICE_PROPERTY_OVERHEAT);
|
this.overheated = jsonObjectToBool(jsonObject, JSON_KEY_OVERHEAT);
|
||||||
this.region = jsonObjectToString(jsonObject, DEVICE_PROPERTY_REGION);
|
this.region = jsonObjectToString(jsonObject, JSON_KEY_REGION);
|
||||||
this.saturation = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_SATURATION);
|
this.saturation = jsonObjectToInt(jsonObject, JSON_KEY_SATURATION);
|
||||||
this.signalLevel = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_SIGNAL);
|
this.signalLevel = jsonObjectToInt(jsonObject, JSON_KEY_SIGNAL_LEVEL);
|
||||||
this.rssi = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_SIGNAL_RSSI);
|
this.rssi = jsonObjectToInt(jsonObject, JSON_KEY_RSSI);
|
||||||
this.timeUsagePast7 = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_USAGE_7);
|
this.timeUsagePast7 = jsonObjectToInt(jsonObject, JSON_KEY_USAGE_7);
|
||||||
this.timeUsagePast30 = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_USAGE_30);
|
this.timeUsagePast30 = jsonObjectToInt(jsonObject, JSON_KEY_USAGE_30);
|
||||||
this.timeUsageToday = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_USAGE_TODAY);
|
this.timeUsageToday = jsonObjectToInt(jsonObject, JSON_KEY_USAGE_TODAY);
|
||||||
this.type = jsonObjectToString(jsonObject, DEVICE_PROPERTY_TYPE);
|
this.type = jsonObjectToString(jsonObject, JSON_KEY_TYPE);
|
||||||
|
|
||||||
if (this.hasLightEffect()) {
|
if (this.hasLightEffect()) {
|
||||||
this.lightEffect = lightEffect.setData(jsonObject);
|
this.lightEffect = lightEffect.setData(jsonObject);
|
||||||
@ -117,7 +117,7 @@ public class TapoDeviceInfo {
|
|||||||
*
|
*
|
||||||
************************************/
|
************************************/
|
||||||
public Boolean hasLightEffect() {
|
public Boolean hasLightEffect() {
|
||||||
return this.jsonObject.has(DEVICE_PROPERTY_EFFECT);
|
return this.jsonObject.has(JSON_KEY_LIGHTNING_EFFECT) || this.jsonObject.has(JSON_KEY_LIGHTNING_DYNAMIC_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
|
@ -60,7 +60,7 @@ public class TapoEnergyData {
|
|||||||
*/
|
*/
|
||||||
public TapoEnergyData setData(JsonObject jso) {
|
public TapoEnergyData setData(JsonObject jso) {
|
||||||
/* create empty jsonObject to set efault values if has no energydata */
|
/* create empty jsonObject to set efault values if has no energydata */
|
||||||
if (jso.has(ENERGY_PROPERTY_POWER)) {
|
if (jso.has(JSON_KEY_ENERGY_POWER)) {
|
||||||
this.jsonObject = jso;
|
this.jsonObject = jso;
|
||||||
} else {
|
} else {
|
||||||
jsonObject = new JsonObject();
|
jsonObject = new JsonObject();
|
||||||
@ -70,12 +70,12 @@ public class TapoEnergyData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setData() {
|
private void setData() {
|
||||||
this.currentPower = (float) jsonObjectToInt(jsonObject, ENERGY_PROPERTY_POWER) / 1000;
|
this.currentPower = (float) jsonObjectToInt(jsonObject, JSON_KEY_ENERGY_POWER) / 1000;
|
||||||
|
|
||||||
this.todayEnergy = jsonObjectToInt(jsonObject, ENERGY_PROPERTY_ENERGY_TODAY);
|
this.todayEnergy = jsonObjectToInt(jsonObject, JSON_KEY_ENERGY_ENERGY_TODAY);
|
||||||
this.monthEnergy = jsonObjectToInt(jsonObject, ENERGY_PROPERTY_ENERGY_MONTH);
|
this.monthEnergy = jsonObjectToInt(jsonObject, JSON_KEY_ENERGY_ENERGY_MONTH);
|
||||||
this.todayRuntime = jsonObjectToInt(jsonObject, ENERGY_PROPERTY_RUNTIME_TODAY);
|
this.todayRuntime = jsonObjectToInt(jsonObject, JSON_KEY_ENERGY_RUNTIME_TODAY);
|
||||||
this.monthRuntime = jsonObjectToInt(jsonObject, ENERGY_PROPERTY_RUNTIME_MONTH);
|
this.monthRuntime = jsonObjectToInt(jsonObject, JSON_KEY_ENERGY_RUNTIME_MONTH);
|
||||||
this.past24h = new Number[24];
|
this.past24h = new Number[24];
|
||||||
this.past30d = new Number[30];
|
this.past30d = new Number[30];
|
||||||
this.past1y = new Number[12];
|
this.past1y = new Number[12];
|
||||||
|
@ -28,10 +28,10 @@ import com.google.gson.JsonObject;
|
|||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class TapoLightEffect {
|
public class TapoLightEffect {
|
||||||
private Integer enable = 0;
|
private Boolean enable = false;
|
||||||
private String id = "";
|
private String id = "";
|
||||||
private String name = "";
|
private String name = "";
|
||||||
private Integer custom = 0;
|
private Boolean custom = false;
|
||||||
private Integer brightness = 0;
|
private Integer brightness = 0;
|
||||||
private Integer[] colorTempRange = { 9000, 9000 }; // :[9000,9000]
|
private Integer[] colorTempRange = { 9000, 9000 }; // :[9000,9000]
|
||||||
private Color displayColors[] = { Color.WHITE };
|
private Color displayColors[] = { Color.WHITE };
|
||||||
@ -42,7 +42,6 @@ public class TapoLightEffect {
|
|||||||
* INIT
|
* INIT
|
||||||
*/
|
*/
|
||||||
public TapoLightEffect() {
|
public TapoLightEffect() {
|
||||||
setData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,21 +60,33 @@ public class TapoLightEffect {
|
|||||||
*/
|
*/
|
||||||
public TapoLightEffect setData(JsonObject jso) {
|
public TapoLightEffect setData(JsonObject jso) {
|
||||||
/* create empty jsonObject to set efault values if has no lighning effect */
|
/* create empty jsonObject to set efault values if has no lighning effect */
|
||||||
if (jso.has(DEVICE_PROPERTY_EFFECT)) {
|
if (jso.has(JSON_KEY_LIGHTNING_EFFECT)) {
|
||||||
|
this.jsonObject = jso.getAsJsonObject(JSON_KEY_LIGHTNING_EFFECT);
|
||||||
|
this.enable = jsonObjectToBool(jsonObject, JSON_KEY_LIGHTNING_EFFECT_ENABLE);
|
||||||
|
this.id = jsonObjectToString(jsonObject, JSON_KEY_LIGHTNING_EFFECT_ID);
|
||||||
|
this.name = jsonObjectToString(jsonObject, JSON_KEY_LIGHTNING_EFFECT_NAME);
|
||||||
|
this.custom = jsonObjectToBool(jsonObject, JSON_KEY_LIGHTNING_EFFECT_CUSTOM);
|
||||||
|
this.brightness = jsonObjectToInt(jsonObject, JSON_KEY_LIGHTNING_EFFECT_BRIGHNTESS);
|
||||||
|
} else if (jso.has(JSON_KEY_LIGHTNING_DYNAMIC_ENABLE)) {
|
||||||
this.jsonObject = jso;
|
this.jsonObject = jso;
|
||||||
|
this.enable = jsonObjectToBool(jsonObject, JSON_KEY_LIGHTNING_DYNAMIC_ENABLE);
|
||||||
|
this.id = jsonObjectToString(jsonObject, JSON_KEY_LIGHTNING_DYNAMIC_ID);
|
||||||
} else {
|
} else {
|
||||||
jsonObject = new JsonObject();
|
setDefaults();
|
||||||
}
|
}
|
||||||
setData();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setData() {
|
/**
|
||||||
this.enable = jsonObjectToInt(jsonObject, PROPERTY_LIGHTNING_EFFECT_ENABLE);
|
* Set default values
|
||||||
this.id = jsonObjectToString(jsonObject, PROPERTY_LIGHTNING_EFFECT_ID);
|
*/
|
||||||
this.name = jsonObjectToString(jsonObject, PROPERTY_LIGHTNING_EFFECT_NAME);
|
private void setDefaults() {
|
||||||
this.custom = jsonObjectToInt(jsonObject, PROPERTY_LIGHTNING_EFFECT_CUSTOM); // jsonObjectToBool
|
this.jsonObject = new JsonObject();
|
||||||
this.brightness = jsonObjectToInt(jsonObject, PROPERTY_LIGHTNING_EFFECT_BRIGHNTESS);
|
this.enable = false;
|
||||||
|
this.id = "";
|
||||||
|
this.name = "";
|
||||||
|
this.custom = false;
|
||||||
|
this.brightness = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
@ -85,7 +96,7 @@ public class TapoLightEffect {
|
|||||||
************************************/
|
************************************/
|
||||||
|
|
||||||
public void setEnable(Boolean enable) {
|
public void setEnable(Boolean enable) {
|
||||||
this.enable = enable ? 1 : 0;
|
this.enable = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String value) {
|
public void setName(String value) {
|
||||||
@ -93,7 +104,7 @@ public class TapoLightEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setCustom(Boolean enable) {
|
public void setCustom(Boolean enable) {
|
||||||
this.custom = enable ? 1 : 0;
|
this.custom = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBrightness(Integer value) {
|
public void setBrightness(Integer value) {
|
||||||
@ -106,7 +117,7 @@ public class TapoLightEffect {
|
|||||||
*
|
*
|
||||||
************************************/
|
************************************/
|
||||||
|
|
||||||
public Integer getEnable() {
|
public Boolean getEnable() {
|
||||||
return this.enable;
|
return this.enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +129,7 @@ public class TapoLightEffect {
|
|||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getCustom() {
|
public Boolean getCustom() {
|
||||||
return this.custom;
|
return this.custom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,8 +58,12 @@ channel-group-type.tapocontrol.energyMonitor.label = Energy Usage
|
|||||||
channel-group-type.tapocontrol.energyMonitor.description = Energy and Power usage
|
channel-group-type.tapocontrol.energyMonitor.description = Energy and Power usage
|
||||||
channel-group-type.tapocontrol.lightBulb.label = Light Bulb
|
channel-group-type.tapocontrol.lightBulb.label = Light Bulb
|
||||||
channel-group-type.tapocontrol.lightBulb.description = Tapo Smart Light Bulb
|
channel-group-type.tapocontrol.lightBulb.description = Tapo Smart Light Bulb
|
||||||
channel-group-type.tapocontrol.lightEffect.label = Lightning Effect
|
channel-group-type.tapocontrol.lightEffectL530.label = Lightning Effect
|
||||||
channel-group-type.tapocontrol.lightEffect.description = Tapo Lightning Effects
|
channel-group-type.tapocontrol.lightEffectL530.description = Tapo Lightning Effects
|
||||||
|
channel-group-type.tapocontrol.lightEffectL920.label = Lightning Effect
|
||||||
|
channel-group-type.tapocontrol.lightEffectL920.description = Tapo Lightning Effects
|
||||||
|
channel-group-type.tapocontrol.lightEffectL920.label = Lightning Effect
|
||||||
|
channel-group-type.tapocontrol.lightEffectL920.description = Tapo Lightning Effects
|
||||||
channel-group-type.tapocontrol.lightStrip.label = Color Light Strip
|
channel-group-type.tapocontrol.lightStrip.label = Color Light Strip
|
||||||
channel-group-type.tapocontrol.lightStrip.description = Tapo Multicolor Smart 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.label = SmartPlug
|
||||||
@ -81,16 +85,56 @@ channel-type.tapocontrol.colorChannel.label = Color
|
|||||||
channel-type.tapocontrol.colorChannel.description = Color
|
channel-type.tapocontrol.colorChannel.description = Color
|
||||||
channel-type.tapocontrol.colorTemperature.label = Color Temperature
|
channel-type.tapocontrol.colorTemperature.label = Color Temperature
|
||||||
channel-type.tapocontrol.colorTemperature.description = This channel supports adjusting the color temperature from 2700K to 6500K.
|
channel-type.tapocontrol.colorTemperature.description = This channel supports adjusting the color temperature from 2700K to 6500K.
|
||||||
channel-type.tapocontrol.customEffect.label = Custom Effect
|
|
||||||
channel-type.tapocontrol.customEffect.description = Use custom lightning effect
|
|
||||||
channel-type.tapocontrol.dimmerChannel.label = Brightness
|
channel-type.tapocontrol.dimmerChannel.label = Brightness
|
||||||
channel-type.tapocontrol.dimmerChannel.description = Brightness
|
channel-type.tapocontrol.dimmerChannel.description = Brightness
|
||||||
channel-type.tapocontrol.effectName.label = Effect Name
|
|
||||||
channel-type.tapocontrol.effectName.description = Name of LightningEffect
|
|
||||||
channel-type.tapocontrol.effectOn.label = Lightning Effect Enable
|
|
||||||
channel-type.tapocontrol.effectOn.description = Switches the lightning effect on/off
|
|
||||||
channel-type.tapocontrol.fade.label = Fade Light
|
channel-type.tapocontrol.fade.label = Fade Light
|
||||||
channel-type.tapocontrol.fade.description = Make the light darker or lighter slowly
|
channel-type.tapocontrol.fade.description = Make the light darker or lighter slowly
|
||||||
|
channel-type.tapocontrol.l530fxList.label = Light Effect Theme
|
||||||
|
channel-type.tapocontrol.l530fxList.description = Name of active lightning effect
|
||||||
|
channel-type.tapocontrol.l530fxList.state.option. = None (No FX)
|
||||||
|
channel-type.tapocontrol.l530fxList.state.option.custom = Custom
|
||||||
|
channel-type.tapocontrol.l530fxList.state.option.L1 = Party
|
||||||
|
channel-type.tapocontrol.l530fxList.state.option.L2 = Relax
|
||||||
|
channel-type.tapocontrol.l920fxList.label = Light Effect Theme
|
||||||
|
channel-type.tapocontrol.l920fxList.description = Name of lightning effect
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option. = None (No FX)
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.aurora = Aurora
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.bubbling_calderon = Bubbling Calderon
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.christmas = Christmas
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.christmas_light = Christmas Light
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.candy_cane = Candy
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.flicker = Flicker
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.hanukkah = Hanukkah
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.haunted_mansion = Haunted Mansion
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.icicle = Icicle
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.lightning = Lightning
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.ocean = Ocean
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.rainbow = Rainbow
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.raindrop = Raindrop
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.spring = Spring
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.sunrise = Sunrise
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.sunset = Sunset
|
||||||
|
channel-type.tapocontrol.l920fxList.state.option.valentines = Valentines
|
||||||
|
channel-type.tapocontrol.l930fxList.label = Light Effect Theme
|
||||||
|
channel-type.tapocontrol.l930fxList.description = Name of lightning effect
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option. = None (No FX)
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.aurora = Aurora
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.bubbling_calderon = Bubbling Calderon
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.christmas = Christmas
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.christmas_light = Christmas Light
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.candy_cane = Candy
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.flicker = Flicker
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.hanukkah = Hanukkah
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.haunted_mansion = Haunted Mansion
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.icicle = Icicle
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.lightning = Lightning
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.ocean = Ocean
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.rainbow = Rainbow
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.raindrop = Raindrop
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.spring = Spring
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.sunrise = Sunrise
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.sunset = Sunset
|
||||||
|
channel-type.tapocontrol.l930fxList.state.option.valentines = Valentines
|
||||||
channel-type.tapocontrol.led.label = Switch Led
|
channel-type.tapocontrol.led.label = Switch Led
|
||||||
channel-type.tapocontrol.led.description = Switch the Smart Home device led on or off.
|
channel-type.tapocontrol.led.description = Switch the Smart Home device led on or off.
|
||||||
channel-type.tapocontrol.lightOn.label = Light On
|
channel-type.tapocontrol.lightOn.label = Light On
|
||||||
@ -105,3 +149,17 @@ channel-type.tapocontrol.todayEnergyUsageChannel.label = Today Usage
|
|||||||
channel-type.tapocontrol.todayEnergyUsageChannel.description = Today energy usage
|
channel-type.tapocontrol.todayEnergyUsageChannel.description = Today energy usage
|
||||||
channel-type.tapocontrol.todayRuntimeChannel.label = Today Runtime
|
channel-type.tapocontrol.todayRuntimeChannel.label = Today Runtime
|
||||||
channel-type.tapocontrol.todayRuntimeChannel.description = Today runtime (On-Time)
|
channel-type.tapocontrol.todayRuntimeChannel.description = Today runtime (On-Time)
|
||||||
|
|
||||||
|
# channel group types
|
||||||
|
|
||||||
|
channel-group-type.tapocontrol.lightEffect.label = Lightning Effect
|
||||||
|
channel-group-type.tapocontrol.lightEffect.description = Tapo Lightning Effects
|
||||||
|
|
||||||
|
# channel types
|
||||||
|
|
||||||
|
channel-type.tapocontrol.customEffect.label = Custom Effect
|
||||||
|
channel-type.tapocontrol.customEffect.description = Use custom lightning effect
|
||||||
|
channel-type.tapocontrol.effectName.label = Effect Name
|
||||||
|
channel-type.tapocontrol.effectName.description = Name of LightningEffect
|
||||||
|
channel-type.tapocontrol.effectOn.label = Lightning Effect Enable
|
||||||
|
channel-type.tapocontrol.effectOn.description = Switches the lightning effect on/off
|
||||||
|
@ -14,10 +14,35 @@
|
|||||||
<description>Tapo Smart Multicolor Light-Bulb</description>
|
<description>Tapo Smart Multicolor Light-Bulb</description>
|
||||||
<channel-groups>
|
<channel-groups>
|
||||||
<channel-group id="actuator" typeId="colorBulb"/>
|
<channel-group id="actuator" typeId="colorBulb"/>
|
||||||
|
<channel-group id="effects" typeId="lightEffectL530"/>
|
||||||
<channel-group id="device" typeId="deviceState"/>
|
<channel-group id="device" typeId="deviceState"/>
|
||||||
</channel-groups>
|
</channel-groups>
|
||||||
<representation-property>macAddress</representation-property>
|
<representation-property>macAddress</representation-property>
|
||||||
|
|
||||||
<config-description-ref uri="thing-type:tapo:device"/>
|
<config-description-ref uri="thing-type:tapo:device"/>
|
||||||
</thing-type>
|
</thing-type>
|
||||||
|
|
||||||
|
<!-- Lightning Effect -->
|
||||||
|
<channel-group-type id="lightEffectL530">
|
||||||
|
<label>Lightning Effect</label>
|
||||||
|
<description>Tapo Lightning Effects</description>
|
||||||
|
<channels>
|
||||||
|
<channel id="fxName" typeId="l530fxList"/>
|
||||||
|
</channels>
|
||||||
|
</channel-group-type>
|
||||||
|
|
||||||
|
<!-- effect name -->
|
||||||
|
<channel-type id="l530fxList">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>Light Effect Theme</label>
|
||||||
|
<description>Name of active lightning effect</description>
|
||||||
|
<state readOnly="true">
|
||||||
|
<options>
|
||||||
|
<option value="">None (No FX)</option>
|
||||||
|
<option value="custom">Custom</option>
|
||||||
|
<option value="L1">Party</option>
|
||||||
|
<option value="L2">Relax</option>
|
||||||
|
</options>
|
||||||
|
</state>
|
||||||
|
</channel-type>
|
||||||
</thing:thing-descriptions>
|
</thing:thing-descriptions>
|
||||||
|
@ -20,4 +20,47 @@
|
|||||||
|
|
||||||
<config-description-ref uri="thing-type:tapo:device"/>
|
<config-description-ref uri="thing-type:tapo:device"/>
|
||||||
</thing-type>
|
</thing-type>
|
||||||
|
|
||||||
|
<!-- Lightning Effect -->
|
||||||
|
<channel-group-type id="lightEffectL920">
|
||||||
|
<label>Lightning Effect</label>
|
||||||
|
<description>Tapo Lightning Effects</description>
|
||||||
|
<channels>
|
||||||
|
<channel id="fxBrightness" typeId="dimmerChannel"/>
|
||||||
|
<channel id="fxName" typeId="l920fxList"/>
|
||||||
|
<channel id="fxColor1" typeId="colorChannel"/>
|
||||||
|
<channel id="fxColor2" typeId="colorChannel"/>
|
||||||
|
<channel id="fxColor3" typeId="colorChannel"/>
|
||||||
|
<channel id="fxColor4" typeId="colorChannel"/>
|
||||||
|
</channels>
|
||||||
|
</channel-group-type>
|
||||||
|
|
||||||
|
<!-- effect name -->
|
||||||
|
<channel-type id="l920fxList">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>Light Effect Theme</label>
|
||||||
|
<description>Name of lightning effect</description>
|
||||||
|
<state readOnly="false">
|
||||||
|
<options>
|
||||||
|
<option value="">None (No FX)</option>
|
||||||
|
<option value="aurora">Aurora</option>
|
||||||
|
<option value="bubbling_calderon">Bubbling Calderon</option>
|
||||||
|
<option value="christmas">Christmas</option>
|
||||||
|
<option value="christmas_light">Christmas Light</option>
|
||||||
|
<option value="candy_cane">Candy</option>
|
||||||
|
<option value="flicker">Flicker</option>
|
||||||
|
<option value="hanukkah">Hanukkah</option>
|
||||||
|
<option value="haunted_mansion">Haunted Mansion</option>
|
||||||
|
<option value="icicle">Icicle</option>
|
||||||
|
<option value="lightning">Lightning</option>
|
||||||
|
<option value="ocean">Ocean</option>
|
||||||
|
<option value="rainbow">Rainbow</option>
|
||||||
|
<option value="raindrop">Raindrop</option>
|
||||||
|
<option value="spring">Spring</option>
|
||||||
|
<option value="sunrise">Sunrise</option>
|
||||||
|
<option value="sunset">Sunset</option>
|
||||||
|
<option value="valentines">Valentines</option>
|
||||||
|
</options>
|
||||||
|
</state>
|
||||||
|
</channel-type>
|
||||||
</thing:thing-descriptions>
|
</thing:thing-descriptions>
|
||||||
|
@ -20,4 +20,47 @@
|
|||||||
|
|
||||||
<config-description-ref uri="thing-type:tapo:device"/>
|
<config-description-ref uri="thing-type:tapo:device"/>
|
||||||
</thing-type>
|
</thing-type>
|
||||||
|
|
||||||
|
<!-- Lightning Effect -->
|
||||||
|
<channel-group-type id="lightEffectL920">
|
||||||
|
<label>Lightning Effect</label>
|
||||||
|
<description>Tapo Lightning Effects</description>
|
||||||
|
<channels>
|
||||||
|
<channel id="fxBrightness" typeId="dimmerChannel"/>
|
||||||
|
<channel id="fxName" typeId="l930fxList"/>
|
||||||
|
<channel id="fxColor1" typeId="colorChannel"/>
|
||||||
|
<channel id="fxColor2" typeId="colorChannel"/>
|
||||||
|
<channel id="fxColor3" typeId="colorChannel"/>
|
||||||
|
<channel id="fxColor4" typeId="colorChannel"/>
|
||||||
|
</channels>
|
||||||
|
</channel-group-type>
|
||||||
|
|
||||||
|
<!-- effect name -->
|
||||||
|
<channel-type id="l930fxList">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>Light Effect Theme</label>
|
||||||
|
<description>Name of lightning effect</description>
|
||||||
|
<state readOnly="false">
|
||||||
|
<options>
|
||||||
|
<option value="">None (No FX)</option>
|
||||||
|
<option value="aurora">Aurora</option>
|
||||||
|
<option value="bubbling_calderon">Bubbling Calderon</option>
|
||||||
|
<option value="christmas">Christmas</option>
|
||||||
|
<option value="christmas_light">Christmas Light</option>
|
||||||
|
<option value="candy_cane">Candy</option>
|
||||||
|
<option value="flicker">Flicker</option>
|
||||||
|
<option value="hanukkah">Hanukkah</option>
|
||||||
|
<option value="haunted_mansion">Haunted Mansion</option>
|
||||||
|
<option value="icicle">Icicle</option>
|
||||||
|
<option value="lightning">Lightning</option>
|
||||||
|
<option value="ocean">Ocean</option>
|
||||||
|
<option value="rainbow">Rainbow</option>
|
||||||
|
<option value="raindrop">Raindrop</option>
|
||||||
|
<option value="spring">Spring</option>
|
||||||
|
<option value="sunrise">Sunrise</option>
|
||||||
|
<option value="sunset">Sunset</option>
|
||||||
|
<option value="valentines">Valentines</option>
|
||||||
|
</options>
|
||||||
|
</state>
|
||||||
|
</channel-type>
|
||||||
</thing:thing-descriptions>
|
</thing:thing-descriptions>
|
||||||
|
@ -102,23 +102,6 @@
|
|||||||
</channels>
|
</channels>
|
||||||
</channel-group-type>
|
</channel-group-type>
|
||||||
|
|
||||||
<!-- Lightning Effect -->
|
|
||||||
<channel-group-type id="lightEffect">
|
|
||||||
<label>Lightning Effect</label>
|
|
||||||
<description>Tapo Lightning Effects</description>
|
|
||||||
<channels>
|
|
||||||
<channel id="enable" typeId="effectOn"/>
|
|
||||||
<channel id="brightness" typeId="dimmerChannel"/>
|
|
||||||
<channel id="name" typeId="effectName"/>
|
|
||||||
<channel id="custom" typeId="customEffect"/>
|
|
||||||
<channel id="displayColor1" typeId="colorChannel"/>
|
|
||||||
<channel id="displayColor2" typeId="colorChannel"/>
|
|
||||||
<channel id="displayColor3" typeId="colorChannel"/>
|
|
||||||
<channel id="displayColor4" typeId="colorChannel"/>
|
|
||||||
</channels>
|
|
||||||
</channel-group-type>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- ############################### CHANNELS ############################### -->
|
<!-- ############################### CHANNELS ############################### -->
|
||||||
|
|
||||||
<!-- ACTOR CHANNEL TYPES -->
|
<!-- ACTOR CHANNEL TYPES -->
|
||||||
@ -216,35 +199,6 @@
|
|||||||
<state readOnly="true" pattern="%.0f %unit%"></state>
|
<state readOnly="true" pattern="%.0f %unit%"></state>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
|
||||||
|
|
||||||
<!-- LIGHTNING EFFECT CHANNEL TYPES -->
|
|
||||||
<!-- effect on -->
|
|
||||||
<channel-type id="effectOn">
|
|
||||||
<item-type>Switch</item-type>
|
|
||||||
<label>Lightning Effect Enable</label>
|
|
||||||
<description>Switches the lightning effect on/off</description>
|
|
||||||
<category>LightBulb</category>
|
|
||||||
<state readOnly="false"/>
|
|
||||||
</channel-type>
|
|
||||||
|
|
||||||
<!-- effect name -->
|
|
||||||
<channel-type id="effectName">
|
|
||||||
<item-type>String</item-type>
|
|
||||||
<label>Effect Name</label>
|
|
||||||
<description>Name of LightningEffect</description>
|
|
||||||
<state readOnly="false"/>
|
|
||||||
</channel-type>
|
|
||||||
|
|
||||||
<!-- custom effect -->
|
|
||||||
<channel-type id="customEffect">
|
|
||||||
<item-type>Switch</item-type>
|
|
||||||
<label>Custom Effect</label>
|
|
||||||
<description>Use custom lightning effect</description>
|
|
||||||
<category>LightBulb</category>
|
|
||||||
<state readOnly="false"/>
|
|
||||||
</channel-type>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- ADVANCED SETTING CHANNELS -->
|
<!-- ADVANCED SETTING CHANNELS -->
|
||||||
<!-- device led -->
|
<!-- device led -->
|
||||||
<channel-type id="led" advanced="true">
|
<channel-type id="led" advanced="true">
|
||||||
|
@ -131,17 +131,17 @@ public class TapoDiscoveryService extends AbstractDiscoveryService implements Th
|
|||||||
TapoBridgeHandler tapoBridge = this.bridge;
|
TapoBridgeHandler tapoBridge = this.bridge;
|
||||||
String deviceModel = getDeviceModel(device);
|
String deviceModel = getDeviceModel(device);
|
||||||
String label = getDeviceLabel(device);
|
String label = getDeviceLabel(device);
|
||||||
String deviceMAC = device.get(CLOUD_PROPERTY_MAC).getAsString();
|
String deviceMAC = device.get(CLOUD_JSON_KEY_MAC).getAsString();
|
||||||
ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, deviceModel);
|
ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, deviceModel);
|
||||||
|
|
||||||
/* create properties */
|
/* create properties */
|
||||||
Map<String, Object> properties = new HashMap<>();
|
Map<String, Object> properties = new HashMap<>();
|
||||||
properties.put(Thing.PROPERTY_VENDOR, DEVICE_VENDOR);
|
properties.put(Thing.PROPERTY_VENDOR, DEVICE_VENDOR);
|
||||||
properties.put(Thing.PROPERTY_MAC_ADDRESS, formatMac(deviceMAC, MAC_DIVISION_CHAR));
|
properties.put(Thing.PROPERTY_MAC_ADDRESS, formatMac(deviceMAC, MAC_DIVISION_CHAR));
|
||||||
properties.put(Thing.PROPERTY_FIRMWARE_VERSION, device.get(CLOUD_PROPERTY_FW).getAsString());
|
properties.put(Thing.PROPERTY_FIRMWARE_VERSION, device.get(CLOUD_JSON_KEY_FW).getAsString());
|
||||||
properties.put(Thing.PROPERTY_HARDWARE_VERSION, device.get(CLOUD_PROPERTY_HW).getAsString());
|
properties.put(Thing.PROPERTY_HARDWARE_VERSION, device.get(CLOUD_JSON_KEY_HW).getAsString());
|
||||||
properties.put(Thing.PROPERTY_MODEL_ID, deviceModel);
|
properties.put(Thing.PROPERTY_MODEL_ID, deviceModel);
|
||||||
properties.put(Thing.PROPERTY_SERIAL_NUMBER, device.get(CLOUD_PROPERTY_ID).getAsString());
|
properties.put(Thing.PROPERTY_SERIAL_NUMBER, device.get(CLOUD_JSON_KEY_ID).getAsString());
|
||||||
|
|
||||||
logger.debug("device {} discovered", deviceModel);
|
logger.debug("device {} discovered", deviceModel);
|
||||||
if (tapoBridge != null) {
|
if (tapoBridge != null) {
|
||||||
@ -190,7 +190,7 @@ public class TapoDiscoveryService extends AbstractDiscoveryService implements Th
|
|||||||
*/
|
*/
|
||||||
protected String getDeviceModel(JsonObject device) {
|
protected String getDeviceModel(JsonObject device) {
|
||||||
try {
|
try {
|
||||||
String deviceModel = device.get(CLOUD_PROPERTY_MODEL).getAsString();
|
String deviceModel = device.get(CLOUD_JSON_KEY_MODEL).getAsString();
|
||||||
deviceModel = deviceModel.replaceAll("\\(.*\\)", ""); // replace (DE)
|
deviceModel = deviceModel.replaceAll("\\(.*\\)", ""); // replace (DE)
|
||||||
deviceModel = deviceModel.replace("Tapo", "");
|
deviceModel = deviceModel.replace("Tapo", "");
|
||||||
deviceModel = deviceModel.replace("Series", "");
|
deviceModel = deviceModel.replace("Series", "");
|
||||||
|
@ -66,7 +66,7 @@ public class TapoUniversalDevice extends TapoDevice {
|
|||||||
} else {
|
} else {
|
||||||
switch (channel) {
|
switch (channel) {
|
||||||
case CHANNEL_OUTPUT:
|
case CHANNEL_OUTPUT:
|
||||||
connector.sendDeviceCommand(DEVICE_PROPERTY_ON, command == OnOffType.ON);
|
connector.sendDeviceCommand(JSON_KEY_ON, command == OnOffType.ON);
|
||||||
refreshInfo = true;
|
refreshInfo = true;
|
||||||
break;
|
break;
|
||||||
case CHANNEL_BRIGHTNESS:
|
case CHANNEL_BRIGHTNESS:
|
||||||
@ -121,11 +121,11 @@ public class TapoUniversalDevice extends TapoDevice {
|
|||||||
protected void setBrightness(Integer newBrightness) {
|
protected void setBrightness(Integer newBrightness) {
|
||||||
/* switch off if 0 */
|
/* switch off if 0 */
|
||||||
if (newBrightness == 0) {
|
if (newBrightness == 0) {
|
||||||
connector.sendDeviceCommand(DEVICE_PROPERTY_ON, false);
|
connector.sendDeviceCommand(JSON_KEY_ON, false);
|
||||||
} else {
|
} else {
|
||||||
HashMap<String, Object> newState = new HashMap<>();
|
HashMap<String, Object> newState = new HashMap<>();
|
||||||
newState.put(DEVICE_PROPERTY_ON, true);
|
newState.put(JSON_KEY_ON, true);
|
||||||
newState.put(DEVICE_PROPERTY_BRIGHTNES, newBrightness);
|
newState.put(JSON_KEY_BRIGHTNES, newBrightness);
|
||||||
connector.sendDeviceCommands(newState);
|
connector.sendDeviceCommands(newState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,10 +137,10 @@ public class TapoUniversalDevice extends TapoDevice {
|
|||||||
*/
|
*/
|
||||||
protected void setColor(HSBType command) {
|
protected void setColor(HSBType command) {
|
||||||
HashMap<String, Object> newState = new HashMap<>();
|
HashMap<String, Object> newState = new HashMap<>();
|
||||||
newState.put(DEVICE_PROPERTY_ON, true);
|
newState.put(JSON_KEY_ON, true);
|
||||||
newState.put(DEVICE_PROPERTY_HUE, command.getHue());
|
newState.put(JSON_KEY_HUE, command.getHue());
|
||||||
newState.put(DEVICE_PROPERTY_SATURATION, command.getSaturation());
|
newState.put(JSON_KEY_SATURATION, command.getSaturation());
|
||||||
newState.put(DEVICE_PROPERTY_BRIGHTNES, command.getBrightness());
|
newState.put(JSON_KEY_BRIGHTNES, command.getBrightness());
|
||||||
connector.sendDeviceCommands(newState);
|
connector.sendDeviceCommands(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,8 +152,8 @@ public class TapoUniversalDevice extends TapoDevice {
|
|||||||
protected void setColorTemp(Integer colorTemp) {
|
protected void setColorTemp(Integer colorTemp) {
|
||||||
HashMap<String, Object> newState = new HashMap<>();
|
HashMap<String, Object> newState = new HashMap<>();
|
||||||
colorTemp = limitVal(colorTemp, BULB_MIN_COLORTEMP, BULB_MAX_COLORTEMP);
|
colorTemp = limitVal(colorTemp, BULB_MIN_COLORTEMP, BULB_MAX_COLORTEMP);
|
||||||
newState.put(DEVICE_PROPERTY_ON, true);
|
newState.put(JSON_KEY_ON, true);
|
||||||
newState.put(DEVICE_PROPERTY_COLORTEMP, colorTemp);
|
newState.put(JSON_KEY_COLORTEMP, colorTemp);
|
||||||
connector.sendDeviceCommands(newState);
|
connector.sendDeviceCommands(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,28 +102,28 @@ public class TapoDeviceInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setData() {
|
private void setData() {
|
||||||
this.brightness = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_BRIGHTNES);
|
this.brightness = jsonObjectToInt(jsonObject, JSON_KEY_BRIGHTNES);
|
||||||
this.colorTemp = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_COLORTEMP, BULB_MIN_COLORTEMP);
|
this.colorTemp = jsonObjectToInt(jsonObject, JSON_KEY_COLORTEMP, BULB_MIN_COLORTEMP);
|
||||||
this.deviceId = jsonObjectToString(jsonObject, DEVICE_PROPERTY_ID);
|
this.deviceId = jsonObjectToString(jsonObject, JSON_KEY_ID);
|
||||||
this.deviceOn = jsonObjectToBool(jsonObject, DEVICE_PROPERTY_ON);
|
this.deviceOn = jsonObjectToBool(jsonObject, JSON_KEY_ON);
|
||||||
this.fwVer = jsonObjectToString(jsonObject, DEVICE_PROPERTY_FW);
|
this.fwVer = jsonObjectToString(jsonObject, JSON_KEY_FW);
|
||||||
this.hue = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_HUE);
|
this.hue = jsonObjectToInt(jsonObject, JSON_KEY_HUE);
|
||||||
this.hwVer = jsonObjectToString(jsonObject, DEVICE_PROPERTY_HW);
|
this.hwVer = jsonObjectToString(jsonObject, JSON_KEY_HW_VER);
|
||||||
this.ip = jsonObjectToString(jsonObject, DEVICE_PROPERTY_IP);
|
this.ip = jsonObjectToString(jsonObject, JSON_KEY_IP);
|
||||||
this.lightEffect = lightEffect.setData(jsonObject);
|
this.lightEffect = lightEffect.setData(jsonObject);
|
||||||
this.mac = jsonObjectToString(jsonObject, DEVICE_PROPERTY_MAC);
|
this.mac = jsonObjectToString(jsonObject, JSON_KEY_MAC);
|
||||||
this.model = jsonObjectToString(jsonObject, DEVICE_PROPERTY_MODEL);
|
this.model = jsonObjectToString(jsonObject, JSON_KEY_MODEL);
|
||||||
this.nickname = jsonObjectToString(jsonObject, DEVICE_PROPERTY_NICKNAME);
|
this.nickname = jsonObjectToString(jsonObject, JSON_KEY_NICKNAME);
|
||||||
this.onTime = jsonObjectToNumber(jsonObject, DEVICE_PROPERTY_ONTIME);
|
this.onTime = jsonObjectToNumber(jsonObject, JSON_KEY_ONTIME);
|
||||||
this.overheated = jsonObjectToBool(jsonObject, DEVICE_PROPERTY_OVERHEAT);
|
this.overheated = jsonObjectToBool(jsonObject, JSON_KEY_OVERHEAT);
|
||||||
this.region = jsonObjectToString(jsonObject, DEVICE_PROPERTY_REGION);
|
this.region = jsonObjectToString(jsonObject, JSON_KEY_REGION);
|
||||||
this.saturation = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_SATURATION);
|
this.saturation = jsonObjectToInt(jsonObject, JSON_KEY_SATURATION);
|
||||||
this.signalLevel = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_SIGNAL);
|
this.signalLevel = jsonObjectToInt(jsonObject, JSON_KEY_SIGNAL_LEVEL);
|
||||||
this.rssi = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_SIGNAL_RSSI);
|
this.rssi = jsonObjectToInt(jsonObject, JSON_KEY_RSSI);
|
||||||
this.timeUsagePast7 = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_USAGE_7);
|
this.timeUsagePast7 = jsonObjectToInt(jsonObject, JSON_KEY_USAGE_7);
|
||||||
this.timeUsagePast30 = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_USAGE_30);
|
this.timeUsagePast30 = jsonObjectToInt(jsonObject, JSON_KEY_USAGE_30);
|
||||||
this.timeUsageToday = jsonObjectToInt(jsonObject, DEVICE_PROPERTY_USAGE_TODAY);
|
this.timeUsageToday = jsonObjectToInt(jsonObject, JSON_KEY_USAGE_TODAY);
|
||||||
this.type = jsonObjectToString(jsonObject, DEVICE_PROPERTY_TYPE);
|
this.type = jsonObjectToString(jsonObject, JSON_KEY_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
|
@ -61,7 +61,7 @@ public class TapoLightEffect {
|
|||||||
*/
|
*/
|
||||||
public TapoLightEffect setData(JsonObject jso) {
|
public TapoLightEffect setData(JsonObject jso) {
|
||||||
/* create empty jsonObject to set efault values if has no lighning effect */
|
/* create empty jsonObject to set efault values if has no lighning effect */
|
||||||
if (jsonObject.has(DEVICE_PROPERTY_EFFECT)) {
|
if (jsonObject.has(JSON_KEY_LIGHTNING_EFFECT)) {
|
||||||
this.jsonObject = jso;
|
this.jsonObject = jso;
|
||||||
} else {
|
} else {
|
||||||
jsonObject = new JsonObject();
|
jsonObject = new JsonObject();
|
||||||
@ -71,11 +71,11 @@ public class TapoLightEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setData() {
|
private void setData() {
|
||||||
this.enable = jsonObjectToInt(jsonObject, PROPERTY_LIGHTNING_EFFECT_ENABLE);
|
this.enable = jsonObjectToInt(jsonObject, JSON_KEY_LIGHTNING_EFFECT_ENABLE);
|
||||||
this.id = jsonObjectToString(jsonObject, PROPERTY_LIGHTNING_EFFECT_ID);
|
this.id = jsonObjectToString(jsonObject, JSON_KEY_LIGHTNING_EFFECT_ID);
|
||||||
this.name = jsonObjectToString(jsonObject, PROPERTY_LIGHTNING_EFFECT_NAME);
|
this.name = jsonObjectToString(jsonObject, JSON_KEY_LIGHTNING_EFFECT_NAME);
|
||||||
this.custom = jsonObjectToInt(jsonObject, PROPERTY_LIGHTNING_EFFECT_CUSTOM); // jsonObjectToBool
|
this.custom = jsonObjectToInt(jsonObject, JSON_KEY_LIGHTNING_EFFECT_CUSTOM); // jsonObjectToBool
|
||||||
this.brightness = jsonObjectToInt(jsonObject, PROPERTY_LIGHTNING_EFFECT_BRIGHNTESS);
|
this.brightness = jsonObjectToInt(jsonObject, JSON_KEY_LIGHTNING_EFFECT_BRIGHNTESS);
|
||||||
// this.color_temp_range = { 9000, 9000 }; PROPERTY_LIGHNTING_ //:[9000,9000]
|
// this.color_temp_range = { 9000, 9000 }; PROPERTY_LIGHNTING_ //:[9000,9000]
|
||||||
// this.displayColors[] PROPERTY_LIGHNTING_;
|
// this.displayColors[] PROPERTY_LIGHNTING_;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user