Fix tplink HS220 dimmers (round 2) (#33928)

* HS220 dimmers are handled as lights with a limited feature set

* Dimmers look up has has_emeter every call so this is cached as well now
to resovle the performance issue.
This commit is contained in:
J. Nick Koston 2020-04-09 19:10:02 -05:00 committed by GitHub
parent c2d1db61b6
commit a000af5c03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 28 deletions

View File

@ -40,6 +40,7 @@ ATTR_MONTHLY_ENERGY_KWH = "monthly_energy_kwh"
LIGHT_STATE_DFT_ON = "dft_on_state"
LIGHT_STATE_ON_OFF = "on_off"
LIGHT_STATE_RELAY_STATE = "relay_state"
LIGHT_STATE_BRIGHTNESS = "brightness"
LIGHT_STATE_COLOR_TEMP = "color_temp"
LIGHT_STATE_HUE = "hue"
@ -116,6 +117,7 @@ class LightFeatures(NamedTuple):
supported_features: int
min_mireds: float
max_mireds: float
has_emeter: bool
class TPLinkSmartBulb(Light):
@ -273,8 +275,9 @@ class TPLinkSmartBulb(Light):
model = sysinfo[LIGHT_SYSINFO_MODEL]
min_mireds = None
max_mireds = None
has_emeter = self.smartbulb.has_emeter
if sysinfo.get(LIGHT_SYSINFO_IS_DIMMABLE):
if sysinfo.get(LIGHT_SYSINFO_IS_DIMMABLE) or LIGHT_STATE_BRIGHTNESS in sysinfo:
supported_features += SUPPORT_BRIGHTNESS
if sysinfo.get(LIGHT_SYSINFO_IS_VARIABLE_COLOR_TEMP):
supported_features += SUPPORT_COLOR_TEMP
@ -294,6 +297,7 @@ class TPLinkSmartBulb(Light):
supported_features=supported_features,
min_mireds=min_mireds,
max_mireds=max_mireds,
has_emeter=has_emeter,
)
def _get_light_state_retry(self) -> LightState:
@ -348,7 +352,7 @@ class TPLinkSmartBulb(Light):
return self._light_state_from_params(self._get_device_state())
def _update_emeter(self):
if not self.smartbulb.has_emeter:
if not self._light_features.has_emeter:
return
now = dt_util.utcnow()
@ -434,10 +438,11 @@ class TPLinkSmartBulb(Light):
if isinstance(self.smartbulb, SmartBulb):
return self.smartbulb.get_light_state()
sysinfo = self.smartbulb.sys_info
# Its not really a bulb, its a dimmable SmartPlug (aka Wall Switch)
return {
LIGHT_STATE_ON_OFF: self.smartbulb.state,
LIGHT_STATE_BRIGHTNESS: self.smartbulb.brightness,
LIGHT_STATE_ON_OFF: sysinfo[LIGHT_STATE_RELAY_STATE],
LIGHT_STATE_BRIGHTNESS: sysinfo.get(LIGHT_STATE_BRIGHTNESS, 0),
LIGHT_STATE_COLOR_TEMP: 0,
LIGHT_STATE_HUE: 0,
LIGHT_STATE_SATURATION: 0,
@ -456,9 +461,12 @@ class TPLinkSmartBulb(Light):
if state[LIGHT_STATE_BRIGHTNESS]:
self.smartbulb.brightness = state[LIGHT_STATE_BRIGHTNESS]
else:
self.smartbulb.state = 0
self.smartbulb.state = self.smartbulb.SWITCH_STATE_OFF
elif LIGHT_STATE_ON_OFF in state:
self.smartbulb.state = state[LIGHT_STATE_ON_OFF]
if state[LIGHT_STATE_ON_OFF]:
self.smartbulb.state = self.smartbulb.SWITCH_STATE_ON
else:
self.smartbulb.state = self.smartbulb.SWITCH_STATE_OFF
return self._get_device_state()

View File

@ -49,7 +49,6 @@ class SmartSwitchMockData(NamedTuple):
"""Mock smart switch data."""
sys_info: dict
light_state: dict
state_mock: Mock
brightness_mock: Mock
get_sysinfo_mock: Mock
@ -188,28 +187,28 @@ def dimmer_switch_mock_data_fixture() -> None:
"model": "HS220",
"alias": "dimmer1",
"feature": ":",
}
light_state = {
"on_off": 1,
"relay_state": 1,
"brightness": 13,
}
def state(*args, **kwargs):
nonlocal light_state
nonlocal sys_info
if len(args) == 0:
return light_state["on_off"]
light_state["on_off"] = args[0]
return sys_info["relay_state"]
if args[0] == "ON":
sys_info["relay_state"] = 1
else:
sys_info["relay_state"] = 0
def brightness(*args, **kwargs):
nonlocal light_state
nonlocal sys_info
if len(args) == 0:
return light_state["brightness"]
if light_state["brightness"] == 0:
light_state["on_off"] = 0
return sys_info["brightness"]
if sys_info["brightness"] == 0:
sys_info["relay_state"] = 0
else:
light_state["on_off"] = 1
light_state["brightness"] = args[0]
sys_info["relay_state"] = 1
sys_info["brightness"] = args[0]
get_sysinfo_patch = patch(
"homeassistant.components.tplink.common.SmartDevice.get_sysinfo",
@ -228,7 +227,6 @@ def dimmer_switch_mock_data_fixture() -> None:
with brightness_patch as brightness_mock, state_patch as state_mock, get_sysinfo_patch as get_sysinfo_mock:
yield SmartSwitchMockData(
sys_info=sys_info,
light_state=light_state,
brightness_mock=brightness_mock,
state_mock=state_mock,
get_sysinfo_mock=get_sysinfo_mock,
@ -247,7 +245,7 @@ async def test_smartswitch(
hass: HomeAssistant, dimmer_switch_mock_data: SmartSwitchMockData
) -> None:
"""Test function."""
light_state = dimmer_switch_mock_data.light_state
sys_info = dimmer_switch_mock_data.sys_info
await async_setup_component(hass, HA_DOMAIN, {})
await hass.async_block_till_done()
@ -276,7 +274,7 @@ async def test_smartswitch(
await update_entity(hass, "light.dimmer1")
assert hass.states.get("light.dimmer1").state == "off"
assert light_state["on_off"] == 0
assert sys_info["relay_state"] == 0
await hass.services.async_call(
LIGHT_DOMAIN,
@ -290,7 +288,7 @@ async def test_smartswitch(
state = hass.states.get("light.dimmer1")
assert state.state == "on"
assert state.attributes["brightness"] == 48.45
assert light_state["on_off"] == 1
assert sys_info["relay_state"] == 1
await hass.services.async_call(
LIGHT_DOMAIN,
@ -304,10 +302,10 @@ async def test_smartswitch(
state = hass.states.get("light.dimmer1")
assert state.state == "on"
assert state.attributes["brightness"] == 53.55
assert light_state["brightness"] == 21
assert sys_info["brightness"] == 21
light_state["on_off"] = 0
light_state["brightness"] = 66
sys_info["relay_state"] = 0
sys_info["brightness"] = 66
await hass.services.async_call(
LIGHT_DOMAIN,
@ -330,7 +328,7 @@ async def test_smartswitch(
state = hass.states.get("light.dimmer1")
assert state.state == "on"
assert state.attributes["brightness"] == 168.3
assert light_state["brightness"] == 66
assert sys_info["brightness"] == 66
async def test_light(hass: HomeAssistant, light_mock_data: LightMockData) -> None: