Skip to content

Commit

Permalink
[tplinksmarthome] Added KL400, KL430 lightstrip support (openhab#12000)
Browse files Browse the repository at this point in the history
Closes openhab#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>
  • Loading branch information
Hilbrand authored and andan67 committed Nov 5, 2022
1 parent 53ff684 commit 42a9e85
Show file tree
Hide file tree
Showing 25 changed files with 944 additions and 131 deletions.
24 changes: 21 additions & 3 deletions bundles/org.openhab.binding.tplinksmarthome/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
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;
Expand Down Expand Up @@ -79,7 +80,7 @@ public static String getRealtimeBulbAndSysinfo() {
* @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 + "}";
}

Expand All @@ -90,8 +91,8 @@ public static String getRealtimeWithContext(String id) {
* @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();
}

Expand All @@ -111,8 +112,8 @@ public static String getSysinfo() {
* @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();
}

Expand All @@ -123,8 +124,8 @@ public Sysinfo getSysinfoReponse(String getSysinfoReponse) {
* @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);
Expand All @@ -138,7 +139,7 @@ public String setRelayState(OnOffType onOff, @Nullable String childId) {
* @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);
}

Expand All @@ -148,8 +149,8 @@ public String setRelayState(OnOffType onOff, @Nullable String childId) {
* @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);
}
Expand All @@ -160,7 +161,7 @@ public String setSwitchState(OnOffType onOff) {
* @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);
}

Expand All @@ -170,8 +171,8 @@ public String setSwitchState(OnOffType onOff) {
* @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);
}
Expand All @@ -182,35 +183,19 @@ public String setDimmerBrightness(int brightness) {
* @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.
*
* @param onOff the led state to set
* @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);
Expand All @@ -224,25 +209,32 @@ public String setLedOn(OnOffType onOff, @Nullable String childId) {
* @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.
*
* @param brightness the brightness value
* @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);
}

/**
Expand All @@ -252,17 +244,13 @@ public String setBrightness(int brightness, int transitionPeriod) {
* @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);
}

/**
Expand All @@ -272,13 +260,18 @@ public String setColor(HSBType hsb, int transitionPeriod) {
* @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);
}

Expand All @@ -288,7 +281,82 @@ public String setColorTemperature(int colorTemperature, int transitionPeriod) {
* @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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
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);

Expand Down
Loading

0 comments on commit 42a9e85

Please sign in to comment.