mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[tplinksmarthome] Added KL400, KL430 lightstrip support (#12000)
Closes #8709 Additional: - Added action to send and receive json commands to a tplink device. This can be used for test purposes or to run commands not available through channels. Fixes: - Power channel of a bulb is defined as QuantityType in xml, therefor it should create the state using QuantityType - Retry getting values 5 times before setting the device offline. Reduced socket time out to 2 seconds as it normally should react quickly and if it times out it tries again. Also-by: Dustin Masters <ceo@dustinsoftware.com> Signed-off-by: Hilbrand Bouwkamp <hilbrand@h72.nl>
This commit is contained in:
parent
a0236bf993
commit
888cf00245
@ -242,6 +242,24 @@ Switching, Brightness and Color is done using the `color` channel.
|
||||
|
||||
Switching, Brightness and Color is done using the `color` channel.
|
||||
|
||||
### KL400 Kasa Smart LED Light Strip
|
||||
|
||||
* Power On/Off
|
||||
* Fine-tune colors
|
||||
* Adjust light appearance from soft white (2500k) to daylight (9000k)
|
||||
* Adjust the brightness
|
||||
* Wi-Fi signal strength (RSSI)
|
||||
|
||||
### KL430 Kasa Smart LED Light Strip, 16 Color Zones
|
||||
|
||||
* Power On/Off
|
||||
* Fine-tune colors
|
||||
* Adjust light appearance from soft white (2500k) to daylight (9000k)
|
||||
* Adjust the brightness
|
||||
* Wi-Fi signal strength (RSSI)
|
||||
|
||||
Switching, Brightness and Color is done using the `color` channel.
|
||||
|
||||
### KP100 Kasa Wi-Fi Smart Plug - Slim Edition
|
||||
|
||||
* Power On/Off
|
||||
@ -363,9 +381,9 @@ All devices support some of the following channels:
|
||||
|---------------------|--------------------------|------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| switch | Switch | Power the device on or off. | EP10, EP40, HS100, HS103, HS105, HS107, HS110, HS200, HS210, HS300, KP100, KP105, KP115, KP200, KP303, KP400, KS230, RE270K, RE370K |
|
||||
| brightness | Dimmer | Set the brightness of device or dimmer. | ES20M, HS220, KB100, KL50, KL60, KL110, KL120, KP405, LB100, LB110, LB120, LB200 |
|
||||
| colorTemperature | Dimmer | Set the color temperature in percentage. | KB130, KL120, KL125, KL130, KL135, LB120, LB130, LB230 |
|
||||
| colorTemperatureAbs | Number | Set the color temperature in Kelvin. | KB130, KL120, KL125, KL130, KL135, LB120, LB130, LB230 |
|
||||
| color | Color | Set the color of the light. | KB130, KL125, KL130, KL135, LB130, LB230 |
|
||||
| colorTemperature | Dimmer | Set the color temperature in percentage. | KB130, KL120, KL125, KL130, KL135, KL400, KL430, LB120, LB130, LB230 |
|
||||
| colorTemperatureAbs | Number | Set the color temperature in Kelvin. | KB130, KL120, KL125, KL130, KL135, KL400, KL430, LB120, LB130, LB230 |
|
||||
| color | Color | Set the color of the light. | KB130, KL125, KL130, KL135, KL400, KL430, LB130, LB230 |
|
||||
| power | Number:Power | Actual energy usage in Watt. | HS110, HS300, KLxxx, KP115, KP125, LBxxx, |
|
||||
| eneryUsage | Number:Energy | Energy Usage in kWh. | HS110, HS300, KP115, KP125 |
|
||||
| current | Number:ElectricCurrent | Actual current usage in Ampere. | HS110, HS300, KP115, KP125 |
|
||||
|
@ -21,6 +21,7 @@ import org.openhab.binding.tplinksmarthome.internal.model.HasErrorResponse;
|
||||
import org.openhab.binding.tplinksmarthome.internal.model.Realtime;
|
||||
import org.openhab.binding.tplinksmarthome.internal.model.SetBrightness;
|
||||
import org.openhab.binding.tplinksmarthome.internal.model.SetLedOff;
|
||||
import org.openhab.binding.tplinksmarthome.internal.model.SetLightState;
|
||||
import org.openhab.binding.tplinksmarthome.internal.model.SetRelayState;
|
||||
import org.openhab.binding.tplinksmarthome.internal.model.SetSwitchState;
|
||||
import org.openhab.binding.tplinksmarthome.internal.model.Sysinfo;
|
||||
@ -79,7 +80,7 @@ public class Commands {
|
||||
* @param id optional id of the device
|
||||
* @return The json string of the command to send to the device
|
||||
*/
|
||||
public static String getRealtimeWithContext(String id) {
|
||||
public static String getRealtimeWithContext(final String id) {
|
||||
return String.format(CONTEXT, id) + REALTIME + "}";
|
||||
}
|
||||
|
||||
@ -90,8 +91,8 @@ public class Commands {
|
||||
* @return The data object containing the energy data from the json string
|
||||
*/
|
||||
@SuppressWarnings("null")
|
||||
public Realtime getRealtimeResponse(String realtimeResponse) {
|
||||
GetRealtime getRealtime = gson.fromJson(realtimeResponse, GetRealtime.class);
|
||||
public Realtime getRealtimeResponse(final String realtimeResponse) {
|
||||
final GetRealtime getRealtime = gson.fromJson(realtimeResponse, GetRealtime.class);
|
||||
return getRealtime == null ? new Realtime() : getRealtime.getRealtime();
|
||||
}
|
||||
|
||||
@ -111,8 +112,8 @@ public class Commands {
|
||||
* @return The data object containing the state data from the json string
|
||||
*/
|
||||
@SuppressWarnings("null")
|
||||
public Sysinfo getSysinfoReponse(String getSysinfoReponse) {
|
||||
GetSysinfo getSysinfo = gson.fromJson(getSysinfoReponse, GetSysinfo.class);
|
||||
public Sysinfo getSysinfoReponse(final String getSysinfoReponse) {
|
||||
final GetSysinfo getSysinfo = gson.fromJson(getSysinfoReponse, GetSysinfo.class);
|
||||
return getSysinfo == null ? new Sysinfo() : getSysinfo.getSysinfo();
|
||||
}
|
||||
|
||||
@ -123,8 +124,8 @@ public class Commands {
|
||||
* @param childId optional child id if multiple children are supported by a single device
|
||||
* @return The json string of the command to send to the device
|
||||
*/
|
||||
public String setRelayState(OnOffType onOff, @Nullable String childId) {
|
||||
SetRelayState relayState = new SetRelayState();
|
||||
public String setRelayState(final OnOffType onOff, @Nullable final String childId) {
|
||||
final SetRelayState relayState = new SetRelayState();
|
||||
relayState.setRelayState(onOff);
|
||||
if (childId != null) {
|
||||
relayState.setChildId(childId);
|
||||
@ -138,7 +139,7 @@ public class Commands {
|
||||
* @param relayStateResponse the json string
|
||||
* @return The data object containing the state data from the json string
|
||||
*/
|
||||
public @Nullable SetRelayState setRelayStateResponse(String relayStateResponse) {
|
||||
public @Nullable SetRelayState setRelayStateResponse(final String relayStateResponse) {
|
||||
return gsonWithExpose.fromJson(relayStateResponse, SetRelayState.class);
|
||||
}
|
||||
|
||||
@ -148,8 +149,8 @@ public class Commands {
|
||||
* @param onOff the switch state to set
|
||||
* @return The json string of the command to send to the device
|
||||
*/
|
||||
public String setSwitchState(OnOffType onOff) {
|
||||
SetSwitchState switchState = new SetSwitchState();
|
||||
public String setSwitchState(final OnOffType onOff) {
|
||||
final SetSwitchState switchState = new SetSwitchState();
|
||||
switchState.setSwitchState(onOff);
|
||||
return gsonWithExpose.toJson(switchState);
|
||||
}
|
||||
@ -160,7 +161,7 @@ public class Commands {
|
||||
* @param switchStateResponse the json string
|
||||
* @return The data object containing the state data from the json string
|
||||
*/
|
||||
public @Nullable SetSwitchState setSwitchStateResponse(String switchStateResponse) {
|
||||
public @Nullable SetSwitchState setSwitchStateResponse(final String switchStateResponse) {
|
||||
return gsonWithExpose.fromJson(switchStateResponse, SetSwitchState.class);
|
||||
}
|
||||
|
||||
@ -170,8 +171,8 @@ public class Commands {
|
||||
* @param brightness the brightness value to set
|
||||
* @return The json string of the command to send to the device
|
||||
*/
|
||||
public String setDimmerBrightness(int brightness) {
|
||||
SetBrightness setBrightness = new SetBrightness();
|
||||
public String setDimmerBrightness(final int brightness) {
|
||||
final SetBrightness setBrightness = new SetBrightness();
|
||||
setBrightness.setBrightness(brightness);
|
||||
return gsonWithExpose.toJson(setBrightness);
|
||||
}
|
||||
@ -182,26 +183,10 @@ public class Commands {
|
||||
* @param dimmerBrightnessResponse the json string
|
||||
* @return The data object containing the state data from the json string
|
||||
*/
|
||||
public @Nullable HasErrorResponse setDimmerBrightnessResponse(String dimmerBrightnessResponse) {
|
||||
public @Nullable HasErrorResponse setDimmerBrightnessResponse(final String dimmerBrightnessResponse) {
|
||||
return gsonWithExpose.fromJson(dimmerBrightnessResponse, SetBrightness.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the json for the set_light_state command to switch a bulb on or off.
|
||||
*
|
||||
* @param onOff the switch state to set
|
||||
* @param transitionPeriod the transition period for the action to take place
|
||||
* @return The json string of the command to send to the device
|
||||
*/
|
||||
public String setLightState(OnOffType onOff, int transitionPeriod) {
|
||||
TransitionLightState transitionLightState = new TransitionLightState();
|
||||
LightOnOff lightState = new LightOnOff();
|
||||
lightState.setOnOff(onOff);
|
||||
lightState.setTransitionPeriod(transitionPeriod);
|
||||
transitionLightState.setLightState(lightState);
|
||||
return gson.toJson(transitionLightState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the json for the set_led_off command to switch the led of the device on or off.
|
||||
*
|
||||
@ -209,8 +194,8 @@ public class Commands {
|
||||
* @param childId optional child id if multiple children are supported by a single device
|
||||
* @return The json string of the command to send to the device
|
||||
*/
|
||||
public String setLedOn(OnOffType onOff, @Nullable String childId) {
|
||||
SetLedOff sLOff = new SetLedOff();
|
||||
public String setLedOn(final OnOffType onOff, @Nullable final String childId) {
|
||||
final SetLedOff sLOff = new SetLedOff();
|
||||
sLOff.setLed(onOff);
|
||||
if (childId != null) {
|
||||
sLOff.setChildId(childId);
|
||||
@ -224,10 +209,21 @@ public class Commands {
|
||||
* @param setLedOnResponse the json string
|
||||
* @return The data object containing the data from the json string
|
||||
*/
|
||||
public @Nullable SetLedOff setLedOnResponse(String setLedOnResponse) {
|
||||
public @Nullable SetLedOff setLedOnResponse(final String setLedOnResponse) {
|
||||
return gsonWithExpose.fromJson(setLedOnResponse, SetLedOff.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the json for the transition_light_state command to switch a bulb on or off.
|
||||
*
|
||||
* @param onOff the switch state to set
|
||||
* @param transitionPeriod the transition period for the action to take place
|
||||
* @return The json string of the command to send to the device
|
||||
*/
|
||||
public String setTransitionLightState(final OnOffType onOff, final int transitionPeriod) {
|
||||
return setTransitionLightState(new LightOnOff(), onOff, transitionPeriod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the json for the set_light_State command to set the brightness.
|
||||
*
|
||||
@ -235,14 +231,10 @@ public class Commands {
|
||||
* @param transitionPeriod the transition period for the action to take place
|
||||
* @return The json string of the command to send to the device
|
||||
*/
|
||||
public String setBrightness(int brightness, int transitionPeriod) {
|
||||
TransitionLightState transitionLightState = new TransitionLightState();
|
||||
LightStateBrightness lightState = new LightStateBrightness();
|
||||
lightState.setOnOff(brightness == 0 ? OnOffType.OFF : OnOffType.ON);
|
||||
public String setTransitionLightStateBrightness(final int brightness, final int transitionPeriod) {
|
||||
final LightStateBrightness lightState = new LightStateBrightness();
|
||||
lightState.setBrightness(brightness);
|
||||
lightState.setTransitionPeriod(transitionPeriod);
|
||||
transitionLightState.setLightState(lightState);
|
||||
return gson.toJson(transitionLightState);
|
||||
return setTransitionLightState(lightState, OnOffType.from(brightness != 0), transitionPeriod);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -252,17 +244,13 @@ public class Commands {
|
||||
* @param transitionPeriod the transition period for the action to take place
|
||||
* @return The json string of the command to send to the device
|
||||
*/
|
||||
public String setColor(HSBType hsb, int transitionPeriod) {
|
||||
TransitionLightState transitionLightState = new TransitionLightState();
|
||||
LightStateColor lightState = new LightStateColor();
|
||||
int brightness = hsb.getBrightness().intValue();
|
||||
lightState.setOnOff(brightness == 0 ? OnOffType.OFF : OnOffType.ON);
|
||||
public String setTransitionLightStateColor(final HSBType hsb, final int transitionPeriod) {
|
||||
final LightStateColor lightState = new LightStateColor();
|
||||
final int brightness = hsb.getBrightness().intValue();
|
||||
lightState.setBrightness(brightness);
|
||||
lightState.setHue(hsb.getHue().intValue());
|
||||
lightState.setSaturation(hsb.getSaturation().intValue());
|
||||
lightState.setTransitionPeriod(transitionPeriod);
|
||||
transitionLightState.setLightState(lightState);
|
||||
return gson.toJson(transitionLightState);
|
||||
return setTransitionLightState(lightState, OnOffType.from(brightness != 0), transitionPeriod);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -272,13 +260,18 @@ public class Commands {
|
||||
* @param transitionPeriod the transition period for the action to take place
|
||||
* @return The json string of the command to send to the device
|
||||
*/
|
||||
public String setColorTemperature(int colorTemperature, int transitionPeriod) {
|
||||
TransitionLightState transitionLightState = new TransitionLightState();
|
||||
LightStateColorTemperature lightState = new LightStateColorTemperature();
|
||||
lightState.setOnOff(OnOffType.ON);
|
||||
public String setColorTemperature(final int colorTemperature, final int transitionPeriod) {
|
||||
final LightStateColorTemperature lightState = new LightStateColorTemperature();
|
||||
lightState.setColorTemperature(colorTemperature);
|
||||
lightState.setTransitionPeriod(transitionPeriod);
|
||||
transitionLightState.setLightState(lightState);
|
||||
return setTransitionLightState(lightState, OnOffType.ON, transitionPeriod);
|
||||
}
|
||||
|
||||
private String setTransitionLightState(final LightOnOff lightOnOff, final OnOffType onOff,
|
||||
final int transitionPeriod) {
|
||||
final TransitionLightState transitionLightState = new TransitionLightState();
|
||||
transitionLightState.setLightState(lightOnOff);
|
||||
lightOnOff.setOnOff(onOff);
|
||||
lightOnOff.setTransitionPeriod(transitionPeriod);
|
||||
return gson.toJson(transitionLightState);
|
||||
}
|
||||
|
||||
@ -288,7 +281,82 @@ public class Commands {
|
||||
* @param response the json string
|
||||
* @return The data object containing the state data from the json string
|
||||
*/
|
||||
public @Nullable TransitionLightStateResponse setTransitionLightStateResponse(String response) {
|
||||
public @Nullable TransitionLightStateResponse setTransitionLightStateResponse(final String response) {
|
||||
return gson.fromJson(response, TransitionLightStateResponse.class);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the json for the set_light_state command to switch a light strip on or off.
|
||||
*
|
||||
* @param onOff the switch state to set
|
||||
* @param transition the transition period for the action to take place
|
||||
* @return The json string of the command to send to the device
|
||||
*/
|
||||
public String setLightStripState(final OnOffType onOff, final int transition) {
|
||||
return setLightStripState(new SetLightState.LightOnOff(), onOff, transition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the json for the set_light_State command to set the brightness.
|
||||
*
|
||||
* @param brightness the brightness value
|
||||
* @param transition the transition period for the action to take place
|
||||
* @return The json string of the command to send to the device
|
||||
*/
|
||||
public String setLightStripBrightness(final int brightness, final int transition) {
|
||||
final SetLightState.Brightness lightState = new SetLightState.Brightness();
|
||||
lightState.setBrightness(brightness);
|
||||
return setLightStripState(lightState, OnOffType.from(brightness != 0), transition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the json for the set_light_State command to set the color.
|
||||
*
|
||||
* @param hsb the color to set
|
||||
* @param transition the transition period for the action to take place
|
||||
* @return The json string of the command to send to the device
|
||||
*/
|
||||
public String setLightStripColor(final HSBType hsb, final int transition) {
|
||||
final SetLightState.Color lightState = new SetLightState.Color();
|
||||
final int brightness = hsb.getBrightness().intValue();
|
||||
lightState.setHue(hsb.getHue().intValue());
|
||||
lightState.setSaturation(hsb.getSaturation().intValue());
|
||||
lightState.setBrightness(brightness);
|
||||
return setLightStripState(lightState, OnOffType.from(brightness != 0), transition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the json for the set_light_State command to set the color temperature.
|
||||
*
|
||||
* @param colorTemperature the color temperature to set
|
||||
* @param transition the transition period for the action to take place
|
||||
* @return The json string of the command to send to the device
|
||||
*/
|
||||
public String setLightStripColorTemperature(final int colorTemperature, final int transition) {
|
||||
final SetLightState.ColorTemperature lightState = new SetLightState.ColorTemperature();
|
||||
lightState.setColorTemp(colorTemperature);
|
||||
return setLightStripState(lightState, OnOffType.ON, transition);
|
||||
}
|
||||
|
||||
private String setLightStripState(final SetLightState.LightOnOff lightOnOff, final OnOffType onOff,
|
||||
final int transition) {
|
||||
final SetLightState setLightState = new SetLightState();
|
||||
setLightState.setContext(new SetLightState.Context());
|
||||
setLightState.setLightState(lightOnOff);
|
||||
lightOnOff.setOnOff(onOff);
|
||||
lightOnOff.setTransition(transition);
|
||||
return gsonWithExpose.toJson(setLightState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the json response for the set_light_state command.
|
||||
*
|
||||
* @param response the json string
|
||||
* @return The data object containing the state data from the json string
|
||||
*/
|
||||
public @Nullable SetLightState setLightStripStateResponse(final String response) {
|
||||
return gsonWithExpose.fromJson(response, SetLightState.class);
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory;
|
||||
public class Connection {
|
||||
|
||||
public static final int TP_LINK_SMART_HOME_PORT = 9999;
|
||||
private static final int SOCKET_TIMEOUT_MILLISECONDS = 3_000;
|
||||
private static final int SOCKET_TIMEOUT_MILLISECONDS = 2_000;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(Connection.class);
|
||||
|
||||
|
@ -19,6 +19,7 @@ import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.tplinksmarthome.internal.device.BulbDevice;
|
||||
import org.openhab.binding.tplinksmarthome.internal.device.DimmerDevice;
|
||||
import org.openhab.binding.tplinksmarthome.internal.device.EnergySwitchDevice;
|
||||
import org.openhab.binding.tplinksmarthome.internal.device.LightStripDevice;
|
||||
import org.openhab.binding.tplinksmarthome.internal.device.PowerStripDevice;
|
||||
import org.openhab.binding.tplinksmarthome.internal.device.RangeExtenderDevice;
|
||||
import org.openhab.binding.tplinksmarthome.internal.device.SmartHomeDevice;
|
||||
@ -67,6 +68,9 @@ public class TPLinkSmartHomeHandlerFactory extends BaseThingHandlerFactory {
|
||||
case DIMMER:
|
||||
device = new DimmerDevice();
|
||||
break;
|
||||
case LIGHT_STRIP:
|
||||
device = new LightStripDevice(type);
|
||||
break;
|
||||
case PLUG:
|
||||
device = new SwitchDevice();
|
||||
break;
|
||||
|
@ -49,6 +49,10 @@ public enum TPLinkSmartHomeThingType {
|
||||
KL130("kl130", DeviceType.BULB, ColorScales.K_2500_9000),
|
||||
KL135("kl135", DeviceType.BULB, ColorScales.K_2500_6500),
|
||||
|
||||
// Light String thing Type UIDs.
|
||||
KL400("kl400", DeviceType.LIGHT_STRIP, ColorScales.K_2500_9000),
|
||||
KL430("kl430", DeviceType.LIGHT_STRIP, ColorScales.K_2500_9000),
|
||||
|
||||
// Plug Thing Type UIDs
|
||||
EP10("ep10", DeviceType.PLUG),
|
||||
HS100("hs100", DeviceType.PLUG),
|
||||
@ -175,6 +179,10 @@ public enum TPLinkSmartHomeThingType {
|
||||
* Dimmer device.
|
||||
*/
|
||||
DIMMER,
|
||||
/**
|
||||
* Light Strip device.
|
||||
*/
|
||||
LIGHT_STRIP,
|
||||
/**
|
||||
* Plug device.
|
||||
*/
|
||||
|
@ -28,11 +28,12 @@ import org.openhab.binding.tplinksmarthome.internal.Commands;
|
||||
import org.openhab.binding.tplinksmarthome.internal.TPLinkSmartHomeThingType;
|
||||
import org.openhab.binding.tplinksmarthome.internal.model.HasErrorResponse;
|
||||
import org.openhab.binding.tplinksmarthome.internal.model.LightState;
|
||||
import org.openhab.binding.tplinksmarthome.internal.model.TransitionLightStateResponse;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
@ -69,9 +70,9 @@ public class BulbDevice extends SmartHomeDevice {
|
||||
final int transitionPeriod = configuration.transitionPeriod;
|
||||
final HasErrorResponse response;
|
||||
|
||||
if (command instanceof OnOffType) {
|
||||
if (command instanceof OnOffType && CHANNELS_BULB_SWITCH.contains(channelId)) {
|
||||
response = handleOnOffType(channelId, (OnOffType) command, transitionPeriod);
|
||||
} else if (command instanceof HSBType) {
|
||||
} else if (command instanceof HSBType && CHANNEL_COLOR.equals(channelId)) {
|
||||
response = handleHSBType(channelId, (HSBType) command, transitionPeriod);
|
||||
} else if (command instanceof DecimalType) {
|
||||
response = handleDecimalType(channelId, (DecimalType) command, transitionPeriod);
|
||||
@ -82,42 +83,42 @@ public class BulbDevice extends SmartHomeDevice {
|
||||
return response != null;
|
||||
}
|
||||
|
||||
private @Nullable HasErrorResponse handleOnOffType(final String channelID, final OnOffType onOff,
|
||||
protected @Nullable HasErrorResponse handleOnOffType(final String channelID, final OnOffType onOff,
|
||||
final int transitionPeriod) throws IOException {
|
||||
if (CHANNELS_BULB_SWITCH.contains(channelID)) {
|
||||
return commands.setTransitionLightStateResponse(
|
||||
connection.sendCommand(commands.setLightState(onOff, transitionPeriod)));
|
||||
}
|
||||
return null;
|
||||
return commands.setTransitionLightStateResponse(
|
||||
connection.sendCommand(commands.setTransitionLightState(onOff, transitionPeriod)));
|
||||
}
|
||||
|
||||
private @Nullable HasErrorResponse handleDecimalType(final String channelID, final DecimalType command,
|
||||
final int transitionPeriod) throws IOException {
|
||||
final int intValue = command.intValue();
|
||||
|
||||
if (CHANNEL_COLOR.equals(channelID) || CHANNEL_BRIGHTNESS.equals(channelID)) {
|
||||
return commands.setTransitionLightStateResponse(
|
||||
connection.sendCommand(commands.setBrightness(command.intValue(), transitionPeriod)));
|
||||
return handleBrightness(intValue, transitionPeriod);
|
||||
} else if (CHANNEL_COLOR_TEMPERATURE.equals(channelID)) {
|
||||
return handleColorTemperature(convertPercentageToKelvin(command.intValue()), transitionPeriod);
|
||||
return handleColorTemperature(convertPercentageToKelvin(intValue), transitionPeriod);
|
||||
} else if (CHANNEL_COLOR_TEMPERATURE_ABS.equals(channelID)) {
|
||||
return handleColorTemperature(guardColorTemperature(command.intValue()), transitionPeriod);
|
||||
return handleColorTemperature(guardColorTemperature(intValue), transitionPeriod);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private @Nullable TransitionLightStateResponse handleColorTemperature(final int colorTemperature,
|
||||
final int transitionPeriod) throws IOException {
|
||||
protected @Nullable HasErrorResponse handleBrightness(final int brightness, final int transitionPeriod)
|
||||
throws IOException {
|
||||
return commands.setTransitionLightStateResponse(
|
||||
connection.sendCommand(commands.setTransitionLightStateBrightness(brightness, transitionPeriod)));
|
||||
}
|
||||
|
||||
protected @Nullable HasErrorResponse handleColorTemperature(final int colorTemperature, final int transitionPeriod)
|
||||
throws IOException {
|
||||
return commands.setTransitionLightStateResponse(
|
||||
connection.sendCommand(commands.setColorTemperature(colorTemperature, transitionPeriod)));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private HasErrorResponse handleHSBType(final String channelID, final HSBType command, final int transitionPeriod)
|
||||
throws IOException {
|
||||
if (CHANNEL_COLOR.equals(channelID)) {
|
||||
return commands.setTransitionLightStateResponse(
|
||||
connection.sendCommand(commands.setColor(command, transitionPeriod)));
|
||||
}
|
||||
return null;
|
||||
protected @Nullable HasErrorResponse handleHSBType(final String channelID, final HSBType command,
|
||||
final int transitionPeriod) throws IOException {
|
||||
return commands.setTransitionLightStateResponse(
|
||||
connection.sendCommand(commands.setTransitionLightStateColor(command, transitionPeriod)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -142,7 +143,7 @@ public class BulbDevice extends SmartHomeDevice {
|
||||
state = lightState.getOnOff();
|
||||
break;
|
||||
case CHANNEL_ENERGY_POWER:
|
||||
state = new DecimalType(deviceState.getRealtime().getPower());
|
||||
state = new QuantityType<>(deviceState.getRealtime().getPower(), Units.WATT);
|
||||
break;
|
||||
default:
|
||||
state = UnDefType.UNDEF;
|
||||
|
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 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.tplinksmarthome.internal.device;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.tplinksmarthome.internal.TPLinkSmartHomeThingType;
|
||||
import org.openhab.binding.tplinksmarthome.internal.model.HasErrorResponse;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
||||
/**
|
||||
* TP-Link Smart Home Light Strip.
|
||||
*
|
||||
* @author Hilbrand Bouwkamp - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LightStripDevice extends BulbDevice {
|
||||
|
||||
public LightStripDevice(final TPLinkSmartHomeThingType type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable HasErrorResponse handleOnOffType(final String channelID, final OnOffType onOff,
|
||||
final int transitionPeriod) throws IOException {
|
||||
return commands.setLightStripStateResponse(
|
||||
connection.sendCommand(commands.setLightStripState(onOff, transitionPeriod)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable HasErrorResponse handleBrightness(final int brightness, final int transitionPeriod)
|
||||
throws IOException {
|
||||
return commands.setLightStripStateResponse(
|
||||
connection.sendCommand(commands.setLightStripBrightness(brightness, transitionPeriod)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable HasErrorResponse handleColorTemperature(final int colorTemperature, final int transitionPeriod)
|
||||
throws IOException {
|
||||
return commands.setLightStripStateResponse(
|
||||
connection.sendCommand(commands.setLightStripColorTemperature(colorTemperature, transitionPeriod)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable HasErrorResponse handleHSBType(final String channelID, final HSBType command,
|
||||
final int transitionPeriod) throws IOException {
|
||||
return commands.setLightStripStateResponse(
|
||||
connection.sendCommand(commands.setLightStripColor(command, transitionPeriod)));
|
||||
}
|
||||
}
|
@ -12,10 +12,16 @@
|
||||
*/
|
||||
package org.openhab.binding.tplinksmarthome.internal.handler;
|
||||
|
||||
import static org.openhab.binding.tplinksmarthome.internal.TPLinkSmartHomeBindingConstants.*;
|
||||
import static org.openhab.binding.tplinksmarthome.internal.TPLinkSmartHomeBindingConstants.CHANNEL_RSSI;
|
||||
import static org.openhab.binding.tplinksmarthome.internal.TPLinkSmartHomeBindingConstants.CONFIG_DEVICE_ID;
|
||||
import static org.openhab.binding.tplinksmarthome.internal.TPLinkSmartHomeBindingConstants.CONFIG_IP;
|
||||
import static org.openhab.binding.tplinksmarthome.internal.TPLinkSmartHomeBindingConstants.FORCED_REFRESH_BOUNDERY_SECONDS;
|
||||
import static org.openhab.binding.tplinksmarthome.internal.TPLinkSmartHomeBindingConstants.FORCED_REFRESH_BOUNDERY_SWITCHED_SECONDS;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -38,6 +44,7 @@ import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
@ -55,6 +62,7 @@ import org.slf4j.LoggerFactory;
|
||||
public class SmartHomeHandler extends BaseThingHandler {
|
||||
|
||||
private static final Duration ONE_SECOND = Duration.ofSeconds(1);
|
||||
private static final int CONNECTION_IO_RETRIES = 5;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SmartHomeHandler.class);
|
||||
|
||||
@ -79,8 +87,8 @@ public class SmartHomeHandler extends BaseThingHandler {
|
||||
* @param type The device type
|
||||
* @param ipAddressService Cache keeping track of ip addresses of tp link devices
|
||||
*/
|
||||
public SmartHomeHandler(Thing thing, SmartHomeDevice smartHomeDevice, TPLinkSmartHomeThingType type,
|
||||
TPLinkIpAddressService ipAddressService) {
|
||||
public SmartHomeHandler(final Thing thing, final SmartHomeDevice smartHomeDevice,
|
||||
final TPLinkSmartHomeThingType type, final TPLinkIpAddressService ipAddressService) {
|
||||
super(thing);
|
||||
this.smartHomeDevice = smartHomeDevice;
|
||||
this.ipAddressService = ipAddressService;
|
||||
@ -90,7 +98,16 @@ public class SmartHomeHandler extends BaseThingHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUid, Command command) {
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return List.of(TPLinkSmartHomeActions.class);
|
||||
}
|
||||
|
||||
Connection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(final ChannelUID channelUid, final Command command) {
|
||||
try {
|
||||
if (command instanceof RefreshType) {
|
||||
updateChannelState(channelUid, fastCache.getValue());
|
||||
@ -100,7 +117,7 @@ public class SmartHomeHandler extends BaseThingHandler {
|
||||
} else {
|
||||
logger.debug("Command {} is not supported for channel: {}", command, channelUid.getId());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
} catch (final IOException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
@ -143,7 +160,7 @@ public class SmartHomeHandler extends BaseThingHandler {
|
||||
* @param config configuration to be used by the connection
|
||||
* @return new Connection object
|
||||
*/
|
||||
Connection createConnection(TPLinkSmartHomeConfiguration config) {
|
||||
Connection createConnection(final TPLinkSmartHomeConfiguration config) {
|
||||
return new Connection(config.ipAddress);
|
||||
}
|
||||
|
||||
@ -158,22 +175,34 @@ public class SmartHomeHandler extends BaseThingHandler {
|
||||
}
|
||||
|
||||
private @Nullable DeviceState refreshCache() {
|
||||
try {
|
||||
updateIpAddress();
|
||||
final DeviceState deviceState = new DeviceState(connection.sendCommand(smartHomeDevice.getUpdateCommand()));
|
||||
updateDeviceId(deviceState.getSysinfo().getDeviceId());
|
||||
smartHomeDevice.refreshedDeviceState(deviceState);
|
||||
if (getThing().getStatus() != ThingStatus.ONLINE) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
int retry = 1;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
updateIpAddress();
|
||||
final DeviceState deviceState = new DeviceState(
|
||||
connection.sendCommand(smartHomeDevice.getUpdateCommand()));
|
||||
updateDeviceId(deviceState.getSysinfo().getDeviceId());
|
||||
smartHomeDevice.refreshedDeviceState(deviceState);
|
||||
if (getThing().getStatus() != ThingStatus.ONLINE) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
return deviceState;
|
||||
} catch (final IOException e) {
|
||||
// If there is a connection problem retry before throwing an exception
|
||||
if (retry < CONNECTION_IO_RETRIES) {
|
||||
logger.trace("Communication error, retry {}", retry, e);
|
||||
retry++;
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
return null;
|
||||
}
|
||||
} catch (final RuntimeException e) {
|
||||
logger.debug("Obtaining new device data unexpectedly crashed. If this keeps happening please report: ",
|
||||
e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.DISABLED, e.getMessage());
|
||||
return null;
|
||||
}
|
||||
return deviceState;
|
||||
} catch (IOException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
return null;
|
||||
} catch (RuntimeException e) {
|
||||
logger.debug("Obtaining new device data unexpectedly crashed. If this keeps happening please report: ", e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.DISABLED, e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,10 +216,10 @@ public class SmartHomeHandler extends BaseThingHandler {
|
||||
// The device id is needed to get the ip address so if not known no need to continue.
|
||||
return;
|
||||
}
|
||||
String lastKnownIpAddress = ipAddressService.getLastKnownIpAddress(configuration.deviceId);
|
||||
final String lastKnownIpAddress = ipAddressService.getLastKnownIpAddress(configuration.deviceId);
|
||||
|
||||
if (lastKnownIpAddress != null && !lastKnownIpAddress.equals(configuration.ipAddress)) {
|
||||
Configuration editConfig = editConfiguration();
|
||||
final Configuration editConfig = editConfiguration();
|
||||
editConfig.put(CONFIG_IP, lastKnownIpAddress);
|
||||
updateConfiguration(editConfig);
|
||||
configuration.ipAddress = lastKnownIpAddress;
|
||||
@ -206,9 +235,9 @@ public class SmartHomeHandler extends BaseThingHandler {
|
||||
* @throws IllegalArgumentException if the configured device id doesn't match with the id reported by the device
|
||||
* itself.
|
||||
*/
|
||||
private void updateDeviceId(String actualDeviceId) {
|
||||
private void updateDeviceId(final String actualDeviceId) {
|
||||
if (StringUtil.isBlank(configuration.deviceId)) {
|
||||
Configuration editConfig = editConfiguration();
|
||||
final Configuration editConfig = editConfiguration();
|
||||
editConfig.put(CONFIG_DEVICE_ID, actualDeviceId);
|
||||
updateConfiguration(editConfig);
|
||||
configuration.deviceId = actualDeviceId;
|
||||
@ -222,7 +251,7 @@ public class SmartHomeHandler extends BaseThingHandler {
|
||||
/**
|
||||
* Starts the background refresh thread.
|
||||
*/
|
||||
private void startAutomaticRefresh(TPLinkSmartHomeConfiguration config) {
|
||||
private void startAutomaticRefresh(final TPLinkSmartHomeConfiguration config) {
|
||||
if (refreshJob == null || refreshJob.isCancelled()) {
|
||||
refreshJob = scheduler.scheduleWithFixedDelay(this::refreshChannels, config.refresh, config.refresh,
|
||||
TimeUnit.SECONDS);
|
||||
@ -241,11 +270,11 @@ public class SmartHomeHandler extends BaseThingHandler {
|
||||
* @param deviceState the state object containing the value to set of the channel
|
||||
*
|
||||
*/
|
||||
private void updateChannelState(ChannelUID channelUID, @Nullable DeviceState deviceState) {
|
||||
private void updateChannelState(final ChannelUID channelUID, @Nullable final DeviceState deviceState) {
|
||||
if (!isLinked(channelUID)) {
|
||||
return;
|
||||
}
|
||||
String channelId = channelUID.isInGroup() ? channelUID.getIdWithoutGroup() : channelUID.getId();
|
||||
final String channelId = channelUID.isInGroup() ? channelUID.getIdWithoutGroup() : channelUID.getId();
|
||||
final State state;
|
||||
|
||||
if (deviceState == null) {
|
||||
|
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 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.tplinksmarthome.internal.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.automation.annotation.ActionInput;
|
||||
import org.openhab.core.automation.annotation.ActionOutput;
|
||||
import org.openhab.core.automation.annotation.RuleAction;
|
||||
import org.openhab.core.thing.binding.ThingActions;
|
||||
import org.openhab.core.thing.binding.ThingActionsScope;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* TP-Link Smart Home Rule Actions.
|
||||
*
|
||||
* @author Hilbrand Bouwkamp - Initial contribution
|
||||
*/
|
||||
@ThingActionsScope(name = "tplinksmarthome")
|
||||
@NonNullByDefault
|
||||
public class TPLinkSmartHomeActions implements ThingActions, ThingHandlerService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(TPLinkSmartHomeActions.class);
|
||||
|
||||
private @Nullable SmartHomeHandler handler;
|
||||
|
||||
@RuleAction(label = "@text/actions.tplinksmarthome.send.label", description = "@text/actions.tplinksmarthome.send.description")
|
||||
@ActionOutput(name = "response", label = "@text/actions.tplinksmarthome.send.response.label", description = "@text/actions.tplinksmarthome.send.response.description", type = "java.lang.String")
|
||||
public String send(
|
||||
@ActionInput(name = "command", label = "@text/actions.tplinksmarthome.send.command.label", description = "@text/actions.tplinksmarthome.send.command.description", type = "java.lang.String", required = true) final String command)
|
||||
throws IOException {
|
||||
if (handler instanceof SmartHomeHandler) {
|
||||
return handler.getConnection().sendCommand(command);
|
||||
} else {
|
||||
logger.warn("Could not send command to tplink device because handler not set.");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static String send(final ThingActions actions, final String command) throws IOException {
|
||||
return ((TPLinkSmartHomeActions) actions).send(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThingHandler(final ThingHandler handler) {
|
||||
if (handler instanceof SmartHomeHandler) {
|
||||
this.handler = (SmartHomeHandler) handler;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingHandler getThingHandler() {
|
||||
return handler;
|
||||
}
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
/**
|
||||
* 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.tplinksmarthome.internal.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Data class for setting the TP-Link Smart Light Strip state and retrieving the result.
|
||||
*
|
||||
* @author Hilbrand Bouwkamp - Initial contribution
|
||||
*/
|
||||
public class SetLightState implements HasErrorResponse {
|
||||
|
||||
private static final int GROUPS_INDEX_HUE = 2;
|
||||
private static final int GROUPS_INDEX_SATURATION = 3;
|
||||
private static final int GROUPS_INDEX_BRIGHTNESS = 4;
|
||||
private static final int GROUPS_INDEX_COLOR_TEMPERATURE = 5;
|
||||
|
||||
public static class ColorTemperature extends LightOnOff {
|
||||
@Expose(deserialize = false)
|
||||
private int colorTemp;
|
||||
@Expose(deserialize = false)
|
||||
private int hue = 0;
|
||||
@Expose(deserialize = false)
|
||||
private int saturation = 0;
|
||||
|
||||
public void setColorTemp(final int colorTemperature) {
|
||||
this.colorTemp = colorTemperature;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Color extends Brightness {
|
||||
@Expose(deserialize = false)
|
||||
private int colorTemp;
|
||||
@Expose(deserialize = false)
|
||||
private int hue;
|
||||
@Expose(deserialize = false)
|
||||
private int saturation;
|
||||
|
||||
public void setHue(final int hue) {
|
||||
this.hue = hue;
|
||||
}
|
||||
|
||||
public void setSaturation(final int saturation) {
|
||||
this.saturation = saturation;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Brightness extends LightOnOff {
|
||||
@Expose(deserialize = false)
|
||||
private int brightness;
|
||||
|
||||
public void setBrightness(final int brightness) {
|
||||
this.brightness = brightness;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LightOnOff extends ErrorResponse {
|
||||
@Expose
|
||||
private int onOff;
|
||||
@Expose(serialize = false)
|
||||
private String mode;
|
||||
@Expose(deserialize = false)
|
||||
private int transition;
|
||||
/**
|
||||
* groups contain status: [[0,31,0,0,73,5275]]
|
||||
* [?,?,hue,saturation,brightness,color_temp]
|
||||
*/
|
||||
@Expose(serialize = false)
|
||||
protected int[][] groups;
|
||||
|
||||
public OnOffType getOnOff() {
|
||||
return OnOffType.from(onOff == 1);
|
||||
}
|
||||
|
||||
public void setOnOff(final OnOffType onOff) {
|
||||
this.onOff = onOff == OnOffType.ON ? 1 : 0;
|
||||
}
|
||||
|
||||
public void setTransition(final int transition) {
|
||||
this.transition = transition;
|
||||
}
|
||||
|
||||
public int getHue() {
|
||||
return groups[0][GROUPS_INDEX_HUE];
|
||||
}
|
||||
|
||||
public int getSaturation() {
|
||||
return groups[0][GROUPS_INDEX_SATURATION];
|
||||
}
|
||||
|
||||
public int getBrightness() {
|
||||
return groups[0][GROUPS_INDEX_BRIGHTNESS];
|
||||
}
|
||||
|
||||
public int getColorTemperature() {
|
||||
return groups[0][GROUPS_INDEX_COLOR_TEMPERATURE];
|
||||
}
|
||||
|
||||
public int[][] getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "onOff:" + onOff + ", mode:" + mode + ", transition:" + transition + ", groups:"
|
||||
+ Arrays.toString(groups);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Context {
|
||||
@Expose
|
||||
private String source = "12345668-1234-1234-1234-123456789012";
|
||||
|
||||
public String getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public void setSource(final String source) {
|
||||
this.source = source;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LightingStrip {
|
||||
@Expose
|
||||
private LightOnOff setLightState;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "setLightState:{" + setLightState + "}";
|
||||
}
|
||||
}
|
||||
|
||||
@NonNullByDefault
|
||||
@SerializedName("smartlife.iot.lightStrip")
|
||||
@Expose
|
||||
private final LightingStrip strip = new LightingStrip();
|
||||
|
||||
@Expose(deserialize = false)
|
||||
private Context context;
|
||||
|
||||
public void setLightState(final LightOnOff lightState) {
|
||||
strip.setLightState = lightState;
|
||||
}
|
||||
|
||||
public void setContext(final Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ErrorResponse getErrorResponse() {
|
||||
return strip.setLightState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SetLightState {strip:{" + strip + "}";
|
||||
}
|
||||
}
|
@ -53,6 +53,10 @@ thing-type.tplinksmarthome.kl130.label = KL130
|
||||
thing-type.tplinksmarthome.kl130.description = TP-Link KL130 Smart Wi-Fi LED Bulb with Color Changing Hue
|
||||
thing-type.tplinksmarthome.kl135.label = KL135
|
||||
thing-type.tplinksmarthome.kl135.description = TP-Link KL135 Kasa Smart Wi-Fi Bulb Multicolor
|
||||
thing-type.tplinksmarthome.kl400.label = KL400
|
||||
thing-type.tplinksmarthome.kl400.description = TP-Link KL400 Kasa Smart Light Strip, Multicolour
|
||||
thing-type.tplinksmarthome.kl430.label = KL430
|
||||
thing-type.tplinksmarthome.kl430.description = TP-Link KL430 Kasa Smart Light Strip, Multicolour
|
||||
thing-type.tplinksmarthome.kl50.label = KL50
|
||||
thing-type.tplinksmarthome.kl50.description = Kasa Filament Smart Bulb, Soft White
|
||||
thing-type.tplinksmarthome.kl60.label = KL60
|
||||
@ -150,3 +154,12 @@ channel-type.tplinksmarthome.switch-readonly.label = Switch
|
||||
channel-type.tplinksmarthome.switch-readonly.description = Shows the switch state of the Smart Home device.
|
||||
channel-type.tplinksmarthome.voltage.label = Voltage
|
||||
channel-type.tplinksmarthome.voltage.description = Actual voltage usage.
|
||||
|
||||
# actions
|
||||
|
||||
actions.tplinksmarthome.send.label = Send Command
|
||||
actions.tplinksmarthome.send.description = Sends the command, a json string, encrypted to a TP-Link device and decrypts the json response.
|
||||
actions.tplinksmarthome.send.command.label = Command
|
||||
actions.tplinksmarthome.send.command.description = The json string command to send to the TP-Link device.
|
||||
actions.tplinksmarthome.send.response.label = Response
|
||||
actions.tplinksmarthome.send.response.description = The decrypted json response returned by the TP-Link device.
|
||||
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="tplinksmarthome"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<thing-type id="kl400">
|
||||
<label>KL400</label>
|
||||
<description>TP-Link KL400 Kasa Smart Light Strip, Multicolour</description>
|
||||
<category>Lightbulb</category>
|
||||
|
||||
<channels>
|
||||
<channel id="color" typeId="system.color"/>
|
||||
<channel id="colorTemperature" typeId="system.color-temperature"/>
|
||||
<channel id="colorTemperatureAbs" typeId="colorTemperatureAbs2"/>
|
||||
<channel id="power" typeId="power"/>
|
||||
<channel id="rssi" typeId="rssi"/>
|
||||
</channels>
|
||||
|
||||
<representation-property>deviceId</representation-property>
|
||||
|
||||
<config-description-ref uri="thing-type:tplinksmarthome:device-bulb"/>
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="tplinksmarthome"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<thing-type id="kl430">
|
||||
<label>KL430</label>
|
||||
<description>TP-Link KL430 Kasa Smart Light Strip, Multicolour</description>
|
||||
<category>Lightbulb</category>
|
||||
|
||||
<channels>
|
||||
<channel id="color" typeId="system.color"/>
|
||||
<channel id="colorTemperature" typeId="system.color-temperature"/>
|
||||
<channel id="colorTemperatureAbs" typeId="colorTemperatureAbs2"/>
|
||||
<channel id="power" typeId="power"/>
|
||||
<channel id="rssi" typeId="rssi"/>
|
||||
</channels>
|
||||
|
||||
<representation-property>deviceId</representation-property>
|
||||
|
||||
<config-description-ref uri="thing-type:tplinksmarthome:device-bulb"/>
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
@ -34,6 +34,8 @@ import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
@ -173,7 +175,7 @@ public class BulbDeviceTest extends DeviceTestBase<BulbDevice> {
|
||||
|
||||
@Test
|
||||
public void testUpdateChannelPower() {
|
||||
assertEquals(new DecimalType(10.8), device.updateChannel(CHANNEL_UID_ENERGY_POWER, deviceState),
|
||||
assertEquals(new QuantityType<>(10.8, Units.WATT), device.updateChannel(CHANNEL_UID_ENERGY_POWER, deviceState),
|
||||
"Power values should be set");
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ package org.openhab.binding.tplinksmarthome.internal.device;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
@ -63,7 +63,7 @@ public class DeviceTestBase<T extends SmartHomeDevice> {
|
||||
*
|
||||
* @throws IOException exception in case device not reachable
|
||||
*/
|
||||
protected DeviceTestBase(T device, String deviceStateFilename) throws IOException {
|
||||
protected DeviceTestBase(final T device, final String deviceStateFilename) throws IOException {
|
||||
this.device = device;
|
||||
this.deviceStateFilename = deviceStateFilename;
|
||||
configuration.ipAddress = "localhost";
|
||||
@ -80,7 +80,7 @@ public class DeviceTestBase<T extends SmartHomeDevice> {
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws IOException {
|
||||
when(socket.getOutputStream()).thenReturn(outputStream);
|
||||
lenient().when(socket.getOutputStream()).thenReturn(outputStream);
|
||||
deviceState = new DeviceState(ModelTestUtil.readJson(deviceStateFilename));
|
||||
}
|
||||
|
||||
@ -91,11 +91,11 @@ public class DeviceTestBase<T extends SmartHomeDevice> {
|
||||
* @param responseFilenames names of the files to read that contains the answer. It's the unencrypted json string
|
||||
* @throws IOException exception in case device not reachable
|
||||
*/
|
||||
protected void setSocketReturnAssert(String... responseFilenames) throws IOException {
|
||||
AtomicInteger index = new AtomicInteger();
|
||||
protected void setSocketReturnAssert(final String... responseFilenames) throws IOException {
|
||||
final AtomicInteger index = new AtomicInteger();
|
||||
|
||||
doAnswer(i -> {
|
||||
String stateResponse = ModelTestUtil.readJson(responseFilenames[index.getAndIncrement()]);
|
||||
lenient().doAnswer(i -> {
|
||||
final String stateResponse = ModelTestUtil.readJson(responseFilenames[index.getAndIncrement()]);
|
||||
|
||||
return new ByteArrayInputStream(CryptUtil.encryptWithLength(stateResponse));
|
||||
}).when(socket).getInputStream();
|
||||
@ -109,20 +109,20 @@ public class DeviceTestBase<T extends SmartHomeDevice> {
|
||||
* @param filenames names of the files containing the reference json
|
||||
* @throws IOException exception in case device not reachable
|
||||
*/
|
||||
protected void assertInput(String... filenames) throws IOException {
|
||||
protected void assertInput(final String... filenames) throws IOException {
|
||||
assertInput(Function.identity(), Function.identity(), filenames);
|
||||
}
|
||||
|
||||
protected void assertInput(Function<String, String> jsonProcessor, Function<String, String> expectedProcessor,
|
||||
String... filenames) throws IOException {
|
||||
AtomicInteger index = new AtomicInteger();
|
||||
protected void assertInput(final Function<String, String> jsonProcessor,
|
||||
final Function<String, String> expectedProcessor, final String... filenames) throws IOException {
|
||||
final AtomicInteger index = new AtomicInteger();
|
||||
|
||||
doAnswer(arg -> {
|
||||
String json = jsonProcessor.apply(ModelTestUtil.readJson(filenames[index.get()]));
|
||||
lenient().doAnswer(arg -> {
|
||||
final String json = jsonProcessor.apply(ModelTestUtil.readJson(filenames[index.get()]));
|
||||
|
||||
byte[] input = (byte[]) arg.getArguments()[0];
|
||||
final byte[] input = (byte[]) arg.getArguments()[0];
|
||||
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(input)) {
|
||||
String expectedString = expectedProcessor.apply(CryptUtil.decryptWithLength(inputStream));
|
||||
final String expectedString = expectedProcessor.apply(CryptUtil.decryptWithLength(inputStream));
|
||||
assertEquals(json, expectedString, filenames[index.get()]);
|
||||
}
|
||||
index.incrementAndGet();
|
||||
|
@ -0,0 +1,186 @@
|
||||
/**
|
||||
* 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.tplinksmarthome.internal.device;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.openhab.binding.tplinksmarthome.internal.ChannelUIDConstants.CHANNEL_UID_BRIGHTNESS;
|
||||
import static org.openhab.binding.tplinksmarthome.internal.ChannelUIDConstants.CHANNEL_UID_COLOR;
|
||||
import static org.openhab.binding.tplinksmarthome.internal.ChannelUIDConstants.CHANNEL_UID_COLOR_TEMPERATURE;
|
||||
import static org.openhab.binding.tplinksmarthome.internal.ChannelUIDConstants.CHANNEL_UID_COLOR_TEMPERATURE_ABS;
|
||||
import static org.openhab.binding.tplinksmarthome.internal.ChannelUIDConstants.CHANNEL_UID_ENERGY_POWER;
|
||||
import static org.openhab.binding.tplinksmarthome.internal.ChannelUIDConstants.CHANNEL_UID_OTHER;
|
||||
import static org.openhab.binding.tplinksmarthome.internal.ChannelUIDConstants.CHANNEL_UID_SWITCH;
|
||||
import static org.openhab.binding.tplinksmarthome.internal.TPLinkSmartHomeThingType.KL430;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.tplinksmarthome.internal.model.ModelTestUtil;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.HSBType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* Test class for {@link BulbDevice} class.
|
||||
*
|
||||
* @author Hilbrand Bouwkamp - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class LightStripDeviceTest extends DeviceTestBase<LightStripDevice> {
|
||||
|
||||
private static final String DEVICE_OFF = "bulb_get_sysinfo_response_off";
|
||||
|
||||
public LightStripDeviceTest() throws IOException {
|
||||
super(new LightStripDevice(KL430), "bulb_get_sysinfo_response_on");
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
@Override
|
||||
public void setUp() throws IOException {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandBrightness() throws IOException {
|
||||
assertInput("kl430_set_brightness");
|
||||
setSocketReturnAssert("kl430_set_brightness_response");
|
||||
assertTrue(device.handleCommand(CHANNEL_UID_BRIGHTNESS, new PercentType(73)),
|
||||
"Brightness channel should be handled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandBrightnessOnOff() throws IOException {
|
||||
assertInput("kl430_set_on");
|
||||
setSocketReturnAssert("kl430_set_brightness_response");
|
||||
assertTrue(device.handleCommand(CHANNEL_UID_BRIGHTNESS, OnOffType.ON),
|
||||
"Brightness channel with OnOff state should be handled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandColor() throws IOException {
|
||||
assertInput("kl430_set_color");
|
||||
setSocketReturnAssert("kl430_set_color_response");
|
||||
assertTrue(device.handleCommand(CHANNEL_UID_COLOR, new HSBType("115,75,73")),
|
||||
"Color channel should be handled");
|
||||
}
|
||||
|
||||
public void testHandleCommandColorBrightness() throws IOException {
|
||||
assertInput("kl430_set_brightness");
|
||||
setSocketReturnAssert("kl430_set_brightness_response");
|
||||
assertTrue(device.handleCommand(CHANNEL_UID_COLOR, new PercentType(33)),
|
||||
"Color channel with Percentage state (=brightness) should be handled");
|
||||
}
|
||||
|
||||
public void testHandleCommandColorOnOff() throws IOException {
|
||||
assertInput("bulb_transition_light_state_on");
|
||||
assertTrue(device.handleCommand(CHANNEL_UID_COLOR, OnOffType.ON),
|
||||
"Color channel with OnOff state should be handled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandColorTemperature() throws IOException {
|
||||
assertInput("kl430_set_colortemperature");
|
||||
setSocketReturnAssert("kl430_set_colortemperature_response");
|
||||
assertTrue(device.handleCommand(CHANNEL_UID_COLOR_TEMPERATURE, new PercentType(40)),
|
||||
"Color temperature channel should be handled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandColorTemperatureAbs() throws IOException {
|
||||
assertInput("kl430_set_colortemperature");
|
||||
setSocketReturnAssert("kl430_set_colortemperature_response");
|
||||
assertTrue(device.handleCommand(CHANNEL_UID_COLOR_TEMPERATURE_ABS, new DecimalType(5100)),
|
||||
"Color temperature channel should be handled");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCommandColorTemperatureOnOff() throws IOException {
|
||||
assertInput("kl430_set_on");
|
||||
setSocketReturnAssert("kl430_set_colortemperature_response");
|
||||
assertTrue(device.handleCommand(CHANNEL_UID_COLOR_TEMPERATURE, OnOffType.ON),
|
||||
"Color temperature channel with OnOff state should be handled");
|
||||
}
|
||||
|
||||
// ---- Update ----
|
||||
|
||||
@Test
|
||||
public void testUpdateChannelBrightnessOn() {
|
||||
assertEquals(new PercentType(92), device.updateChannel(CHANNEL_UID_BRIGHTNESS, deviceState),
|
||||
"Brightness should be on");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateChannelBrightnessOff() throws IOException {
|
||||
deviceState = new DeviceState(ModelTestUtil.readJson(DEVICE_OFF));
|
||||
assertEquals(PercentType.ZERO, device.updateChannel(CHANNEL_UID_BRIGHTNESS, deviceState),
|
||||
"Brightness should be off");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateChannelColorOn() {
|
||||
assertEquals(new HSBType("7,44,92"), device.updateChannel(CHANNEL_UID_COLOR, deviceState),
|
||||
"Color should be on");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateChannelColorOff() throws IOException {
|
||||
deviceState = new DeviceState(ModelTestUtil.readJson(DEVICE_OFF));
|
||||
assertEquals(new HSBType("7,44,0"), device.updateChannel(CHANNEL_UID_COLOR, deviceState),
|
||||
"Color should be off");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateChannelSwitchOn() {
|
||||
assertSame(OnOffType.ON, device.updateChannel(CHANNEL_UID_SWITCH, deviceState), "Switch should be on");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateChannelSwitchOff() throws IOException {
|
||||
deviceState = new DeviceState(ModelTestUtil.readJson(DEVICE_OFF));
|
||||
assertSame(OnOffType.OFF, device.updateChannel(CHANNEL_UID_SWITCH, deviceState), "Switch should be off");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateChannelColorTemperature() throws IOException {
|
||||
assertInput("kl430_set_colortemperature");
|
||||
assertEquals(new PercentType(2), device.updateChannel(CHANNEL_UID_COLOR_TEMPERATURE, deviceState),
|
||||
"Color temperature should be set");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateChannelColorTemperatureAbs() throws IOException {
|
||||
assertInput("kl430_set_colortemperature");
|
||||
assertEquals(new DecimalType(2630), device.updateChannel(CHANNEL_UID_COLOR_TEMPERATURE_ABS, deviceState),
|
||||
"Color temperature should be set");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateChannelOther() {
|
||||
assertSame(UnDefType.UNDEF, device.updateChannel(CHANNEL_UID_OTHER, deviceState),
|
||||
"Unknown channel should return UNDEF");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateChannelPower() {
|
||||
assertEquals(new QuantityType<>(10.8, Units.WATT), device.updateChannel(CHANNEL_UID_ENERGY_POWER, deviceState),
|
||||
"Power values should be set");
|
||||
}
|
||||
}
|
@ -75,8 +75,8 @@ public class SmartHomeHandlerTest {
|
||||
configuration.put(CONFIG_IP, "localhost");
|
||||
configuration.put(CONFIG_REFRESH, 1);
|
||||
when(thing.getConfiguration()).thenReturn(configuration);
|
||||
when(smartHomeDevice.getUpdateCommand()).thenReturn(Commands.getSysinfo());
|
||||
when(connection.sendCommand(Commands.getSysinfo()))
|
||||
lenient().when(smartHomeDevice.getUpdateCommand()).thenReturn(Commands.getSysinfo());
|
||||
lenient().when(connection.sendCommand(Commands.getSysinfo()))
|
||||
.thenReturn(ModelTestUtil.readJson("plug_get_sysinfo_response"));
|
||||
handler = new SmartHomeHandler(thing, smartHomeDevice, TPLinkSmartHomeThingType.HS100, discoveryService) {
|
||||
@Override
|
||||
@ -84,8 +84,8 @@ public class SmartHomeHandlerTest {
|
||||
return connection;
|
||||
}
|
||||
};
|
||||
when(smartHomeDevice.handleCommand(eq(CHANNEL_UID_SWITCH), any())).thenReturn(true);
|
||||
when(callback.isChannelLinked(any())).thenReturn(true);
|
||||
lenient().when(smartHomeDevice.handleCommand(eq(CHANNEL_UID_SWITCH), any())).thenReturn(true);
|
||||
lenient().when(callback.isChannelLinked(any())).thenReturn(true);
|
||||
handler.setCallback(callback);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,12 @@
|
||||
{
|
||||
"smartlife.iot.lightStrip": {
|
||||
"set_light_state": {
|
||||
"brightness": 73,
|
||||
"on_off": 1,
|
||||
"transition": 10
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"source": "12345668-1234-1234-1234-123456789012"
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"smartlife.iot.lightStrip": {
|
||||
"set_light_state": {
|
||||
"on_off": 1,
|
||||
"mode": "normal",
|
||||
"groups": [
|
||||
[
|
||||
0,
|
||||
31,
|
||||
0,
|
||||
0,
|
||||
73,
|
||||
4970
|
||||
]
|
||||
],
|
||||
"err_code": 0
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"smartlife.iot.lightStrip": {
|
||||
"set_light_state": {
|
||||
"color_temp": 0,
|
||||
"hue": 115,
|
||||
"saturation": 75,
|
||||
"brightness": 73,
|
||||
"on_off": 1,
|
||||
"transition": 10
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"source": "12345668-1234-1234-1234-123456789012"
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"smartlife.iot.lightStrip": {
|
||||
"set_light_state": {
|
||||
"on_off": 1,
|
||||
"mode": "normal",
|
||||
"groups": [
|
||||
[
|
||||
0,
|
||||
31,
|
||||
115,
|
||||
75,
|
||||
73,
|
||||
0
|
||||
]
|
||||
],
|
||||
"err_code": 0
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
{
|
||||
"smartlife.iot.lightStrip": {
|
||||
"set_light_state": {
|
||||
"color_temp": 5100,
|
||||
"hue": 0,
|
||||
"saturation": 0,
|
||||
"on_off": 1,
|
||||
"transition": 10
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"source": "12345668-1234-1234-1234-123456789012"
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"smartlife.iot.lightStrip": {
|
||||
"set_light_state": {
|
||||
"on_off": 1,
|
||||
"mode": "normal",
|
||||
"groups": [
|
||||
[
|
||||
0,
|
||||
31,
|
||||
0,
|
||||
0,
|
||||
73,
|
||||
5100
|
||||
]
|
||||
],
|
||||
"err_code": 0
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"smartlife.iot.lightStrip": {
|
||||
"set_light_state": {
|
||||
"on_off": 1,
|
||||
"transition": 10
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"source": "12345668-1234-1234-1234-123456789012"
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"smartlife.iot.lightStrip": {
|
||||
"set_light_state": {
|
||||
"on_off": 1,
|
||||
"mode": "normal",
|
||||
"groups": [
|
||||
[
|
||||
0,
|
||||
31,
|
||||
0,
|
||||
0,
|
||||
100,
|
||||
2630
|
||||
]
|
||||
],
|
||||
"err_code": 0
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user