mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 04:37:06 +00:00
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:
parent
c2d1db61b6
commit
a000af5c03
@ -40,6 +40,7 @@ ATTR_MONTHLY_ENERGY_KWH = "monthly_energy_kwh"
|
|||||||
|
|
||||||
LIGHT_STATE_DFT_ON = "dft_on_state"
|
LIGHT_STATE_DFT_ON = "dft_on_state"
|
||||||
LIGHT_STATE_ON_OFF = "on_off"
|
LIGHT_STATE_ON_OFF = "on_off"
|
||||||
|
LIGHT_STATE_RELAY_STATE = "relay_state"
|
||||||
LIGHT_STATE_BRIGHTNESS = "brightness"
|
LIGHT_STATE_BRIGHTNESS = "brightness"
|
||||||
LIGHT_STATE_COLOR_TEMP = "color_temp"
|
LIGHT_STATE_COLOR_TEMP = "color_temp"
|
||||||
LIGHT_STATE_HUE = "hue"
|
LIGHT_STATE_HUE = "hue"
|
||||||
@ -116,6 +117,7 @@ class LightFeatures(NamedTuple):
|
|||||||
supported_features: int
|
supported_features: int
|
||||||
min_mireds: float
|
min_mireds: float
|
||||||
max_mireds: float
|
max_mireds: float
|
||||||
|
has_emeter: bool
|
||||||
|
|
||||||
|
|
||||||
class TPLinkSmartBulb(Light):
|
class TPLinkSmartBulb(Light):
|
||||||
@ -273,8 +275,9 @@ class TPLinkSmartBulb(Light):
|
|||||||
model = sysinfo[LIGHT_SYSINFO_MODEL]
|
model = sysinfo[LIGHT_SYSINFO_MODEL]
|
||||||
min_mireds = None
|
min_mireds = None
|
||||||
max_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
|
supported_features += SUPPORT_BRIGHTNESS
|
||||||
if sysinfo.get(LIGHT_SYSINFO_IS_VARIABLE_COLOR_TEMP):
|
if sysinfo.get(LIGHT_SYSINFO_IS_VARIABLE_COLOR_TEMP):
|
||||||
supported_features += SUPPORT_COLOR_TEMP
|
supported_features += SUPPORT_COLOR_TEMP
|
||||||
@ -294,6 +297,7 @@ class TPLinkSmartBulb(Light):
|
|||||||
supported_features=supported_features,
|
supported_features=supported_features,
|
||||||
min_mireds=min_mireds,
|
min_mireds=min_mireds,
|
||||||
max_mireds=max_mireds,
|
max_mireds=max_mireds,
|
||||||
|
has_emeter=has_emeter,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _get_light_state_retry(self) -> LightState:
|
def _get_light_state_retry(self) -> LightState:
|
||||||
@ -348,7 +352,7 @@ class TPLinkSmartBulb(Light):
|
|||||||
return self._light_state_from_params(self._get_device_state())
|
return self._light_state_from_params(self._get_device_state())
|
||||||
|
|
||||||
def _update_emeter(self):
|
def _update_emeter(self):
|
||||||
if not self.smartbulb.has_emeter:
|
if not self._light_features.has_emeter:
|
||||||
return
|
return
|
||||||
|
|
||||||
now = dt_util.utcnow()
|
now = dt_util.utcnow()
|
||||||
@ -434,10 +438,11 @@ class TPLinkSmartBulb(Light):
|
|||||||
if isinstance(self.smartbulb, SmartBulb):
|
if isinstance(self.smartbulb, SmartBulb):
|
||||||
return self.smartbulb.get_light_state()
|
return self.smartbulb.get_light_state()
|
||||||
|
|
||||||
|
sysinfo = self.smartbulb.sys_info
|
||||||
# Its not really a bulb, its a dimmable SmartPlug (aka Wall Switch)
|
# Its not really a bulb, its a dimmable SmartPlug (aka Wall Switch)
|
||||||
return {
|
return {
|
||||||
LIGHT_STATE_ON_OFF: self.smartbulb.state,
|
LIGHT_STATE_ON_OFF: sysinfo[LIGHT_STATE_RELAY_STATE],
|
||||||
LIGHT_STATE_BRIGHTNESS: self.smartbulb.brightness,
|
LIGHT_STATE_BRIGHTNESS: sysinfo.get(LIGHT_STATE_BRIGHTNESS, 0),
|
||||||
LIGHT_STATE_COLOR_TEMP: 0,
|
LIGHT_STATE_COLOR_TEMP: 0,
|
||||||
LIGHT_STATE_HUE: 0,
|
LIGHT_STATE_HUE: 0,
|
||||||
LIGHT_STATE_SATURATION: 0,
|
LIGHT_STATE_SATURATION: 0,
|
||||||
@ -456,9 +461,12 @@ class TPLinkSmartBulb(Light):
|
|||||||
if state[LIGHT_STATE_BRIGHTNESS]:
|
if state[LIGHT_STATE_BRIGHTNESS]:
|
||||||
self.smartbulb.brightness = state[LIGHT_STATE_BRIGHTNESS]
|
self.smartbulb.brightness = state[LIGHT_STATE_BRIGHTNESS]
|
||||||
else:
|
else:
|
||||||
self.smartbulb.state = 0
|
self.smartbulb.state = self.smartbulb.SWITCH_STATE_OFF
|
||||||
elif LIGHT_STATE_ON_OFF in state:
|
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()
|
return self._get_device_state()
|
||||||
|
|
||||||
|
@ -49,7 +49,6 @@ class SmartSwitchMockData(NamedTuple):
|
|||||||
"""Mock smart switch data."""
|
"""Mock smart switch data."""
|
||||||
|
|
||||||
sys_info: dict
|
sys_info: dict
|
||||||
light_state: dict
|
|
||||||
state_mock: Mock
|
state_mock: Mock
|
||||||
brightness_mock: Mock
|
brightness_mock: Mock
|
||||||
get_sysinfo_mock: Mock
|
get_sysinfo_mock: Mock
|
||||||
@ -188,28 +187,28 @@ def dimmer_switch_mock_data_fixture() -> None:
|
|||||||
"model": "HS220",
|
"model": "HS220",
|
||||||
"alias": "dimmer1",
|
"alias": "dimmer1",
|
||||||
"feature": ":",
|
"feature": ":",
|
||||||
}
|
"relay_state": 1,
|
||||||
|
|
||||||
light_state = {
|
|
||||||
"on_off": 1,
|
|
||||||
"brightness": 13,
|
"brightness": 13,
|
||||||
}
|
}
|
||||||
|
|
||||||
def state(*args, **kwargs):
|
def state(*args, **kwargs):
|
||||||
nonlocal light_state
|
nonlocal sys_info
|
||||||
if len(args) == 0:
|
if len(args) == 0:
|
||||||
return light_state["on_off"]
|
return sys_info["relay_state"]
|
||||||
light_state["on_off"] = args[0]
|
if args[0] == "ON":
|
||||||
|
sys_info["relay_state"] = 1
|
||||||
|
else:
|
||||||
|
sys_info["relay_state"] = 0
|
||||||
|
|
||||||
def brightness(*args, **kwargs):
|
def brightness(*args, **kwargs):
|
||||||
nonlocal light_state
|
nonlocal sys_info
|
||||||
if len(args) == 0:
|
if len(args) == 0:
|
||||||
return light_state["brightness"]
|
return sys_info["brightness"]
|
||||||
if light_state["brightness"] == 0:
|
if sys_info["brightness"] == 0:
|
||||||
light_state["on_off"] = 0
|
sys_info["relay_state"] = 0
|
||||||
else:
|
else:
|
||||||
light_state["on_off"] = 1
|
sys_info["relay_state"] = 1
|
||||||
light_state["brightness"] = args[0]
|
sys_info["brightness"] = args[0]
|
||||||
|
|
||||||
get_sysinfo_patch = patch(
|
get_sysinfo_patch = patch(
|
||||||
"homeassistant.components.tplink.common.SmartDevice.get_sysinfo",
|
"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:
|
with brightness_patch as brightness_mock, state_patch as state_mock, get_sysinfo_patch as get_sysinfo_mock:
|
||||||
yield SmartSwitchMockData(
|
yield SmartSwitchMockData(
|
||||||
sys_info=sys_info,
|
sys_info=sys_info,
|
||||||
light_state=light_state,
|
|
||||||
brightness_mock=brightness_mock,
|
brightness_mock=brightness_mock,
|
||||||
state_mock=state_mock,
|
state_mock=state_mock,
|
||||||
get_sysinfo_mock=get_sysinfo_mock,
|
get_sysinfo_mock=get_sysinfo_mock,
|
||||||
@ -247,7 +245,7 @@ async def test_smartswitch(
|
|||||||
hass: HomeAssistant, dimmer_switch_mock_data: SmartSwitchMockData
|
hass: HomeAssistant, dimmer_switch_mock_data: SmartSwitchMockData
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test function."""
|
"""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 async_setup_component(hass, HA_DOMAIN, {})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
@ -276,7 +274,7 @@ async def test_smartswitch(
|
|||||||
await update_entity(hass, "light.dimmer1")
|
await update_entity(hass, "light.dimmer1")
|
||||||
|
|
||||||
assert hass.states.get("light.dimmer1").state == "off"
|
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(
|
await hass.services.async_call(
|
||||||
LIGHT_DOMAIN,
|
LIGHT_DOMAIN,
|
||||||
@ -290,7 +288,7 @@ async def test_smartswitch(
|
|||||||
state = hass.states.get("light.dimmer1")
|
state = hass.states.get("light.dimmer1")
|
||||||
assert state.state == "on"
|
assert state.state == "on"
|
||||||
assert state.attributes["brightness"] == 48.45
|
assert state.attributes["brightness"] == 48.45
|
||||||
assert light_state["on_off"] == 1
|
assert sys_info["relay_state"] == 1
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
LIGHT_DOMAIN,
|
LIGHT_DOMAIN,
|
||||||
@ -304,10 +302,10 @@ async def test_smartswitch(
|
|||||||
state = hass.states.get("light.dimmer1")
|
state = hass.states.get("light.dimmer1")
|
||||||
assert state.state == "on"
|
assert state.state == "on"
|
||||||
assert state.attributes["brightness"] == 53.55
|
assert state.attributes["brightness"] == 53.55
|
||||||
assert light_state["brightness"] == 21
|
assert sys_info["brightness"] == 21
|
||||||
|
|
||||||
light_state["on_off"] = 0
|
sys_info["relay_state"] = 0
|
||||||
light_state["brightness"] = 66
|
sys_info["brightness"] = 66
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
LIGHT_DOMAIN,
|
LIGHT_DOMAIN,
|
||||||
@ -330,7 +328,7 @@ async def test_smartswitch(
|
|||||||
state = hass.states.get("light.dimmer1")
|
state = hass.states.get("light.dimmer1")
|
||||||
assert state.state == "on"
|
assert state.state == "on"
|
||||||
assert state.attributes["brightness"] == 168.3
|
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:
|
async def test_light(hass: HomeAssistant, light_mock_data: LightMockData) -> None:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user