mirror of
https://github.com/home-assistant/core.git
synced 2025-04-29 03:37:51 +00:00
Avoid divide by zero errors in tplink light integration (#48235)
This commit is contained in:
parent
9e1a17c62e
commit
9fd6980144
@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
import asyncio
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
import re
|
||||
import time
|
||||
from typing import Any, NamedTuple, cast
|
||||
|
||||
@ -60,6 +61,21 @@ LIGHT_SYSINFO_IS_COLOR = "is_color"
|
||||
MAX_ATTEMPTS = 300
|
||||
SLEEP_TIME = 2
|
||||
|
||||
TPLINK_KELVIN = {
|
||||
"LB130": (2500, 9000),
|
||||
"LB120": (2700, 6500),
|
||||
"LB230": (2500, 9000),
|
||||
"KB130": (2500, 9000),
|
||||
"KL130": (2500, 9000),
|
||||
"KL125": (2500, 6500),
|
||||
r"KL120\(EU\)": (2700, 6500),
|
||||
r"KL120\(US\)": (2700, 5000),
|
||||
r"KL430\(US\)": (2500, 9000),
|
||||
}
|
||||
|
||||
FALLBACK_MIN_COLOR = 2700
|
||||
FALLBACK_MAX_COLOR = 5000
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistantType, config_entry, async_add_entities):
|
||||
"""Set up lights."""
|
||||
@ -269,6 +285,19 @@ class TPLinkSmartBulb(LightEntity):
|
||||
"""Flag supported features."""
|
||||
return self._light_features.supported_features
|
||||
|
||||
def _get_valid_temperature_range(self):
|
||||
"""Return the device-specific white temperature range (in Kelvin).
|
||||
|
||||
:return: White temperature range in Kelvin (minimum, maximum)
|
||||
"""
|
||||
model = self.smartbulb.sys_info[LIGHT_SYSINFO_MODEL]
|
||||
for obj, temp_range in TPLINK_KELVIN.items():
|
||||
if re.match(obj, model):
|
||||
return temp_range
|
||||
# pyHS100 is abandoned, but some bulb definitions aren't present
|
||||
# use "safe" values for something that advertises color temperature
|
||||
return FALLBACK_MIN_COLOR, FALLBACK_MAX_COLOR
|
||||
|
||||
def _get_light_features(self):
|
||||
"""Determine all supported features in one go."""
|
||||
sysinfo = self.smartbulb.sys_info
|
||||
@ -285,9 +314,7 @@ class TPLinkSmartBulb(LightEntity):
|
||||
supported_features += SUPPORT_BRIGHTNESS
|
||||
if sysinfo.get(LIGHT_SYSINFO_IS_VARIABLE_COLOR_TEMP):
|
||||
supported_features += SUPPORT_COLOR_TEMP
|
||||
# Have to make another api request here in
|
||||
# order to not re-implement pyHS100 here
|
||||
max_range, min_range = self.smartbulb.valid_temperature_range
|
||||
max_range, min_range = self._get_valid_temperature_range()
|
||||
min_mireds = kelvin_to_mired(min_range)
|
||||
max_mireds = kelvin_to_mired(max_range)
|
||||
if sysinfo.get(LIGHT_SYSINFO_IS_COLOR):
|
||||
|
@ -60,6 +60,116 @@ class SmartSwitchMockData(NamedTuple):
|
||||
get_sysinfo_mock: Mock
|
||||
|
||||
|
||||
@pytest.fixture(name="unknown_light_mock_data")
|
||||
def unknown_light_mock_data_fixture() -> None:
|
||||
"""Create light 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": "light",
|
||||
"hwId": "1234",
|
||||
"fwId": "4567",
|
||||
"oemId": "891011",
|
||||
"dev_name": "light1",
|
||||
"rssi": 11,
|
||||
"latitude": "0",
|
||||
"longitude": "0",
|
||||
"is_color": True,
|
||||
"is_dimmable": True,
|
||||
"is_variable_color_temp": True,
|
||||
"model": "Foo",
|
||||
"alias": "light1",
|
||||
}
|
||||
light_state = {
|
||||
"on_off": True,
|
||||
"dft_on_state": {
|
||||
"brightness": 12,
|
||||
"color_temp": 3200,
|
||||
"hue": 110,
|
||||
"saturation": 90,
|
||||
},
|
||||
"brightness": 13,
|
||||
"color_temp": 3300,
|
||||
"hue": 110,
|
||||
"saturation": 90,
|
||||
}
|
||||
|
||||
def set_light_state(state) -> None:
|
||||
nonlocal light_state
|
||||
drt_on_state = light_state["dft_on_state"]
|
||||
drt_on_state.update(state.get("dft_on_state", {}))
|
||||
|
||||
light_state.update(state)
|
||||
light_state["dft_on_state"] = drt_on_state
|
||||
return light_state
|
||||
|
||||
set_light_state_patch = patch(
|
||||
"homeassistant.components.tplink.common.SmartBulb.set_light_state",
|
||||
side_effect=set_light_state,
|
||||
)
|
||||
get_light_state_patch = patch(
|
||||
"homeassistant.components.tplink.common.SmartBulb.get_light_state",
|
||||
return_value=light_state,
|
||||
)
|
||||
current_consumption_patch = patch(
|
||||
"homeassistant.components.tplink.common.SmartDevice.current_consumption",
|
||||
return_value=3.23,
|
||||
)
|
||||
get_sysinfo_patch = patch(
|
||||
"homeassistant.components.tplink.common.SmartDevice.get_sysinfo",
|
||||
return_value=sys_info,
|
||||
)
|
||||
get_emeter_daily_patch = patch(
|
||||
"homeassistant.components.tplink.common.SmartDevice.get_emeter_daily",
|
||||
return_value={
|
||||
1: 1.01,
|
||||
2: 1.02,
|
||||
3: 1.03,
|
||||
4: 1.04,
|
||||
5: 1.05,
|
||||
6: 1.06,
|
||||
7: 1.07,
|
||||
8: 1.08,
|
||||
9: 1.09,
|
||||
10: 1.10,
|
||||
11: 1.11,
|
||||
12: 1.12,
|
||||
},
|
||||
)
|
||||
get_emeter_monthly_patch = patch(
|
||||
"homeassistant.components.tplink.common.SmartDevice.get_emeter_monthly",
|
||||
return_value={
|
||||
1: 2.01,
|
||||
2: 2.02,
|
||||
3: 2.03,
|
||||
4: 2.04,
|
||||
5: 2.05,
|
||||
6: 2.06,
|
||||
7: 2.07,
|
||||
8: 2.08,
|
||||
9: 2.09,
|
||||
10: 2.10,
|
||||
11: 2.11,
|
||||
12: 2.12,
|
||||
},
|
||||
)
|
||||
|
||||
with set_light_state_patch as set_light_state_mock, get_light_state_patch as get_light_state_mock, current_consumption_patch as current_consumption_mock, get_sysinfo_patch as get_sysinfo_mock, get_emeter_daily_patch as get_emeter_daily_mock, get_emeter_monthly_patch as get_emeter_monthly_mock:
|
||||
yield LightMockData(
|
||||
sys_info=sys_info,
|
||||
light_state=light_state,
|
||||
set_light_state=set_light_state,
|
||||
set_light_state_mock=set_light_state_mock,
|
||||
get_light_state_mock=get_light_state_mock,
|
||||
current_consumption_mock=current_consumption_mock,
|
||||
get_sysinfo_mock=get_sysinfo_mock,
|
||||
get_emeter_daily_mock=get_emeter_daily_mock,
|
||||
get_emeter_monthly_mock=get_emeter_monthly_mock,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(name="light_mock_data")
|
||||
def light_mock_data_fixture() -> None:
|
||||
"""Create light mock data."""
|
||||
@ -343,6 +453,31 @@ async def test_smartswitch(
|
||||
assert sys_info["brightness"] == 66
|
||||
|
||||
|
||||
async def test_unknown_light(
|
||||
hass: HomeAssistant, unknown_light_mock_data: LightMockData
|
||||
) -> None:
|
||||
"""Test function."""
|
||||
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_LIGHT: [{CONF_HOST: "123.123.123.123"}],
|
||||
}
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("light.light1")
|
||||
assert state.state == "on"
|
||||
assert state.attributes["min_mireds"] == 200
|
||||
assert state.attributes["max_mireds"] == 370
|
||||
|
||||
|
||||
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