Refactor HomeKit to allow supported features/device class to change (#101719)
This commit is contained in:
parent
f166e1cc1a
commit
7b4b8e7516
18 changed files with 662 additions and 452 deletions
|
@ -36,7 +36,13 @@ from homeassistant.components.homekit.const import (
|
|||
)
|
||||
from homeassistant.components.homekit.type_triggers import DeviceTriggerAccessory
|
||||
from homeassistant.components.homekit.util import get_persist_fullpath_for_entry_id
|
||||
from homeassistant.components.light import (
|
||||
ATTR_COLOR_MODE,
|
||||
ATTR_SUPPORTED_COLOR_MODES,
|
||||
ColorMode,
|
||||
)
|
||||
from homeassistant.components.sensor import SensorDeviceClass
|
||||
from homeassistant.components.switch import SwitchDeviceClass
|
||||
from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_ZEROCONF
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
|
@ -532,7 +538,7 @@ async def test_homekit_remove_accessory(
|
|||
acc_mock.stop = AsyncMock()
|
||||
homekit.bridge.accessories = {6: acc_mock}
|
||||
|
||||
acc = await homekit.async_remove_bridge_accessory(6)
|
||||
acc = homekit.async_remove_bridge_accessory(6)
|
||||
assert acc is acc_mock
|
||||
assert len(homekit.bridge.accessories) == 0
|
||||
|
||||
|
@ -876,6 +882,7 @@ async def test_homekit_stop(hass: HomeAssistant) -> None:
|
|||
|
||||
# Test if driver is started
|
||||
homekit.status = STATUS_RUNNING
|
||||
homekit._cancel_reload_dispatcher = lambda: None
|
||||
await homekit.async_stop()
|
||||
await hass.async_block_till_done()
|
||||
assert homekit.driver.async_stop.called is True
|
||||
|
@ -919,6 +926,120 @@ async def test_homekit_reset_accessories(
|
|||
await homekit.async_stop()
|
||||
|
||||
|
||||
async def test_homekit_reload_accessory_can_change_class(
|
||||
hass: HomeAssistant, mock_async_zeroconf: None, mock_hap
|
||||
) -> None:
|
||||
"""Test reloading a HomeKit Accessory in brdige mode.
|
||||
|
||||
This test ensure when device class changes the HomeKit class changes.
|
||||
"""
|
||||
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN, data={CONF_NAME: "mock_name", CONF_PORT: 12345}
|
||||
)
|
||||
entity_id = "switch.outlet"
|
||||
hass.states.async_set(entity_id, "on", {ATTR_DEVICE_CLASS: None})
|
||||
homekit = _mock_homekit(hass, entry, HOMEKIT_MODE_BRIDGE)
|
||||
|
||||
with patch(f"{PATH_HOMEKIT}.HomeKit", return_value=homekit):
|
||||
await async_init_entry(hass, entry)
|
||||
bridge: HomeBridge = homekit.driver.accessory
|
||||
await bridge.run()
|
||||
switch_accessory = next(iter(bridge.accessories.values()))
|
||||
assert type(switch_accessory).__name__ == "Switch"
|
||||
await hass.async_block_till_done()
|
||||
assert homekit.status == STATUS_RUNNING
|
||||
homekit.driver.aio_stop_event = MagicMock()
|
||||
hass.states.async_set(
|
||||
entity_id, "off", {ATTR_DEVICE_CLASS: SwitchDeviceClass.OUTLET}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
outlet_accessory = next(iter(bridge.accessories.values()))
|
||||
assert type(outlet_accessory).__name__ == "Outlet"
|
||||
|
||||
await homekit.async_stop()
|
||||
|
||||
|
||||
async def test_homekit_reload_accessory_in_accessory_mode(
|
||||
hass: HomeAssistant, mock_async_zeroconf: None, mock_hap
|
||||
) -> None:
|
||||
"""Test reloading a HomeKit Accessory in accessory mode.
|
||||
|
||||
This test ensure a device class changes can change the class of
|
||||
the accessory.
|
||||
"""
|
||||
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN, data={CONF_NAME: "mock_name", CONF_PORT: 12345}
|
||||
)
|
||||
entity_id = "switch.outlet"
|
||||
hass.states.async_set(entity_id, "on", {ATTR_DEVICE_CLASS: None})
|
||||
homekit = _mock_homekit(hass, entry, HOMEKIT_MODE_ACCESSORY)
|
||||
|
||||
with patch(f"{PATH_HOMEKIT}.HomeKit", return_value=homekit):
|
||||
await async_init_entry(hass, entry)
|
||||
primary_accessory = homekit.driver.accessory
|
||||
await primary_accessory.run()
|
||||
assert type(primary_accessory).__name__ == "Switch"
|
||||
await hass.async_block_till_done()
|
||||
assert homekit.status == STATUS_RUNNING
|
||||
homekit.driver.aio_stop_event = MagicMock()
|
||||
hass.states.async_set(
|
||||
entity_id, "off", {ATTR_DEVICE_CLASS: SwitchDeviceClass.OUTLET}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
primary_accessory = homekit.driver.accessory
|
||||
assert type(primary_accessory).__name__ == "Outlet"
|
||||
|
||||
await homekit.async_stop()
|
||||
|
||||
|
||||
async def test_homekit_reload_accessory_same_class(
|
||||
hass: HomeAssistant, mock_async_zeroconf: None, mock_hap
|
||||
) -> None:
|
||||
"""Test reloading a HomeKit Accessory in bridge mode.
|
||||
|
||||
The class of the accessory remains the same.
|
||||
"""
|
||||
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN, data={CONF_NAME: "mock_name", CONF_PORT: 12345}
|
||||
)
|
||||
entity_id = "light.color"
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
"on",
|
||||
{ATTR_SUPPORTED_COLOR_MODES: [ColorMode.HS], ATTR_COLOR_MODE: ColorMode.HS},
|
||||
)
|
||||
homekit = _mock_homekit(hass, entry, HOMEKIT_MODE_BRIDGE)
|
||||
|
||||
with patch(f"{PATH_HOMEKIT}.HomeKit", return_value=homekit):
|
||||
await async_init_entry(hass, entry)
|
||||
bridge: HomeBridge = homekit.driver.accessory
|
||||
await bridge.run()
|
||||
light_accessory_color = next(iter(bridge.accessories.values()))
|
||||
assert not hasattr(light_accessory_color, "char_color_temp")
|
||||
await hass.async_block_till_done()
|
||||
assert homekit.status == STATUS_RUNNING
|
||||
homekit.driver.aio_stop_event = MagicMock()
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
"on",
|
||||
{
|
||||
ATTR_SUPPORTED_COLOR_MODES: [ColorMode.HS, ColorMode.COLOR_TEMP],
|
||||
ATTR_COLOR_MODE: ColorMode.COLOR_TEMP,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
light_accessory_color_and_temp = next(iter(bridge.accessories.values()))
|
||||
assert hasattr(light_accessory_color_and_temp, "char_color_temp")
|
||||
|
||||
await homekit.async_stop()
|
||||
|
||||
|
||||
async def test_homekit_unpair(
|
||||
hass: HomeAssistant, device_registry: dr.DeviceRegistry, mock_async_zeroconf: None
|
||||
) -> None:
|
||||
|
@ -1076,8 +1197,8 @@ async def test_homekit_reset_accessories_not_supported(
|
|||
with patch(f"{PATH_HOMEKIT}.HomeKit", return_value=homekit), patch(
|
||||
"pyhap.accessory.Bridge.add_accessory"
|
||||
) as mock_add_accessory, patch(
|
||||
"pyhap.accessory_driver.AccessoryDriver.config_changed"
|
||||
) as hk_driver_config_changed, patch(
|
||||
"pyhap.accessory_driver.AccessoryDriver.async_update_advertisement"
|
||||
) as hk_driver_async_update_advertisement, patch(
|
||||
"pyhap.accessory_driver.AccessoryDriver.async_start"
|
||||
), patch.object(
|
||||
homekit_base, "_HOMEKIT_CONFIG_UPDATE_TIME", 0
|
||||
|
@ -1101,7 +1222,7 @@ async def test_homekit_reset_accessories_not_supported(
|
|||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hk_driver_config_changed.call_count == 2
|
||||
assert hk_driver_async_update_advertisement.call_count == 1
|
||||
assert not mock_add_accessory.called
|
||||
assert len(homekit.bridge.accessories) == 0
|
||||
homekit.status = STATUS_STOPPED
|
||||
|
@ -1165,22 +1286,25 @@ async def test_homekit_reset_accessories_not_bridged(
|
|||
with patch(f"{PATH_HOMEKIT}.HomeKit", return_value=homekit), patch(
|
||||
"pyhap.accessory.Bridge.add_accessory"
|
||||
) as mock_add_accessory, patch(
|
||||
"pyhap.accessory_driver.AccessoryDriver.config_changed"
|
||||
) as hk_driver_config_changed, patch(
|
||||
"pyhap.accessory_driver.AccessoryDriver.async_update_advertisement"
|
||||
) as hk_driver_async_update_advertisement, patch(
|
||||
"pyhap.accessory_driver.AccessoryDriver.async_start"
|
||||
), patch.object(
|
||||
homekit_base, "_HOMEKIT_CONFIG_UPDATE_TIME", 0
|
||||
):
|
||||
await async_init_entry(hass, entry)
|
||||
|
||||
assert hk_driver_async_update_advertisement.call_count == 0
|
||||
acc_mock = MagicMock()
|
||||
acc_mock.entity_id = entity_id
|
||||
acc_mock.stop = AsyncMock()
|
||||
acc_mock.to_HAP = lambda: {}
|
||||
|
||||
aid = homekit.aid_storage.get_or_allocate_aid_for_entity_id(entity_id)
|
||||
homekit.bridge.accessories = {aid: acc_mock}
|
||||
homekit.status = STATUS_RUNNING
|
||||
homekit.driver.aio_stop_event = MagicMock()
|
||||
assert hk_driver_async_update_advertisement.call_count == 0
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
|
@ -1190,7 +1314,7 @@ async def test_homekit_reset_accessories_not_bridged(
|
|||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hk_driver_config_changed.call_count == 0
|
||||
assert hk_driver_async_update_advertisement.call_count == 0
|
||||
assert not mock_add_accessory.called
|
||||
homekit.status = STATUS_STOPPED
|
||||
|
||||
|
@ -1208,8 +1332,8 @@ async def test_homekit_reset_single_accessory(
|
|||
homekit = _mock_homekit(hass, entry, HOMEKIT_MODE_ACCESSORY)
|
||||
|
||||
with patch(f"{PATH_HOMEKIT}.HomeKit", return_value=homekit), patch(
|
||||
"pyhap.accessory_driver.AccessoryDriver.config_changed"
|
||||
) as hk_driver_config_changed, patch(
|
||||
"pyhap.accessory_driver.AccessoryDriver.async_update_advertisement"
|
||||
) as hk_driver_async_update_advertisement, patch(
|
||||
"pyhap.accessory_driver.AccessoryDriver.async_start"
|
||||
), patch(
|
||||
f"{PATH_HOMEKIT}.accessories.HomeAccessory.run"
|
||||
|
@ -1226,7 +1350,7 @@ async def test_homekit_reset_single_accessory(
|
|||
)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_run.called
|
||||
assert hk_driver_config_changed.call_count == 1
|
||||
assert hk_driver_async_update_advertisement.call_count == 1
|
||||
homekit.status = STATUS_READY
|
||||
await homekit.async_stop()
|
||||
|
||||
|
|
|
@ -129,7 +129,14 @@ async def test_fan_direction(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
await hass.async_block_till_done()
|
||||
assert acc.char_direction.value == 0
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_DIRECTION: DIRECTION_REVERSE})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: FanEntityFeature.DIRECTION,
|
||||
ATTR_DIRECTION: DIRECTION_REVERSE,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_direction.value == 1
|
||||
|
||||
|
@ -197,7 +204,11 @@ async def test_fan_oscillate(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
await hass.async_block_till_done()
|
||||
assert acc.char_swing.value == 0
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_OSCILLATING: True})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{ATTR_SUPPORTED_FEATURES: FanEntityFeature.OSCILLATE, ATTR_OSCILLATING: True},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_swing.value == 1
|
||||
|
||||
|
@ -272,7 +283,15 @@ async def test_fan_speed(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
await acc.run()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_PERCENTAGE: 100})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_PERCENTAGE_STEP: 25,
|
||||
ATTR_SUPPORTED_FEATURES: FanEntityFeature.SET_SPEED,
|
||||
ATTR_PERCENTAGE: 100,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_speed.value == 100
|
||||
|
||||
|
@ -306,7 +325,15 @@ async def test_fan_speed(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
assert events[-1].data[ATTR_VALUE] == 42
|
||||
|
||||
# Verify speed is preserved from off to on
|
||||
hass.states.async_set(entity_id, STATE_OFF, {ATTR_PERCENTAGE: 42})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_OFF,
|
||||
{
|
||||
ATTR_PERCENTAGE_STEP: 25,
|
||||
ATTR_SUPPORTED_FEATURES: FanEntityFeature.SET_SPEED,
|
||||
ATTR_PERCENTAGE: 42,
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_speed.value == 50
|
||||
assert acc.char_active.value == 0
|
||||
|
|
|
@ -48,7 +48,9 @@ async def test_humidifier(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
"""Test if humidifier accessory and HA are updated accordingly."""
|
||||
entity_id = "humidifier.test"
|
||||
|
||||
hass.states.async_set(entity_id, STATE_OFF)
|
||||
hass.states.async_set(
|
||||
entity_id, STATE_OFF, {ATTR_DEVICE_CLASS: HumidifierDeviceClass.HUMIDIFIER}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
acc = HumidifierDehumidifier(
|
||||
hass, hk_driver, "HumidifierDehumidifier", entity_id, 1, None
|
||||
|
@ -77,7 +79,7 @@ async def test_humidifier(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{ATTR_HUMIDITY: 47},
|
||||
{ATTR_HUMIDITY: 47, ATTR_DEVICE_CLASS: HumidifierDeviceClass.HUMIDIFIER},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_target_humidity.value == 47.0
|
||||
|
@ -158,7 +160,7 @@ async def test_dehumidifier(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{ATTR_HUMIDITY: 30},
|
||||
{ATTR_HUMIDITY: 30, ATTR_DEVICE_CLASS: HumidifierDeviceClass.DEHUMIDIFIER},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_target_humidity.value == 30.0
|
||||
|
@ -169,7 +171,7 @@ async def test_dehumidifier(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_OFF,
|
||||
{ATTR_HUMIDITY: 42},
|
||||
{ATTR_HUMIDITY: 42, ATTR_DEVICE_CLASS: HumidifierDeviceClass.DEHUMIDIFIER},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_target_humidity.value == 42.0
|
||||
|
|
|
@ -122,7 +122,8 @@ async def test_light_basic(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"supported_color_modes", [["brightness"], ["hs"], ["color_temp"]]
|
||||
"supported_color_modes",
|
||||
[[ColorMode.BRIGHTNESS], [ColorMode.HS], [ColorMode.COLOR_TEMP]],
|
||||
)
|
||||
async def test_light_brightness(
|
||||
hass: HomeAssistant, hk_driver, events, supported_color_modes
|
||||
|
@ -149,7 +150,11 @@ async def test_light_brightness(
|
|||
await hass.async_block_till_done()
|
||||
assert acc.char_brightness.value == 100
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 102})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{ATTR_SUPPORTED_COLOR_MODES: supported_color_modes, ATTR_BRIGHTNESS: 102},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_brightness.value == 40
|
||||
|
||||
|
@ -222,24 +227,48 @@ async def test_light_brightness(
|
|||
|
||||
# 0 is a special case for homekit, see "Handle Brightness"
|
||||
# in update_state
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 0})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{ATTR_SUPPORTED_COLOR_MODES: supported_color_modes, ATTR_BRIGHTNESS: 0},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_brightness.value == 1
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 255})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{ATTR_SUPPORTED_COLOR_MODES: supported_color_modes, ATTR_BRIGHTNESS: 255},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_brightness.value == 100
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 0})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{ATTR_SUPPORTED_COLOR_MODES: supported_color_modes, ATTR_BRIGHTNESS: 0},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_brightness.value == 1
|
||||
|
||||
# Ensure floats are handled
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 55.66})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{ATTR_SUPPORTED_COLOR_MODES: supported_color_modes, ATTR_BRIGHTNESS: 55.66},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_brightness.value == 22
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 108.4})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{ATTR_SUPPORTED_COLOR_MODES: supported_color_modes, ATTR_BRIGHTNESS: 108.4},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_brightness.value == 43
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 0.0})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{ATTR_SUPPORTED_COLOR_MODES: supported_color_modes, ATTR_BRIGHTNESS: 0.0},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_brightness.value == 1
|
||||
|
||||
|
@ -490,7 +519,9 @@ async def test_light_color_temperature_and_rgb_color(
|
|||
assert acc.char_saturation.value == 100
|
||||
|
||||
|
||||
@pytest.mark.parametrize("supported_color_modes", [["hs"], ["rgb"], ["xy"]])
|
||||
@pytest.mark.parametrize(
|
||||
"supported_color_modes", [[ColorMode.HS], [ColorMode.RGB], [ColorMode.XY]]
|
||||
)
|
||||
async def test_light_rgb_color(
|
||||
hass: HomeAssistant, hk_driver, events, supported_color_modes
|
||||
) -> None:
|
||||
|
@ -1221,7 +1252,7 @@ async def test_light_set_brightness_and_color(
|
|||
entity_id,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_COLOR_MODES: ["hs"],
|
||||
ATTR_SUPPORTED_COLOR_MODES: [ColorMode.HS],
|
||||
ATTR_BRIGHTNESS: 255,
|
||||
},
|
||||
)
|
||||
|
@ -1241,11 +1272,19 @@ async def test_light_set_brightness_and_color(
|
|||
await hass.async_block_till_done()
|
||||
assert acc.char_brightness.value == 100
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 102})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{ATTR_SUPPORTED_COLOR_MODES: [ColorMode.HS], ATTR_BRIGHTNESS: 102},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_brightness.value == 40
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_HS_COLOR: (4.5, 9.2)})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{ATTR_SUPPORTED_COLOR_MODES: [ColorMode.HS], ATTR_HS_COLOR: (4.5, 9.2)},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_hue.value == 4
|
||||
assert acc.char_saturation.value == 9
|
||||
|
@ -1297,7 +1336,7 @@ async def test_light_min_max_mireds(hass: HomeAssistant, hk_driver, events) -> N
|
|||
entity_id,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_COLOR_MODES: ["color_temp"],
|
||||
ATTR_SUPPORTED_COLOR_MODES: [ColorMode.COLOR_TEMP],
|
||||
ATTR_BRIGHTNESS: 255,
|
||||
ATTR_MAX_MIREDS: 500.5,
|
||||
ATTR_MIN_MIREDS: 100.5,
|
||||
|
@ -1319,7 +1358,7 @@ async def test_light_set_brightness_and_color_temp(
|
|||
entity_id,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_COLOR_MODES: ["color_temp"],
|
||||
ATTR_SUPPORTED_COLOR_MODES: [ColorMode.COLOR_TEMP],
|
||||
ATTR_BRIGHTNESS: 255,
|
||||
},
|
||||
)
|
||||
|
@ -1338,11 +1377,22 @@ async def test_light_set_brightness_and_color_temp(
|
|||
await hass.async_block_till_done()
|
||||
assert acc.char_brightness.value == 100
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 102})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{ATTR_SUPPORTED_COLOR_MODES: [ColorMode.COLOR_TEMP], ATTR_BRIGHTNESS: 102},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_brightness.value == 40
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_COLOR_TEMP_KELVIN: (4461)})
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_COLOR_MODES: [ColorMode.COLOR_TEMP],
|
||||
ATTR_COLOR_TEMP_KELVIN: (4461),
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_color_temp.value == 224
|
||||
|
||||
|
|
|
@ -56,11 +56,12 @@ async def test_media_player_set_state(hass: HomeAssistant, hk_driver, events) ->
|
|||
}
|
||||
}
|
||||
entity_id = "media_player.test"
|
||||
base_attrs = {ATTR_SUPPORTED_FEATURES: 20873, ATTR_MEDIA_VOLUME_MUTED: False}
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
None,
|
||||
{ATTR_SUPPORTED_FEATURES: 20873, ATTR_MEDIA_VOLUME_MUTED: False},
|
||||
base_attrs,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
acc = MediaPlayer(hass, hk_driver, "MediaPlayer", entity_id, 2, config)
|
||||
|
@ -75,33 +76,35 @@ async def test_media_player_set_state(hass: HomeAssistant, hk_driver, events) ->
|
|||
assert acc.chars[FEATURE_PLAY_STOP].value is False
|
||||
assert acc.chars[FEATURE_TOGGLE_MUTE].value is False
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_MEDIA_VOLUME_MUTED: True})
|
||||
hass.states.async_set(
|
||||
entity_id, STATE_ON, {**base_attrs, ATTR_MEDIA_VOLUME_MUTED: True}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.chars[FEATURE_ON_OFF].value is True
|
||||
assert acc.chars[FEATURE_TOGGLE_MUTE].value is True
|
||||
|
||||
hass.states.async_set(entity_id, STATE_OFF)
|
||||
hass.states.async_set(entity_id, STATE_OFF, base_attrs)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.chars[FEATURE_ON_OFF].value is False
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON)
|
||||
hass.states.async_set(entity_id, STATE_ON, base_attrs)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.chars[FEATURE_ON_OFF].value is True
|
||||
|
||||
hass.states.async_set(entity_id, STATE_STANDBY)
|
||||
hass.states.async_set(entity_id, STATE_STANDBY, base_attrs)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.chars[FEATURE_ON_OFF].value is False
|
||||
|
||||
hass.states.async_set(entity_id, STATE_PLAYING)
|
||||
hass.states.async_set(entity_id, STATE_PLAYING, base_attrs)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.chars[FEATURE_PLAY_PAUSE].value is True
|
||||
assert acc.chars[FEATURE_PLAY_STOP].value is True
|
||||
|
||||
hass.states.async_set(entity_id, STATE_PAUSED)
|
||||
hass.states.async_set(entity_id, STATE_PAUSED, base_attrs)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.chars[FEATURE_PLAY_PAUSE].value is False
|
||||
|
||||
hass.states.async_set(entity_id, STATE_IDLE)
|
||||
hass.states.async_set(entity_id, STATE_IDLE, base_attrs)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.chars[FEATURE_PLAY_STOP].value is False
|
||||
|
||||
|
@ -180,15 +183,16 @@ async def test_media_player_television(
|
|||
|
||||
# Supports 'select_source', 'volume_step', 'turn_on', 'turn_off',
|
||||
# 'volume_mute', 'volume_set', 'pause'
|
||||
base_attrs = {
|
||||
ATTR_DEVICE_CLASS: MediaPlayerDeviceClass.TV,
|
||||
ATTR_SUPPORTED_FEATURES: 3469,
|
||||
ATTR_MEDIA_VOLUME_MUTED: False,
|
||||
ATTR_INPUT_SOURCE_LIST: ["HDMI 1", "HDMI 2", "HDMI 3", "HDMI 4"],
|
||||
}
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
None,
|
||||
{
|
||||
ATTR_DEVICE_CLASS: MediaPlayerDeviceClass.TV,
|
||||
ATTR_SUPPORTED_FEATURES: 3469,
|
||||
ATTR_MEDIA_VOLUME_MUTED: False,
|
||||
ATTR_INPUT_SOURCE_LIST: ["HDMI 1", "HDMI 2", "HDMI 3", "HDMI 4"],
|
||||
},
|
||||
base_attrs,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
acc = TelevisionMediaPlayer(hass, hk_driver, "MediaPlayer", entity_id, 2, None)
|
||||
|
@ -203,32 +207,40 @@ async def test_media_player_television(
|
|||
assert acc.char_input_source.value == 0
|
||||
assert acc.char_mute.value is False
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_MEDIA_VOLUME_MUTED: True})
|
||||
hass.states.async_set(
|
||||
entity_id, STATE_ON, {**base_attrs, ATTR_MEDIA_VOLUME_MUTED: True}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_active.value == 1
|
||||
assert acc.char_mute.value is True
|
||||
|
||||
hass.states.async_set(entity_id, STATE_OFF)
|
||||
hass.states.async_set(entity_id, STATE_OFF, base_attrs)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_active.value == 0
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON)
|
||||
hass.states.async_set(entity_id, STATE_ON, base_attrs)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_active.value == 1
|
||||
|
||||
hass.states.async_set(entity_id, STATE_STANDBY)
|
||||
hass.states.async_set(entity_id, STATE_STANDBY, base_attrs)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_active.value == 0
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: "HDMI 2"})
|
||||
hass.states.async_set(
|
||||
entity_id, STATE_ON, {**base_attrs, ATTR_INPUT_SOURCE: "HDMI 2"}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_input_source.value == 1
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: "HDMI 3"})
|
||||
hass.states.async_set(
|
||||
entity_id, STATE_ON, {**base_attrs, ATTR_INPUT_SOURCE: "HDMI 3"}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_input_source.value == 2
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: "HDMI 5"})
|
||||
hass.states.async_set(
|
||||
entity_id, STATE_ON, {**base_attrs, ATTR_INPUT_SOURCE: "HDMI 5"}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_input_source.value == 0
|
||||
assert caplog.records[-2].levelname == "DEBUG"
|
||||
|
@ -358,12 +370,15 @@ async def test_media_player_television_basic(
|
|||
) -> None:
|
||||
"""Test if basic television accessory and HA are updated accordingly."""
|
||||
entity_id = "media_player.television"
|
||||
|
||||
base_attrs = {
|
||||
ATTR_DEVICE_CLASS: MediaPlayerDeviceClass.TV,
|
||||
ATTR_SUPPORTED_FEATURES: 384,
|
||||
}
|
||||
# Supports turn_on', 'turn_off'
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
None,
|
||||
{ATTR_DEVICE_CLASS: MediaPlayerDeviceClass.TV, ATTR_SUPPORTED_FEATURES: 384},
|
||||
base_attrs,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
acc = TelevisionMediaPlayer(hass, hk_driver, "MediaPlayer", entity_id, 2, None)
|
||||
|
@ -374,15 +389,19 @@ async def test_media_player_television_basic(
|
|||
assert acc.chars_speaker == []
|
||||
assert acc.support_select_source is False
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_MEDIA_VOLUME_MUTED: True})
|
||||
hass.states.async_set(
|
||||
entity_id, STATE_ON, {**base_attrs, ATTR_MEDIA_VOLUME_MUTED: True}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_active.value == 1
|
||||
|
||||
hass.states.async_set(entity_id, STATE_OFF)
|
||||
hass.states.async_set(entity_id, STATE_OFF, base_attrs)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_active.value == 0
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: "HDMI 3"})
|
||||
hass.states.async_set(
|
||||
entity_id, STATE_ON, {**base_attrs, ATTR_INPUT_SOURCE: "HDMI 3"}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_active.value == 1
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
"""Test different accessory types: Remotes."""
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.homekit.accessories import HomeDriver
|
||||
from homeassistant.components.homekit.const import (
|
||||
ATTR_KEY_NAME,
|
||||
ATTR_VALUE,
|
||||
DOMAIN as HOMEKIT_DOMAIN,
|
||||
EVENT_HOMEKIT_TV_REMOTE_KEY_PRESSED,
|
||||
KEY_ARROW_RIGHT,
|
||||
SERVICE_HOMEKIT_RESET_ACCESSORY,
|
||||
)
|
||||
from homeassistant.components.homekit.type_remotes import ActivityRemote
|
||||
from homeassistant.components.remote import (
|
||||
|
@ -30,18 +31,19 @@ from tests.common import async_mock_service
|
|||
|
||||
|
||||
async def test_activity_remote(
|
||||
hass: HomeAssistant, hk_driver, events, caplog: pytest.LogCaptureFixture
|
||||
hass: HomeAssistant, hk_driver: HomeDriver, events, caplog: pytest.LogCaptureFixture
|
||||
) -> None:
|
||||
"""Test if remote accessory and HA are updated accordingly."""
|
||||
entity_id = "remote.harmony"
|
||||
base_attrs = {
|
||||
ATTR_SUPPORTED_FEATURES: RemoteEntityFeature.ACTIVITY,
|
||||
ATTR_CURRENT_ACTIVITY: "Apple TV",
|
||||
ATTR_ACTIVITY_LIST: ["TV", "Apple TV"],
|
||||
}
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
None,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: RemoteEntityFeature.ACTIVITY,
|
||||
ATTR_CURRENT_ACTIVITY: "Apple TV",
|
||||
ATTR_ACTIVITY_LIST: ["TV", "Apple TV"],
|
||||
},
|
||||
base_attrs,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
acc = ActivityRemote(hass, hk_driver, "ActivityRemote", entity_id, 2, None)
|
||||
|
@ -58,47 +60,31 @@ async def test_activity_remote(
|
|||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: RemoteEntityFeature.ACTIVITY,
|
||||
ATTR_CURRENT_ACTIVITY: "Apple TV",
|
||||
ATTR_ACTIVITY_LIST: ["TV", "Apple TV"],
|
||||
},
|
||||
base_attrs,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_active.value == 1
|
||||
|
||||
hass.states.async_set(entity_id, STATE_OFF)
|
||||
hass.states.async_set(entity_id, STATE_OFF, base_attrs)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_active.value == 0
|
||||
|
||||
hass.states.async_set(entity_id, STATE_ON)
|
||||
hass.states.async_set(entity_id, STATE_ON, base_attrs)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_active.value == 1
|
||||
|
||||
hass.states.async_set(entity_id, STATE_STANDBY)
|
||||
hass.states.async_set(entity_id, STATE_STANDBY, base_attrs)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_active.value == 0
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: RemoteEntityFeature.ACTIVITY,
|
||||
ATTR_CURRENT_ACTIVITY: "TV",
|
||||
ATTR_ACTIVITY_LIST: ["TV", "Apple TV"],
|
||||
},
|
||||
entity_id, STATE_ON, {**base_attrs, ATTR_CURRENT_ACTIVITY: "TV"}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_input_source.value == 0
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: RemoteEntityFeature.ACTIVITY,
|
||||
ATTR_CURRENT_ACTIVITY: "Apple TV",
|
||||
ATTR_ACTIVITY_LIST: ["TV", "Apple TV"],
|
||||
},
|
||||
entity_id, STATE_ON, {**base_attrs, ATTR_CURRENT_ACTIVITY: "Apple TV"}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_input_source.value == 1
|
||||
|
@ -154,21 +140,19 @@ async def test_activity_remote(
|
|||
assert len(events) == 1
|
||||
assert events[0].data[ATTR_KEY_NAME] == KEY_ARROW_RIGHT
|
||||
|
||||
call_reset_accessory = async_mock_service(
|
||||
hass, HOMEKIT_DOMAIN, SERVICE_HOMEKIT_RESET_ACCESSORY
|
||||
)
|
||||
# A wild source appears - The accessory should rebuild itself
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: RemoteEntityFeature.ACTIVITY,
|
||||
ATTR_CURRENT_ACTIVITY: "Amazon TV",
|
||||
ATTR_ACTIVITY_LIST: ["TV", "Apple TV", "Amazon TV"],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert call_reset_accessory[0].data[ATTR_ENTITY_ID] == entity_id
|
||||
# A wild source appears - The accessory should reload itself
|
||||
with patch.object(acc, "async_reload") as mock_reload:
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
STATE_ON,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_CURRENT_ACTIVITY: "Amazon TV",
|
||||
ATTR_ACTIVITY_LIST: ["TV", "Apple TV", "Amazon TV"],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_reload.called
|
||||
|
||||
|
||||
async def test_activity_remote_bad_names(
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
"""Test different accessory types: Sensors."""
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
|
||||
from homeassistant.components.homekit import get_accessory
|
||||
from homeassistant.components.homekit.const import (
|
||||
|
@ -71,11 +73,13 @@ async def test_temperature(hass: HomeAssistant, hk_driver) -> None:
|
|||
await hass.async_block_till_done()
|
||||
assert acc.char_temp.value == 0
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id, "75.2", {ATTR_UNIT_OF_MEASUREMENT: UnitOfTemperature.FAHRENHEIT}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_temp.value == 24
|
||||
# The UOM changes, the accessory should reload itself
|
||||
with patch.object(acc, "async_reload") as mock_reload:
|
||||
hass.states.async_set(
|
||||
entity_id, "75.2", {ATTR_UNIT_OF_MEASUREMENT: UnitOfTemperature.FAHRENHEIT}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_reload.called
|
||||
|
||||
|
||||
async def test_humidity(hass: HomeAssistant, hk_driver) -> None:
|
||||
|
|
|
@ -79,21 +79,22 @@ from tests.common import async_mock_service
|
|||
async def test_thermostat(hass: HomeAssistant, hk_driver, events) -> None:
|
||||
"""Test if accessory and HA are updated accordingly."""
|
||||
entity_id = "climate.test"
|
||||
base_attrs = {
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
}
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
HVACMode.OFF,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
base_attrs,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
acc = Thermostat(hass, hk_driver, "Climate", entity_id, 1, None)
|
||||
|
@ -124,17 +125,10 @@ async def test_thermostat(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
entity_id,
|
||||
HVACMode.HEAT,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TEMPERATURE: 22.2,
|
||||
ATTR_CURRENT_TEMPERATURE: 17.8,
|
||||
ATTR_HVAC_ACTION: HVACAction.HEATING,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -148,17 +142,10 @@ async def test_thermostat(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
entity_id,
|
||||
HVACMode.HEAT,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TEMPERATURE: 22.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 23.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.IDLE,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -172,17 +159,10 @@ async def test_thermostat(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
entity_id,
|
||||
HVACMode.FAN_ONLY,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TEMPERATURE: 20.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 25.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.COOLING,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -196,6 +176,7 @@ async def test_thermostat(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
entity_id,
|
||||
HVACMode.COOL,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TEMPERATURE: 20.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 19.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.IDLE,
|
||||
|
@ -211,7 +192,7 @@ async def test_thermostat(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
hass.states.async_set(
|
||||
entity_id,
|
||||
HVACMode.OFF,
|
||||
{ATTR_TEMPERATURE: 22.0, ATTR_CURRENT_TEMPERATURE: 18.0},
|
||||
{**base_attrs, ATTR_TEMPERATURE: 22.0, ATTR_CURRENT_TEMPERATURE: 18.0},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_target_temp.value == 22.0
|
||||
|
@ -224,17 +205,10 @@ async def test_thermostat(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
entity_id,
|
||||
HVACMode.AUTO,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TEMPERATURE: 22.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 18.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.HEATING,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -248,17 +222,10 @@ async def test_thermostat(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
entity_id,
|
||||
HVACMode.HEAT_COOL,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TEMPERATURE: 22.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 25.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.COOLING,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -272,17 +239,10 @@ async def test_thermostat(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
entity_id,
|
||||
HVACMode.AUTO,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TEMPERATURE: 22.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 22.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.IDLE,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -296,17 +256,10 @@ async def test_thermostat(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
entity_id,
|
||||
HVACMode.FAN_ONLY,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TEMPERATURE: 22.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 22.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.FAN,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -320,7 +273,7 @@ async def test_thermostat(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
entity_id,
|
||||
HVACMode.DRY,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE,
|
||||
**base_attrs,
|
||||
ATTR_TEMPERATURE: 22.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 22.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.DRYING,
|
||||
|
@ -419,23 +372,23 @@ async def test_thermostat(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
async def test_thermostat_auto(hass: HomeAssistant, hk_driver, events) -> None:
|
||||
"""Test if accessory and HA are updated accordingly."""
|
||||
entity_id = "climate.test"
|
||||
|
||||
base_attrs = {
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
}
|
||||
# support_auto = True
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
HVACMode.OFF,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
base_attrs,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
acc = Thermostat(hass, hk_driver, "Climate", entity_id, 1, None)
|
||||
|
@ -458,18 +411,11 @@ async def test_thermostat_auto(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
entity_id,
|
||||
HVACMode.HEAT_COOL,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TARGET_TEMP_HIGH: 22.0,
|
||||
ATTR_TARGET_TEMP_LOW: 20.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 18.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.HEATING,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -484,18 +430,11 @@ async def test_thermostat_auto(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
entity_id,
|
||||
HVACMode.COOL,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TARGET_TEMP_HIGH: 23.0,
|
||||
ATTR_TARGET_TEMP_LOW: 19.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 24.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.COOLING,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -510,18 +449,11 @@ async def test_thermostat_auto(hass: HomeAssistant, hk_driver, events) -> None:
|
|||
entity_id,
|
||||
HVACMode.AUTO,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TARGET_TEMP_HIGH: 23.0,
|
||||
ATTR_TARGET_TEMP_LOW: 19.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 21.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.IDLE,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -575,23 +507,23 @@ async def test_thermostat_mode_and_temp_change(
|
|||
) -> None:
|
||||
"""Test if accessory where the mode and temp change in the same call."""
|
||||
entity_id = "climate.test"
|
||||
|
||||
base_attrs = {
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
}
|
||||
# support_auto = True
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
HVACMode.OFF,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
base_attrs,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
acc = Thermostat(hass, hk_driver, "Climate", entity_id, 1, None)
|
||||
|
@ -614,18 +546,11 @@ async def test_thermostat_mode_and_temp_change(
|
|||
entity_id,
|
||||
HVACMode.COOL,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TARGET_TEMP_HIGH: 23.0,
|
||||
ATTR_TARGET_TEMP_LOW: 19.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 21.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.COOLING,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -688,9 +613,9 @@ async def test_thermostat_mode_and_temp_change(
|
|||
async def test_thermostat_humidity(hass: HomeAssistant, hk_driver, events) -> None:
|
||||
"""Test if accessory and HA are updated accordingly with humidity."""
|
||||
entity_id = "climate.test"
|
||||
|
||||
base_attrs = {ATTR_SUPPORTED_FEATURES: 4}
|
||||
# support_auto = True
|
||||
hass.states.async_set(entity_id, HVACMode.OFF, {ATTR_SUPPORTED_FEATURES: 4})
|
||||
hass.states.async_set(entity_id, HVACMode.OFF, base_attrs)
|
||||
await hass.async_block_till_done()
|
||||
acc = Thermostat(hass, hk_driver, "Climate", entity_id, 1, None)
|
||||
hk_driver.add_accessory(acc)
|
||||
|
@ -704,14 +629,18 @@ async def test_thermostat_humidity(hass: HomeAssistant, hk_driver, events) -> No
|
|||
assert acc.char_target_humidity.properties[PROP_MIN_VALUE] == DEFAULT_MIN_HUMIDITY
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id, HVACMode.HEAT_COOL, {ATTR_HUMIDITY: 65, ATTR_CURRENT_HUMIDITY: 40}
|
||||
entity_id,
|
||||
HVACMode.HEAT_COOL,
|
||||
{**base_attrs, ATTR_HUMIDITY: 65, ATTR_CURRENT_HUMIDITY: 40},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_current_humidity.value == 40
|
||||
assert acc.char_target_humidity.value == 65
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id, HVACMode.COOL, {ATTR_HUMIDITY: 35, ATTR_CURRENT_HUMIDITY: 70}
|
||||
entity_id,
|
||||
HVACMode.COOL,
|
||||
{**base_attrs, ATTR_HUMIDITY: 35, ATTR_CURRENT_HUMIDITY: 70},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_current_humidity.value == 70
|
||||
|
@ -772,24 +701,24 @@ async def test_thermostat_humidity_with_target_humidity(
|
|||
async def test_thermostat_power_state(hass: HomeAssistant, hk_driver, events) -> None:
|
||||
"""Test if accessory and HA are updated accordingly."""
|
||||
entity_id = "climate.test"
|
||||
|
||||
base_attrs = {
|
||||
ATTR_SUPPORTED_FEATURES: 4096,
|
||||
ATTR_TEMPERATURE: 23.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 18.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.HEATING,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.COOL,
|
||||
HVACMode.AUTO,
|
||||
HVACMode.HEAT,
|
||||
HVACMode.OFF,
|
||||
],
|
||||
}
|
||||
# SUPPORT_ON_OFF = True
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
HVACMode.HEAT,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: 4096,
|
||||
ATTR_TEMPERATURE: 23.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 18.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.HEATING,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.COOL,
|
||||
HVACMode.AUTO,
|
||||
HVACMode.HEAT,
|
||||
HVACMode.OFF,
|
||||
],
|
||||
},
|
||||
base_attrs,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
acc = Thermostat(hass, hk_driver, "Climate", entity_id, 1, None)
|
||||
|
@ -805,16 +734,10 @@ async def test_thermostat_power_state(hass: HomeAssistant, hk_driver, events) ->
|
|||
entity_id,
|
||||
HVACMode.OFF,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TEMPERATURE: 23.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 18.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.IDLE,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.COOL,
|
||||
HVACMode.AUTO,
|
||||
HVACMode.HEAT,
|
||||
HVACMode.OFF,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -825,16 +748,10 @@ async def test_thermostat_power_state(hass: HomeAssistant, hk_driver, events) ->
|
|||
entity_id,
|
||||
HVACMode.OFF,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TEMPERATURE: 23.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 18.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.IDLE,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.COOL,
|
||||
HVACMode.AUTO,
|
||||
HVACMode.HEAT,
|
||||
HVACMode.OFF,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -1566,12 +1483,15 @@ async def test_thermostat_without_target_temp_only_range(
|
|||
) -> None:
|
||||
"""Test a thermostat that only supports a range."""
|
||||
entity_id = "climate.test"
|
||||
base_attrs = {
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
|
||||
}
|
||||
|
||||
# support_auto = True
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
HVACMode.OFF,
|
||||
{ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE_RANGE},
|
||||
base_attrs,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
acc = Thermostat(hass, hk_driver, "Climate", entity_id, 1, None)
|
||||
|
@ -1594,19 +1514,11 @@ async def test_thermostat_without_target_temp_only_range(
|
|||
entity_id,
|
||||
HVACMode.HEAT_COOL,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TARGET_TEMP_HIGH: 22.0,
|
||||
ATTR_TARGET_TEMP_LOW: 20.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 18.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.HEATING,
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE_RANGE,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -1621,19 +1533,11 @@ async def test_thermostat_without_target_temp_only_range(
|
|||
entity_id,
|
||||
HVACMode.COOL,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TARGET_TEMP_HIGH: 23.0,
|
||||
ATTR_TARGET_TEMP_LOW: 19.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 24.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.COOLING,
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE_RANGE,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -1648,19 +1552,11 @@ async def test_thermostat_without_target_temp_only_range(
|
|||
entity_id,
|
||||
HVACMode.COOL,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TARGET_TEMP_HIGH: 23.0,
|
||||
ATTR_TARGET_TEMP_LOW: 19.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 21.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.IDLE,
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE_RANGE,
|
||||
ATTR_HVAC_MODES: [
|
||||
HVACMode.HEAT,
|
||||
HVACMode.HEAT_COOL,
|
||||
HVACMode.FAN_ONLY,
|
||||
HVACMode.COOL,
|
||||
HVACMode.OFF,
|
||||
HVACMode.AUTO,
|
||||
],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -1925,16 +1821,17 @@ async def test_thermostat_with_no_modes_when_we_first_see(
|
|||
) -> None:
|
||||
"""Test if a thermostat that is not ready when we first see it."""
|
||||
entity_id = "climate.test"
|
||||
base_attrs = {
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE,
|
||||
ATTR_HVAC_MODES: [],
|
||||
}
|
||||
|
||||
# support_auto = True
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
HVACMode.OFF,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE,
|
||||
ATTR_HVAC_MODES: [],
|
||||
},
|
||||
base_attrs,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
acc = Thermostat(hass, hk_driver, "Climate", entity_id, 1, None)
|
||||
|
@ -1955,24 +1852,22 @@ async def test_thermostat_with_no_modes_when_we_first_see(
|
|||
|
||||
assert acc.char_target_heat_cool.value == 0
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
HVACMode.HEAT_COOL,
|
||||
{
|
||||
ATTR_TARGET_TEMP_HIGH: 22.0,
|
||||
ATTR_TARGET_TEMP_LOW: 20.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 18.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.HEATING,
|
||||
ATTR_HVAC_MODES: [HVACMode.HEAT_COOL, HVACMode.OFF, HVACMode.AUTO],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_heating_thresh_temp.value == 20.0
|
||||
assert acc.char_cooling_thresh_temp.value == 22.0
|
||||
assert acc.char_current_heat_cool.value == 1
|
||||
assert acc.char_target_heat_cool.value == 3
|
||||
assert acc.char_current_temp.value == 18.0
|
||||
assert acc.char_display_units.value == 0
|
||||
# Verify reload on modes changed out from under us
|
||||
with patch.object(acc, "async_reload") as mock_reload:
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
HVACMode.HEAT_COOL,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TARGET_TEMP_HIGH: 22.0,
|
||||
ATTR_TARGET_TEMP_LOW: 20.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 18.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.HEATING,
|
||||
ATTR_HVAC_MODES: [HVACMode.HEAT_COOL, HVACMode.OFF, HVACMode.AUTO],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_reload.called
|
||||
|
||||
|
||||
async def test_thermostat_with_no_off_after_recheck(
|
||||
|
@ -1981,15 +1876,16 @@ async def test_thermostat_with_no_off_after_recheck(
|
|||
"""Test if a thermostat that is not ready when we first see it that actually does not have off."""
|
||||
entity_id = "climate.test"
|
||||
|
||||
base_attrs = {
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE,
|
||||
ATTR_HVAC_MODES: [],
|
||||
}
|
||||
# support_auto = True
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
HVACMode.COOL,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE,
|
||||
ATTR_HVAC_MODES: [],
|
||||
},
|
||||
base_attrs,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
acc = Thermostat(hass, hk_driver, "Climate", entity_id, 1, None)
|
||||
|
@ -2010,24 +1906,22 @@ async def test_thermostat_with_no_off_after_recheck(
|
|||
|
||||
assert acc.char_target_heat_cool.value == 2
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
HVACMode.HEAT_COOL,
|
||||
{
|
||||
ATTR_TARGET_TEMP_HIGH: 22.0,
|
||||
ATTR_TARGET_TEMP_LOW: 20.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 18.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.HEATING,
|
||||
ATTR_HVAC_MODES: [HVACMode.HEAT_COOL, HVACMode.AUTO],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert acc.char_heating_thresh_temp.value == 20.0
|
||||
assert acc.char_cooling_thresh_temp.value == 22.0
|
||||
assert acc.char_current_heat_cool.value == 1
|
||||
assert acc.char_target_heat_cool.value == 3
|
||||
assert acc.char_current_temp.value == 18.0
|
||||
assert acc.char_display_units.value == 0
|
||||
# Verify reload when modes change out from under us
|
||||
with patch.object(acc, "async_reload") as mock_reload:
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
HVACMode.HEAT_COOL,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TARGET_TEMP_HIGH: 22.0,
|
||||
ATTR_TARGET_TEMP_LOW: 20.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 18.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.HEATING,
|
||||
ATTR_HVAC_MODES: [HVACMode.HEAT_COOL, HVACMode.AUTO],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_reload.called
|
||||
|
||||
|
||||
async def test_thermostat_with_temp_clamps(
|
||||
|
@ -2035,17 +1929,17 @@ async def test_thermostat_with_temp_clamps(
|
|||
) -> None:
|
||||
"""Test that tempatures are clamped to valid values to prevent homekit crash."""
|
||||
entity_id = "climate.test"
|
||||
|
||||
base_attrs = {
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE,
|
||||
ATTR_HVAC_MODES: [HVACMode.HEAT_COOL, HVACMode.AUTO],
|
||||
ATTR_MAX_TEMP: 50,
|
||||
ATTR_MIN_TEMP: 100,
|
||||
}
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
HVACMode.COOL,
|
||||
{
|
||||
ATTR_SUPPORTED_FEATURES: ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE,
|
||||
ATTR_HVAC_MODES: [],
|
||||
ATTR_MAX_TEMP: 50,
|
||||
ATTR_MIN_TEMP: 100,
|
||||
},
|
||||
base_attrs,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
acc = Thermostat(hass, hk_driver, "Climate", entity_id, 1, None)
|
||||
|
@ -2064,17 +1958,17 @@ async def test_thermostat_with_temp_clamps(
|
|||
assert acc.char_heating_thresh_temp.properties[PROP_MIN_VALUE] == 100
|
||||
assert acc.char_heating_thresh_temp.properties[PROP_MIN_STEP] == 0.1
|
||||
|
||||
assert acc.char_target_heat_cool.value == 2
|
||||
assert acc.char_target_heat_cool.value == 3
|
||||
|
||||
hass.states.async_set(
|
||||
entity_id,
|
||||
HVACMode.HEAT_COOL,
|
||||
{
|
||||
**base_attrs,
|
||||
ATTR_TARGET_TEMP_HIGH: 822.0,
|
||||
ATTR_TARGET_TEMP_LOW: 20.0,
|
||||
ATTR_CURRENT_TEMPERATURE: 9918.0,
|
||||
ATTR_HVAC_ACTION: HVACAction.HEATING,
|
||||
ATTR_HVAC_MODES: [HVACMode.HEAT_COOL, HVACMode.AUTO],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
|
|
@ -71,3 +71,4 @@ async def test_programmable_switch_button_fires_on_trigger(
|
|||
char = acc.get_characteristic(call.args[0]["aid"], call.args[0]["iid"])
|
||||
assert char.display_name == CHAR_PROGRAMMABLE_SWITCH_EVENT
|
||||
await acc.stop()
|
||||
await hass.async_block_till_done()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue