mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 09:17:53 +00:00
Fix tplink HS220 dimmers (#33909)
* HS220 dimmers are handled as lights with a limited feature set
This commit is contained in:
parent
425c97626a
commit
6b2baae0de
@ -345,7 +345,7 @@ class TPLinkSmartBulb(Light):
|
||||
def _get_light_state(self) -> LightState:
|
||||
"""Get the light state."""
|
||||
self._update_emeter()
|
||||
return self._light_state_from_params(self.smartbulb.get_light_state())
|
||||
return self._light_state_from_params(self._get_device_state())
|
||||
|
||||
def _update_emeter(self):
|
||||
if not self.smartbulb.has_emeter:
|
||||
@ -427,7 +427,40 @@ class TPLinkSmartBulb(Light):
|
||||
if not diff:
|
||||
return
|
||||
|
||||
return self.smartbulb.set_light_state(diff)
|
||||
return self._set_device_state(diff)
|
||||
|
||||
def _get_device_state(self):
|
||||
"""State of the bulb or smart dimmer switch."""
|
||||
if isinstance(self.smartbulb, SmartBulb):
|
||||
return self.smartbulb.get_light_state()
|
||||
|
||||
# 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_COLOR_TEMP: 0,
|
||||
LIGHT_STATE_HUE: 0,
|
||||
LIGHT_STATE_SATURATION: 0,
|
||||
}
|
||||
|
||||
def _set_device_state(self, state):
|
||||
"""Set state of the bulb or smart dimmer switch."""
|
||||
if isinstance(self.smartbulb, SmartBulb):
|
||||
return self.smartbulb.set_light_state(state)
|
||||
|
||||
# Its not really a bulb, its a dimmable SmartPlug (aka Wall Switch)
|
||||
if LIGHT_STATE_BRIGHTNESS in state:
|
||||
# Brightness of 0 is accepted by the
|
||||
# device but the underlying library rejects it
|
||||
# so we turn off instead.
|
||||
if state[LIGHT_STATE_BRIGHTNESS]:
|
||||
self.smartbulb.brightness = state[LIGHT_STATE_BRIGHTNESS]
|
||||
else:
|
||||
self.smartbulb.state = 0
|
||||
elif LIGHT_STATE_ON_OFF in state:
|
||||
self.smartbulb.state = state[LIGHT_STATE_ON_OFF]
|
||||
|
||||
return self._get_device_state()
|
||||
|
||||
|
||||
def _light_state_diff(old_light_state: LightState, new_light_state: LightState):
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""Tests for light platform."""
|
||||
from typing import Callable, NamedTuple
|
||||
from unittest.mock import Mock, patch
|
||||
from unittest.mock import Mock, PropertyMock, patch
|
||||
|
||||
from pyHS100 import SmartDeviceException
|
||||
import pytest
|
||||
@ -16,7 +16,11 @@ from homeassistant.components.light import (
|
||||
ATTR_HS_COLOR,
|
||||
DOMAIN as LIGHT_DOMAIN,
|
||||
)
|
||||
from homeassistant.components.tplink.common import CONF_DISCOVERY, CONF_LIGHT
|
||||
from homeassistant.components.tplink.common import (
|
||||
CONF_DIMMER,
|
||||
CONF_DISCOVERY,
|
||||
CONF_LIGHT,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
CONF_HOST,
|
||||
@ -41,6 +45,16 @@ class LightMockData(NamedTuple):
|
||||
get_emeter_monthly_mock: Mock
|
||||
|
||||
|
||||
class SmartSwitchMockData(NamedTuple):
|
||||
"""Mock smart switch data."""
|
||||
|
||||
sys_info: dict
|
||||
light_state: dict
|
||||
state_mock: Mock
|
||||
brightness_mock: Mock
|
||||
get_sysinfo_mock: Mock
|
||||
|
||||
|
||||
@pytest.fixture(name="light_mock_data")
|
||||
def light_mock_data_fixture() -> None:
|
||||
"""Create light mock data."""
|
||||
@ -152,6 +166,75 @@ def light_mock_data_fixture() -> None:
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(name="dimmer_switch_mock_data")
|
||||
def dimmer_switch_mock_data_fixture() -> None:
|
||||
"""Create dimmer switch mock data."""
|
||||
sys_info = {
|
||||
"sw_ver": "1.2.3",
|
||||
"hw_ver": "2.3.4",
|
||||
"mac": "aa:bb:cc:dd:ee:ff",
|
||||
"mic_mac": "00:11:22:33:44",
|
||||
"type": "switch",
|
||||
"hwId": "1234",
|
||||
"fwId": "4567",
|
||||
"oemId": "891011",
|
||||
"dev_name": "dimmer1",
|
||||
"rssi": 11,
|
||||
"latitude": "0",
|
||||
"longitude": "0",
|
||||
"is_color": False,
|
||||
"is_dimmable": True,
|
||||
"is_variable_color_temp": False,
|
||||
"model": "HS220",
|
||||
"alias": "dimmer1",
|
||||
"feature": ":",
|
||||
}
|
||||
|
||||
light_state = {
|
||||
"on_off": 1,
|
||||
"brightness": 13,
|
||||
}
|
||||
|
||||
def state(*args, **kwargs):
|
||||
nonlocal light_state
|
||||
if len(args) == 0:
|
||||
return light_state["on_off"]
|
||||
light_state["on_off"] = args[0]
|
||||
|
||||
def brightness(*args, **kwargs):
|
||||
nonlocal light_state
|
||||
if len(args) == 0:
|
||||
return light_state["brightness"]
|
||||
if light_state["brightness"] == 0:
|
||||
light_state["on_off"] = 0
|
||||
else:
|
||||
light_state["on_off"] = 1
|
||||
light_state["brightness"] = args[0]
|
||||
|
||||
get_sysinfo_patch = patch(
|
||||
"homeassistant.components.tplink.common.SmartDevice.get_sysinfo",
|
||||
return_value=sys_info,
|
||||
)
|
||||
state_patch = patch(
|
||||
"homeassistant.components.tplink.common.SmartPlug.state",
|
||||
new_callable=PropertyMock,
|
||||
side_effect=state,
|
||||
)
|
||||
brightness_patch = patch(
|
||||
"homeassistant.components.tplink.common.SmartPlug.brightness",
|
||||
new_callable=PropertyMock,
|
||||
side_effect=brightness,
|
||||
)
|
||||
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,
|
||||
)
|
||||
|
||||
|
||||
async def update_entity(hass: HomeAssistant, entity_id: str) -> None:
|
||||
"""Run an update action for an entity."""
|
||||
await hass.services.async_call(
|
||||
@ -160,6 +243,96 @@ async def update_entity(hass: HomeAssistant, entity_id: str) -> None:
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def test_smartswitch(
|
||||
hass: HomeAssistant, dimmer_switch_mock_data: SmartSwitchMockData
|
||||
) -> None:
|
||||
"""Test function."""
|
||||
light_state = dimmer_switch_mock_data.light_state
|
||||
|
||||
await async_setup_component(hass, HA_DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await async_setup_component(
|
||||
hass,
|
||||
tplink.DOMAIN,
|
||||
{
|
||||
tplink.DOMAIN: {
|
||||
CONF_DISCOVERY: False,
|
||||
CONF_DIMMER: [{CONF_HOST: "123.123.123.123"}],
|
||||
}
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get("light.dimmer1")
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: "light.dimmer1"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await update_entity(hass, "light.dimmer1")
|
||||
|
||||
assert hass.states.get("light.dimmer1").state == "off"
|
||||
assert light_state["on_off"] == 0
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: "light.dimmer1", ATTR_BRIGHTNESS: 50},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await update_entity(hass, "light.dimmer1")
|
||||
|
||||
state = hass.states.get("light.dimmer1")
|
||||
assert state.state == "on"
|
||||
assert state.attributes["brightness"] == 48.45
|
||||
assert light_state["on_off"] == 1
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: "light.dimmer1", ATTR_BRIGHTNESS: 55},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await update_entity(hass, "light.dimmer1")
|
||||
|
||||
state = hass.states.get("light.dimmer1")
|
||||
assert state.state == "on"
|
||||
assert state.attributes["brightness"] == 53.55
|
||||
assert light_state["brightness"] == 21
|
||||
|
||||
light_state["on_off"] = 0
|
||||
light_state["brightness"] = 66
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: "light.dimmer1"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await update_entity(hass, "light.dimmer1")
|
||||
|
||||
state = hass.states.get("light.dimmer1")
|
||||
assert state.state == "off"
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: "light.dimmer1"}, blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await update_entity(hass, "light.dimmer1")
|
||||
|
||||
state = hass.states.get("light.dimmer1")
|
||||
assert state.state == "on"
|
||||
assert state.attributes["brightness"] == 168.3
|
||||
assert light_state["brightness"] == 66
|
||||
|
||||
|
||||
async def test_light(hass: HomeAssistant, light_mock_data: LightMockData) -> None:
|
||||
"""Test function."""
|
||||
light_state = light_mock_data.light_state
|
||||
|
Loading…
x
Reference in New Issue
Block a user