diff --git a/tests/components/homekit_controller/common.py b/tests/components/homekit_controller/common.py index 802c150b981..0891d6209b7 100644 --- a/tests/components/homekit_controller/common.py +++ b/tests/components/homekit_controller/common.py @@ -10,9 +10,8 @@ from typing import Any, Final from unittest import mock from aiohomekit.model import Accessories, Accessory -from aiohomekit.model.characteristics import CharacteristicsTypes from aiohomekit.model.services import ServicesTypes -from aiohomekit.testing import FakeController +from aiohomekit.testing import FakeController, FakePairing from homeassistant.components import zeroconf from homeassistant.components.device_automation import DeviceAutomationType @@ -24,7 +23,8 @@ from homeassistant.components.homekit_controller.const import ( IDENTIFIER_ACCESSORY_ID, IDENTIFIER_SERIAL_NUMBER, ) -from homeassistant.core import HomeAssistant +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant, State, callback from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers.entity import EntityCategory from homeassistant.setup import async_setup_component @@ -94,7 +94,14 @@ class DeviceTestInfo: class Helper: """Helper methods for interacting with HomeKit fakes.""" - def __init__(self, hass, entity_id, pairing, accessory, config_entry): + def __init__( + self, + hass: HomeAssistant, + entity_id: str, + pairing: FakePairing, + accessory: Accessory, + config_entry: ConfigEntry, + ) -> None: """Create a helper for a given accessory/entity.""" self.hass = hass self.entity_id = entity_id @@ -102,19 +109,43 @@ class Helper: self.accessory = accessory self.config_entry = config_entry - self.characteristics = {} - for service in self.accessory.services: - service_name = ServicesTypes.get_short(service.type) - for char in service.characteristics: - char_name = CharacteristicsTypes.get_short(char.type) - self.characteristics[(service_name, char_name)] = char + async def async_update( + self, service: str, characteristics: dict[str, Any] + ) -> State: + """Set the characteristics on this service.""" + changes = [] + + service = self.accessory.services.first(service_type=service) + aid = service.accessory.aid + + for ctype, value in characteristics.items(): + char = service.characteristics.first(char_types=[ctype]) + changes.append((aid, char.iid, value)) + + self.pairing.testing.update_aid_iid(changes) + + if not self.pairing.testing.events_enabled: + # If events aren't enabled, explicitly do a poll + # If they are enabled, then HA will pick up the changes next time + # we yield control + await time_changed(self.hass, 60) - async def update_named_service(self, service, characteristics): - """Update a service.""" - self.pairing.testing.update_named_service(service, characteristics) await self.hass.async_block_till_done() - async def poll_and_get_state(self): + state = self.hass.states.get(self.entity_id) + assert state is not None + return state + + @callback + def async_assert_service_values( + self, service: str, characteristics: dict[str, Any] + ) -> None: + """Assert a service has characteristics with these values.""" + service = self.accessory.services.first(service_type=service) + for ctype, value in characteristics.items(): + assert service.value(ctype) == value + + async def poll_and_get_state(self) -> State: """Trigger a time based poll and return the current entity state.""" await time_changed(self.hass, 60) diff --git a/tests/components/homekit_controller/specific_devices/test_koogeek_ls1.py b/tests/components/homekit_controller/specific_devices/test_koogeek_ls1.py index 9591eb27b6f..33a1ebdbafe 100644 --- a/tests/components/homekit_controller/specific_devices/test_koogeek_ls1.py +++ b/tests/components/homekit_controller/specific_devices/test_koogeek_ls1.py @@ -4,6 +4,7 @@ from datetime import timedelta from unittest import mock from aiohomekit.exceptions import AccessoryDisconnectedError, EncryptionError +from aiohomekit.model import CharacteristicsTypes, ServicesTypes from aiohomekit.testing import FakePairing import pytest @@ -72,26 +73,29 @@ async def test_recover_from_failure(hass, utcnow, failure_cls): accessories = await setup_accessories_from_file(hass, "koogeek_ls1.json") config_entry, pairing = await setup_test_accessories(hass, accessories) + pairing.testing.events_enabled = False + helper = Helper( hass, "light.koogeek_ls1_20833f", pairing, accessories[0], config_entry ) # Set light state on fake device to off - helper.characteristics[LIGHT_ON].set_value(False) + state = await helper.async_update( + ServicesTypes.LIGHTBULB, {CharacteristicsTypes.ON: False} + ) # Test that entity starts off in a known state - state = await helper.poll_and_get_state() assert state.state == "off" - # Set light state on fake device to on - helper.characteristics[LIGHT_ON].set_value(True) - # Test that entity remains in the same state if there is a network error next_update = dt_util.utcnow() + timedelta(seconds=60) with mock.patch.object(FakePairing, "get_characteristics") as get_char: get_char.side_effect = failure_cls("Disconnected") - state = await helper.poll_and_get_state() + # Set light state on fake device to on + state = await helper.async_update( + ServicesTypes.LIGHTBULB, {CharacteristicsTypes.ON: True} + ) assert state.state == "off" chars = get_char.call_args[0][0] @@ -102,5 +106,7 @@ async def test_recover_from_failure(hass, utcnow, failure_cls): async_fire_time_changed(hass, next_update) await hass.async_block_till_done() - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.LIGHTBULB, {CharacteristicsTypes.ON: True} + ) assert state.state == "on" diff --git a/tests/components/homekit_controller/test_alarm_control_panel.py b/tests/components/homekit_controller/test_alarm_control_panel.py index 5694be5f955..2804ffff824 100644 --- a/tests/components/homekit_controller/test_alarm_control_panel.py +++ b/tests/components/homekit_controller/test_alarm_control_panel.py @@ -4,9 +4,6 @@ from aiohomekit.model.services import ServicesTypes from tests.components.homekit_controller.common import setup_test_component -CURRENT_STATE = ("security-system", "security-system-state.current") -TARGET_STATE = ("security-system", "security-system-state.target") - def create_security_system_service(accessory): """Define a security-system characteristics as per page 219 of HAP spec.""" @@ -36,7 +33,12 @@ async def test_switch_change_alarm_state(hass, utcnow): {"entity_id": "alarm_control_panel.testdevice"}, blocking=True, ) - assert helper.characteristics[TARGET_STATE].value == 0 + helper.async_assert_service_values( + ServicesTypes.SECURITY_SYSTEM, + { + CharacteristicsTypes.SECURITY_SYSTEM_STATE_TARGET: 0, + }, + ) await hass.services.async_call( "alarm_control_panel", @@ -44,7 +46,12 @@ async def test_switch_change_alarm_state(hass, utcnow): {"entity_id": "alarm_control_panel.testdevice"}, blocking=True, ) - assert helper.characteristics[TARGET_STATE].value == 1 + helper.async_assert_service_values( + ServicesTypes.SECURITY_SYSTEM, + { + CharacteristicsTypes.SECURITY_SYSTEM_STATE_TARGET: 1, + }, + ) await hass.services.async_call( "alarm_control_panel", @@ -52,7 +59,12 @@ async def test_switch_change_alarm_state(hass, utcnow): {"entity_id": "alarm_control_panel.testdevice"}, blocking=True, ) - assert helper.characteristics[TARGET_STATE].value == 2 + helper.async_assert_service_values( + ServicesTypes.SECURITY_SYSTEM, + { + CharacteristicsTypes.SECURITY_SYSTEM_STATE_TARGET: 2, + }, + ) await hass.services.async_call( "alarm_control_panel", @@ -60,30 +72,50 @@ async def test_switch_change_alarm_state(hass, utcnow): {"entity_id": "alarm_control_panel.testdevice"}, blocking=True, ) - assert helper.characteristics[TARGET_STATE].value == 3 + helper.async_assert_service_values( + ServicesTypes.SECURITY_SYSTEM, + { + CharacteristicsTypes.SECURITY_SYSTEM_STATE_TARGET: 3, + }, + ) async def test_switch_read_alarm_state(hass, utcnow): """Test that we can read the state of a HomeKit alarm accessory.""" helper = await setup_test_component(hass, create_security_system_service) - helper.characteristics[CURRENT_STATE].value = 0 + await helper.async_update( + ServicesTypes.SECURITY_SYSTEM, + {CharacteristicsTypes.SECURITY_SYSTEM_STATE_CURRENT: 0}, + ) state = await helper.poll_and_get_state() assert state.state == "armed_home" assert state.attributes["battery_level"] == 50 - helper.characteristics[CURRENT_STATE].value = 1 + await helper.async_update( + ServicesTypes.SECURITY_SYSTEM, + {CharacteristicsTypes.SECURITY_SYSTEM_STATE_CURRENT: 1}, + ) state = await helper.poll_and_get_state() assert state.state == "armed_away" - helper.characteristics[CURRENT_STATE].value = 2 + await helper.async_update( + ServicesTypes.SECURITY_SYSTEM, + {CharacteristicsTypes.SECURITY_SYSTEM_STATE_CURRENT: 2}, + ) state = await helper.poll_and_get_state() assert state.state == "armed_night" - helper.characteristics[CURRENT_STATE].value = 3 + await helper.async_update( + ServicesTypes.SECURITY_SYSTEM, + {CharacteristicsTypes.SECURITY_SYSTEM_STATE_CURRENT: 3}, + ) state = await helper.poll_and_get_state() assert state.state == "disarmed" - helper.characteristics[CURRENT_STATE].value = 4 + await helper.async_update( + ServicesTypes.SECURITY_SYSTEM, + {CharacteristicsTypes.SECURITY_SYSTEM_STATE_CURRENT: 4}, + ) state = await helper.poll_and_get_state() assert state.state == "triggered" diff --git a/tests/components/homekit_controller/test_binary_sensor.py b/tests/components/homekit_controller/test_binary_sensor.py index e0b23775c4d..d83beb07df3 100644 --- a/tests/components/homekit_controller/test_binary_sensor.py +++ b/tests/components/homekit_controller/test_binary_sensor.py @@ -6,13 +6,6 @@ from homeassistant.components.binary_sensor import BinarySensorDeviceClass from tests.components.homekit_controller.common import setup_test_component -MOTION_DETECTED = ("motion", "motion-detected") -CONTACT_STATE = ("contact", "contact-state") -SMOKE_DETECTED = ("smoke", "smoke-detected") -CARBON_MONOXIDE_DETECTED = ("carbon-monoxide", "carbon-monoxide.detected") -OCCUPANCY_DETECTED = ("occupancy", "occupancy-detected") -LEAK_DETECTED = ("leak", "leak-detected") - def create_motion_sensor_service(accessory): """Define motion characteristics as per page 225 of HAP spec.""" @@ -26,11 +19,15 @@ async def test_motion_sensor_read_state(hass, utcnow): """Test that we can read the state of a HomeKit motion sensor accessory.""" helper = await setup_test_component(hass, create_motion_sensor_service) - helper.characteristics[MOTION_DETECTED].value = False + await helper.async_update( + ServicesTypes.MOTION_SENSOR, {CharacteristicsTypes.MOTION_DETECTED: False} + ) state = await helper.poll_and_get_state() assert state.state == "off" - helper.characteristics[MOTION_DETECTED].value = True + await helper.async_update( + ServicesTypes.MOTION_SENSOR, {CharacteristicsTypes.MOTION_DETECTED: True} + ) state = await helper.poll_and_get_state() assert state.state == "on" @@ -49,11 +46,15 @@ async def test_contact_sensor_read_state(hass, utcnow): """Test that we can read the state of a HomeKit contact accessory.""" helper = await setup_test_component(hass, create_contact_sensor_service) - helper.characteristics[CONTACT_STATE].value = 0 + await helper.async_update( + ServicesTypes.CONTACT_SENSOR, {CharacteristicsTypes.CONTACT_STATE: 0} + ) state = await helper.poll_and_get_state() assert state.state == "off" - helper.characteristics[CONTACT_STATE].value = 1 + await helper.async_update( + ServicesTypes.CONTACT_SENSOR, {CharacteristicsTypes.CONTACT_STATE: 1} + ) state = await helper.poll_and_get_state() assert state.state == "on" @@ -72,11 +73,15 @@ async def test_smoke_sensor_read_state(hass, utcnow): """Test that we can read the state of a HomeKit contact accessory.""" helper = await setup_test_component(hass, create_smoke_sensor_service) - helper.characteristics[SMOKE_DETECTED].value = 0 + await helper.async_update( + ServicesTypes.SMOKE_SENSOR, {CharacteristicsTypes.SMOKE_DETECTED: 0} + ) state = await helper.poll_and_get_state() assert state.state == "off" - helper.characteristics[SMOKE_DETECTED].value = 1 + await helper.async_update( + ServicesTypes.SMOKE_SENSOR, {CharacteristicsTypes.SMOKE_DETECTED: 1} + ) state = await helper.poll_and_get_state() assert state.state == "on" @@ -95,11 +100,17 @@ async def test_carbon_monoxide_sensor_read_state(hass, utcnow): """Test that we can read the state of a HomeKit contact accessory.""" helper = await setup_test_component(hass, create_carbon_monoxide_sensor_service) - helper.characteristics[CARBON_MONOXIDE_DETECTED].value = 0 + await helper.async_update( + ServicesTypes.CARBON_MONOXIDE_SENSOR, + {CharacteristicsTypes.CARBON_MONOXIDE_DETECTED: 0}, + ) state = await helper.poll_and_get_state() assert state.state == "off" - helper.characteristics[CARBON_MONOXIDE_DETECTED].value = 1 + await helper.async_update( + ServicesTypes.CARBON_MONOXIDE_SENSOR, + {CharacteristicsTypes.CARBON_MONOXIDE_DETECTED: 1}, + ) state = await helper.poll_and_get_state() assert state.state == "on" @@ -118,11 +129,15 @@ async def test_occupancy_sensor_read_state(hass, utcnow): """Test that we can read the state of a HomeKit occupancy sensor accessory.""" helper = await setup_test_component(hass, create_occupancy_sensor_service) - helper.characteristics[OCCUPANCY_DETECTED].value = False + await helper.async_update( + ServicesTypes.OCCUPANCY_SENSOR, {CharacteristicsTypes.OCCUPANCY_DETECTED: False} + ) state = await helper.poll_and_get_state() assert state.state == "off" - helper.characteristics[OCCUPANCY_DETECTED].value = True + await helper.async_update( + ServicesTypes.OCCUPANCY_SENSOR, {CharacteristicsTypes.OCCUPANCY_DETECTED: True} + ) state = await helper.poll_and_get_state() assert state.state == "on" @@ -141,11 +156,15 @@ async def test_leak_sensor_read_state(hass, utcnow): """Test that we can read the state of a HomeKit leak sensor accessory.""" helper = await setup_test_component(hass, create_leak_sensor_service) - helper.characteristics[LEAK_DETECTED].value = 0 + await helper.async_update( + ServicesTypes.LEAK_SENSOR, {CharacteristicsTypes.LEAK_DETECTED: 0} + ) state = await helper.poll_and_get_state() assert state.state == "off" - helper.characteristics[LEAK_DETECTED].value = 1 + await helper.async_update( + ServicesTypes.LEAK_SENSOR, {CharacteristicsTypes.LEAK_DETECTED: 1} + ) state = await helper.poll_and_get_state() assert state.state == "on" diff --git a/tests/components/homekit_controller/test_button.py b/tests/components/homekit_controller/test_button.py index c501a9e6fb0..131fed572f7 100644 --- a/tests/components/homekit_controller/test_button.py +++ b/tests/components/homekit_controller/test_button.py @@ -40,7 +40,7 @@ async def test_press_button(hass): helper = await setup_test_component(hass, create_switch_with_setup_button) # Helper will be for the primary entity, which is the outlet. Make a helper for the button. - energy_helper = Helper( + button = Helper( hass, "button.testdevice_setup", helper.pairing, @@ -48,16 +48,18 @@ async def test_press_button(hass): helper.config_entry, ) - outlet = energy_helper.accessory.services.first(service_type=ServicesTypes.OUTLET) - setup = outlet[CharacteristicsTypes.Vendor.HAA_SETUP] - await hass.services.async_call( "button", "press", {"entity_id": "button.testdevice_setup"}, blocking=True, ) - assert setup.value == "#HAA@trcmd" + button.async_assert_service_values( + ServicesTypes.OUTLET, + { + CharacteristicsTypes.Vendor.HAA_SETUP: "#HAA@trcmd", + }, + ) async def test_ecobee_clear_hold_press_button(hass): @@ -67,7 +69,7 @@ async def test_ecobee_clear_hold_press_button(hass): ) # Helper will be for the primary entity, which is the outlet. Make a helper for the button. - energy_helper = Helper( + clear_hold = Helper( hass, "button.testdevice_clear_hold", helper.pairing, @@ -75,13 +77,15 @@ async def test_ecobee_clear_hold_press_button(hass): helper.config_entry, ) - outlet = energy_helper.accessory.services.first(service_type=ServicesTypes.OUTLET) - setup = outlet[CharacteristicsTypes.Vendor.ECOBEE_CLEAR_HOLD] - await hass.services.async_call( "button", "press", {"entity_id": "button.testdevice_clear_hold"}, blocking=True, ) - assert setup.value is True + clear_hold.async_assert_service_values( + ServicesTypes.OUTLET, + { + CharacteristicsTypes.Vendor.ECOBEE_CLEAR_HOLD: True, + }, + ) diff --git a/tests/components/homekit_controller/test_climate.py b/tests/components/homekit_controller/test_climate.py index 07a5025ac88..9ca45fd53ac 100644 --- a/tests/components/homekit_controller/test_climate.py +++ b/tests/components/homekit_controller/test_climate.py @@ -22,21 +22,6 @@ from homeassistant.components.climate.const import ( from tests.components.homekit_controller.common import setup_test_component -HEATING_COOLING_TARGET = ("thermostat", "heating-cooling.target") -HEATING_COOLING_CURRENT = ("thermostat", "heating-cooling.current") -THERMOSTAT_TEMPERATURE_COOLING_THRESHOLD = ( - "thermostat", - "temperature.cooling-threshold", -) -THERMOSTAT_TEMPERATURE_HEATING_THRESHOLD = ( - "thermostat", - "temperature.heating-threshold", -) -TEMPERATURE_TARGET = ("thermostat", "temperature.target") -TEMPERATURE_CURRENT = ("thermostat", "temperature.current") -HUMIDITY_TARGET = ("thermostat", "relative-humidity.target") -HUMIDITY_CURRENT = ("thermostat", "relative-humidity.current") - # Test thermostat devices @@ -116,8 +101,12 @@ async def test_climate_change_thermostat_state(hass, utcnow): {"entity_id": "climate.testdevice", "hvac_mode": HVAC_MODE_HEAT}, blocking=True, ) - - assert helper.characteristics[HEATING_COOLING_TARGET].value == 1 + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.HEATING_COOLING_TARGET: 1, + }, + ) await hass.services.async_call( DOMAIN, @@ -125,7 +114,12 @@ async def test_climate_change_thermostat_state(hass, utcnow): {"entity_id": "climate.testdevice", "hvac_mode": HVAC_MODE_COOL}, blocking=True, ) - assert helper.characteristics[HEATING_COOLING_TARGET].value == 2 + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.HEATING_COOLING_TARGET: 2, + }, + ) await hass.services.async_call( DOMAIN, @@ -133,7 +127,12 @@ async def test_climate_change_thermostat_state(hass, utcnow): {"entity_id": "climate.testdevice", "hvac_mode": HVAC_MODE_HEAT_COOL}, blocking=True, ) - assert helper.characteristics[HEATING_COOLING_TARGET].value == 3 + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.HEATING_COOLING_TARGET: 3, + }, + ) await hass.services.async_call( DOMAIN, @@ -141,7 +140,12 @@ async def test_climate_change_thermostat_state(hass, utcnow): {"entity_id": "climate.testdevice", "hvac_mode": HVAC_MODE_OFF}, blocking=True, ) - assert helper.characteristics[HEATING_COOLING_TARGET].value == 0 + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.HEATING_COOLING_TARGET: 0, + }, + ) async def test_climate_check_min_max_values_per_mode(hass, utcnow): @@ -189,7 +193,12 @@ async def test_climate_change_thermostat_temperature(hass, utcnow): {"entity_id": "climate.testdevice", "temperature": 21}, blocking=True, ) - assert helper.characteristics[TEMPERATURE_TARGET].value == 21 + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.TEMPERATURE_TARGET: 21, + }, + ) await hass.services.async_call( DOMAIN, @@ -197,7 +206,12 @@ async def test_climate_change_thermostat_temperature(hass, utcnow): {"entity_id": "climate.testdevice", "temperature": 25}, blocking=True, ) - assert helper.characteristics[TEMPERATURE_TARGET].value == 25 + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.TEMPERATURE_TARGET: 25, + }, + ) async def test_climate_change_thermostat_temperature_range(hass, utcnow): @@ -222,9 +236,15 @@ async def test_climate_change_thermostat_temperature_range(hass, utcnow): }, blocking=True, ) - assert helper.characteristics[TEMPERATURE_TARGET].value == 22.5 - assert helper.characteristics[THERMOSTAT_TEMPERATURE_HEATING_THRESHOLD].value == 20 - assert helper.characteristics[THERMOSTAT_TEMPERATURE_COOLING_THRESHOLD].value == 25 + + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.TEMPERATURE_TARGET: 22.5, + CharacteristicsTypes.TEMPERATURE_HEATING_THRESHOLD: 20, + CharacteristicsTypes.TEMPERATURE_COOLING_THRESHOLD: 25, + }, + ) async def test_climate_change_thermostat_temperature_range_iphone(hass, utcnow): @@ -250,9 +270,14 @@ async def test_climate_change_thermostat_temperature_range_iphone(hass, utcnow): }, blocking=True, ) - assert helper.characteristics[TEMPERATURE_TARGET].value == 22 - assert helper.characteristics[THERMOSTAT_TEMPERATURE_HEATING_THRESHOLD].value == 20 - assert helper.characteristics[THERMOSTAT_TEMPERATURE_COOLING_THRESHOLD].value == 24 + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.TEMPERATURE_TARGET: 22, + CharacteristicsTypes.TEMPERATURE_HEATING_THRESHOLD: 20, + CharacteristicsTypes.TEMPERATURE_COOLING_THRESHOLD: 24, + }, + ) async def test_climate_cannot_set_thermostat_temp_range_in_wrong_mode(hass, utcnow): @@ -277,9 +302,14 @@ async def test_climate_cannot_set_thermostat_temp_range_in_wrong_mode(hass, utcn }, blocking=True, ) - assert helper.characteristics[TEMPERATURE_TARGET].value == 22 - assert helper.characteristics[THERMOSTAT_TEMPERATURE_HEATING_THRESHOLD].value == 0 - assert helper.characteristics[THERMOSTAT_TEMPERATURE_COOLING_THRESHOLD].value == 0 + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.TEMPERATURE_TARGET: 22, + CharacteristicsTypes.TEMPERATURE_HEATING_THRESHOLD: 0, + CharacteristicsTypes.TEMPERATURE_COOLING_THRESHOLD: 0, + }, + ) def create_thermostat_single_set_point_auto(accessory): @@ -359,7 +389,12 @@ async def test_climate_set_thermostat_temp_on_sspa_device(hass, utcnow): {"entity_id": "climate.testdevice", "temperature": 21}, blocking=True, ) - assert helper.characteristics[TEMPERATURE_TARGET].value == 21 + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.TEMPERATURE_TARGET: 21, + }, + ) await hass.services.async_call( DOMAIN, @@ -367,7 +402,12 @@ async def test_climate_set_thermostat_temp_on_sspa_device(hass, utcnow): {"entity_id": "climate.testdevice", "hvac_mode": HVAC_MODE_HEAT_COOL}, blocking=True, ) - assert helper.characteristics[TEMPERATURE_TARGET].value == 21 + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.TEMPERATURE_TARGET: 21, + }, + ) await hass.services.async_call( DOMAIN, @@ -378,7 +418,12 @@ async def test_climate_set_thermostat_temp_on_sspa_device(hass, utcnow): }, blocking=True, ) - assert helper.characteristics[TEMPERATURE_TARGET].value == 22 + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.TEMPERATURE_TARGET: 22, + }, + ) async def test_climate_set_mode_via_temp(hass, utcnow): @@ -395,8 +440,13 @@ async def test_climate_set_mode_via_temp(hass, utcnow): }, blocking=True, ) - assert helper.characteristics[TEMPERATURE_TARGET].value == 21 - assert helper.characteristics[HEATING_COOLING_TARGET].value == 1 + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.TEMPERATURE_TARGET: 21, + CharacteristicsTypes.HEATING_COOLING_TARGET: 1, + }, + ) await hass.services.async_call( DOMAIN, @@ -408,8 +458,13 @@ async def test_climate_set_mode_via_temp(hass, utcnow): }, blocking=True, ) - assert helper.characteristics[TEMPERATURE_TARGET].value == 22 - assert helper.characteristics[HEATING_COOLING_TARGET].value == 3 + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.TEMPERATURE_TARGET: 22, + CharacteristicsTypes.HEATING_COOLING_TARGET: 3, + }, + ) async def test_climate_change_thermostat_humidity(hass, utcnow): @@ -422,7 +477,12 @@ async def test_climate_change_thermostat_humidity(hass, utcnow): {"entity_id": "climate.testdevice", "humidity": 50}, blocking=True, ) - assert helper.characteristics[HUMIDITY_TARGET].value == 50 + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.RELATIVE_HUMIDITY_TARGET: 50, + }, + ) await hass.services.async_call( DOMAIN, @@ -430,7 +490,12 @@ async def test_climate_change_thermostat_humidity(hass, utcnow): {"entity_id": "climate.testdevice", "humidity": 45}, blocking=True, ) - assert helper.characteristics[HUMIDITY_TARGET].value == 45 + helper.async_assert_service_values( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.RELATIVE_HUMIDITY_TARGET: 45, + }, + ) async def test_climate_read_thermostat_state(hass, utcnow): @@ -438,12 +503,17 @@ async def test_climate_read_thermostat_state(hass, utcnow): helper = await setup_test_component(hass, create_thermostat_service) # Simulate that heating is on - helper.characteristics[TEMPERATURE_CURRENT].value = 19 - helper.characteristics[TEMPERATURE_TARGET].value = 21 - helper.characteristics[HEATING_COOLING_CURRENT].value = 1 - helper.characteristics[HEATING_COOLING_TARGET].value = 1 - helper.characteristics[HUMIDITY_CURRENT].value = 50 - helper.characteristics[HUMIDITY_TARGET].value = 45 + await helper.async_update( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.TEMPERATURE_CURRENT: 19, + CharacteristicsTypes.TEMPERATURE_TARGET: 21, + CharacteristicsTypes.HEATING_COOLING_CURRENT: 1, + CharacteristicsTypes.HEATING_COOLING_TARGET: 1, + CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT: 50, + CharacteristicsTypes.RELATIVE_HUMIDITY_TARGET: 45, + }, + ) state = await helper.poll_and_get_state() assert state.state == HVAC_MODE_HEAT @@ -453,12 +523,17 @@ async def test_climate_read_thermostat_state(hass, utcnow): assert state.attributes["max_temp"] == 35 # Simulate that cooling is on - helper.characteristics[TEMPERATURE_CURRENT].value = 21 - helper.characteristics[TEMPERATURE_TARGET].value = 19 - helper.characteristics[HEATING_COOLING_CURRENT].value = 2 - helper.characteristics[HEATING_COOLING_TARGET].value = 2 - helper.characteristics[HUMIDITY_CURRENT].value = 45 - helper.characteristics[HUMIDITY_TARGET].value = 45 + await helper.async_update( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.TEMPERATURE_CURRENT: 21, + CharacteristicsTypes.TEMPERATURE_TARGET: 19, + CharacteristicsTypes.HEATING_COOLING_CURRENT: 2, + CharacteristicsTypes.HEATING_COOLING_TARGET: 2, + CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT: 45, + CharacteristicsTypes.RELATIVE_HUMIDITY_TARGET: 45, + }, + ) state = await helper.poll_and_get_state() assert state.state == HVAC_MODE_COOL @@ -466,10 +541,15 @@ async def test_climate_read_thermostat_state(hass, utcnow): assert state.attributes["current_humidity"] == 45 # Simulate that we are in heat/cool mode - helper.characteristics[TEMPERATURE_CURRENT].value = 21 - helper.characteristics[TEMPERATURE_TARGET].value = 21 - helper.characteristics[HEATING_COOLING_CURRENT].value = 0 - helper.characteristics[HEATING_COOLING_TARGET].value = 3 + await helper.async_update( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.TEMPERATURE_CURRENT: 21, + CharacteristicsTypes.TEMPERATURE_TARGET: 21, + CharacteristicsTypes.HEATING_COOLING_CURRENT: 0, + CharacteristicsTypes.HEATING_COOLING_TARGET: 3, + }, + ) state = await helper.poll_and_get_state() assert state.state == HVAC_MODE_HEAT_COOL @@ -481,12 +561,17 @@ async def test_hvac_mode_vs_hvac_action(hass, utcnow): # Simulate that current temperature is above target temp # Heating might be on, but hvac_action currently 'off' - helper.characteristics[TEMPERATURE_CURRENT].value = 22 - helper.characteristics[TEMPERATURE_TARGET].value = 21 - helper.characteristics[HEATING_COOLING_CURRENT].value = 0 - helper.characteristics[HEATING_COOLING_TARGET].value = 1 - helper.characteristics[HUMIDITY_CURRENT].value = 50 - helper.characteristics[HUMIDITY_TARGET].value = 45 + await helper.async_update( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.TEMPERATURE_CURRENT: 22, + CharacteristicsTypes.TEMPERATURE_TARGET: 21, + CharacteristicsTypes.HEATING_COOLING_CURRENT: 0, + CharacteristicsTypes.HEATING_COOLING_TARGET: 1, + CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT: 50, + CharacteristicsTypes.RELATIVE_HUMIDITY_TARGET: 45, + }, + ) state = await helper.poll_and_get_state() assert state.state == "heat" @@ -494,23 +579,19 @@ async def test_hvac_mode_vs_hvac_action(hass, utcnow): # Simulate that current temperature is below target temp # Heating might be on and hvac_action currently 'heat' - helper.characteristics[TEMPERATURE_CURRENT].value = 19 - helper.characteristics[HEATING_COOLING_CURRENT].value = 1 + await helper.async_update( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.TEMPERATURE_CURRENT: 19, + CharacteristicsTypes.HEATING_COOLING_CURRENT: 1, + }, + ) state = await helper.poll_and_get_state() assert state.state == "heat" assert state.attributes["hvac_action"] == "heating" -TARGET_HEATER_COOLER_STATE = ("heater-cooler", "heater-cooler.state.target") -CURRENT_HEATER_COOLER_STATE = ("heater-cooler", "heater-cooler.state.current") -HEATER_COOLER_ACTIVE = ("heater-cooler", "active") -HEATER_COOLER_TEMPERATURE_CURRENT = ("heater-cooler", "temperature.current") -TEMPERATURE_COOLING_THRESHOLD = ("heater-cooler", "temperature.cooling-threshold") -TEMPERATURE_HEATING_THRESHOLD = ("heater-cooler", "temperature.heating-threshold") -SWING_MODE = ("heater-cooler", "swing-mode") - - def create_heater_cooler_service(accessory): """Define thermostat characteristics.""" service = accessory.add_service(ServicesTypes.HEATER_COOLER) @@ -583,10 +664,11 @@ async def test_heater_cooler_change_thermostat_state(hass, utcnow): {"entity_id": "climate.testdevice", "hvac_mode": HVAC_MODE_HEAT}, blocking=True, ) - - assert ( - helper.characteristics[TARGET_HEATER_COOLER_STATE].value - == TargetHeaterCoolerStateValues.HEAT + helper.async_assert_service_values( + ServicesTypes.HEATER_COOLER, + { + CharacteristicsTypes.TARGET_HEATER_COOLER_STATE: TargetHeaterCoolerStateValues.HEAT, + }, ) await hass.services.async_call( @@ -595,9 +677,11 @@ async def test_heater_cooler_change_thermostat_state(hass, utcnow): {"entity_id": "climate.testdevice", "hvac_mode": HVAC_MODE_COOL}, blocking=True, ) - assert ( - helper.characteristics[TARGET_HEATER_COOLER_STATE].value - == TargetHeaterCoolerStateValues.COOL + helper.async_assert_service_values( + ServicesTypes.HEATER_COOLER, + { + CharacteristicsTypes.TARGET_HEATER_COOLER_STATE: TargetHeaterCoolerStateValues.COOL, + }, ) await hass.services.async_call( @@ -606,9 +690,11 @@ async def test_heater_cooler_change_thermostat_state(hass, utcnow): {"entity_id": "climate.testdevice", "hvac_mode": HVAC_MODE_HEAT_COOL}, blocking=True, ) - assert ( - helper.characteristics[TARGET_HEATER_COOLER_STATE].value - == TargetHeaterCoolerStateValues.AUTOMATIC + helper.async_assert_service_values( + ServicesTypes.HEATER_COOLER, + { + CharacteristicsTypes.TARGET_HEATER_COOLER_STATE: TargetHeaterCoolerStateValues.AUTOMATIC, + }, ) await hass.services.async_call( @@ -617,9 +703,11 @@ async def test_heater_cooler_change_thermostat_state(hass, utcnow): {"entity_id": "climate.testdevice", "hvac_mode": HVAC_MODE_OFF}, blocking=True, ) - assert ( - helper.characteristics[HEATER_COOLER_ACTIVE].value - == ActivationStateValues.INACTIVE + helper.async_assert_service_values( + ServicesTypes.HEATER_COOLER, + { + CharacteristicsTypes.ACTIVE: ActivationStateValues.INACTIVE, + }, ) @@ -639,7 +727,12 @@ async def test_heater_cooler_change_thermostat_temperature(hass, utcnow): {"entity_id": "climate.testdevice", "temperature": 20}, blocking=True, ) - assert helper.characteristics[TEMPERATURE_HEATING_THRESHOLD].value == 20 + helper.async_assert_service_values( + ServicesTypes.HEATER_COOLER, + { + CharacteristicsTypes.TEMPERATURE_HEATING_THRESHOLD: 20, + }, + ) await hass.services.async_call( DOMAIN, @@ -653,7 +746,12 @@ async def test_heater_cooler_change_thermostat_temperature(hass, utcnow): {"entity_id": "climate.testdevice", "temperature": 26}, blocking=True, ) - assert helper.characteristics[TEMPERATURE_COOLING_THRESHOLD].value == 26 + helper.async_assert_service_values( + ServicesTypes.HEATER_COOLER, + { + CharacteristicsTypes.TEMPERATURE_COOLING_THRESHOLD: 26, + }, + ) async def test_heater_cooler_read_thermostat_state(hass, utcnow): @@ -661,15 +759,16 @@ async def test_heater_cooler_read_thermostat_state(hass, utcnow): helper = await setup_test_component(hass, create_heater_cooler_service) # Simulate that heating is on - helper.characteristics[HEATER_COOLER_TEMPERATURE_CURRENT].value = 19 - helper.characteristics[TEMPERATURE_HEATING_THRESHOLD].value = 20 - helper.characteristics[ - CURRENT_HEATER_COOLER_STATE - ].value = CurrentHeaterCoolerStateValues.HEATING - helper.characteristics[ - TARGET_HEATER_COOLER_STATE - ].value = TargetHeaterCoolerStateValues.HEAT - helper.characteristics[SWING_MODE].value = SwingModeValues.DISABLED + await helper.async_update( + ServicesTypes.HEATER_COOLER, + { + CharacteristicsTypes.TEMPERATURE_CURRENT: 19, + CharacteristicsTypes.TEMPERATURE_COOLING_THRESHOLD: 21, + CharacteristicsTypes.CURRENT_HEATER_COOLER_STATE: CurrentHeaterCoolerStateValues.HEATING, + CharacteristicsTypes.TARGET_HEATER_COOLER_STATE: TargetHeaterCoolerStateValues.HEAT, + CharacteristicsTypes.SWING_MODE: SwingModeValues.DISABLED, + }, + ) state = await helper.poll_and_get_state() assert state.state == HVAC_MODE_HEAT @@ -678,30 +777,32 @@ async def test_heater_cooler_read_thermostat_state(hass, utcnow): assert state.attributes["max_temp"] == 35 # Simulate that cooling is on - helper.characteristics[HEATER_COOLER_TEMPERATURE_CURRENT].value = 21 - helper.characteristics[TEMPERATURE_COOLING_THRESHOLD].value = 19 - helper.characteristics[ - CURRENT_HEATER_COOLER_STATE - ].value = CurrentHeaterCoolerStateValues.COOLING - helper.characteristics[ - TARGET_HEATER_COOLER_STATE - ].value = TargetHeaterCoolerStateValues.COOL - helper.characteristics[SWING_MODE].value = SwingModeValues.DISABLED + await helper.async_update( + ServicesTypes.HEATER_COOLER, + { + CharacteristicsTypes.TEMPERATURE_CURRENT: 21, + CharacteristicsTypes.TEMPERATURE_COOLING_THRESHOLD: 19, + CharacteristicsTypes.CURRENT_HEATER_COOLER_STATE: CurrentHeaterCoolerStateValues.COOLING, + CharacteristicsTypes.TARGET_HEATER_COOLER_STATE: TargetHeaterCoolerStateValues.COOL, + CharacteristicsTypes.SWING_MODE: SwingModeValues.DISABLED, + }, + ) state = await helper.poll_and_get_state() assert state.state == HVAC_MODE_COOL assert state.attributes["current_temperature"] == 21 # Simulate that we are in auto mode - helper.characteristics[HEATER_COOLER_TEMPERATURE_CURRENT].value = 21 - helper.characteristics[TEMPERATURE_COOLING_THRESHOLD].value = 21 - helper.characteristics[ - CURRENT_HEATER_COOLER_STATE - ].value = CurrentHeaterCoolerStateValues.COOLING - helper.characteristics[ - TARGET_HEATER_COOLER_STATE - ].value = TargetHeaterCoolerStateValues.AUTOMATIC - helper.characteristics[SWING_MODE].value = SwingModeValues.DISABLED + await helper.async_update( + ServicesTypes.HEATER_COOLER, + { + CharacteristicsTypes.TEMPERATURE_CURRENT: 21, + CharacteristicsTypes.TEMPERATURE_COOLING_THRESHOLD: 21, + CharacteristicsTypes.CURRENT_HEATER_COOLER_STATE: CurrentHeaterCoolerStateValues.COOLING, + CharacteristicsTypes.TARGET_HEATER_COOLER_STATE: TargetHeaterCoolerStateValues.AUTOMATIC, + CharacteristicsTypes.SWING_MODE: SwingModeValues.DISABLED, + }, + ) state = await helper.poll_and_get_state() assert state.state == HVAC_MODE_HEAT_COOL @@ -713,15 +814,16 @@ async def test_heater_cooler_hvac_mode_vs_hvac_action(hass, utcnow): # Simulate that current temperature is above target temp # Heating might be on, but hvac_action currently 'off' - helper.characteristics[HEATER_COOLER_TEMPERATURE_CURRENT].value = 22 - helper.characteristics[TEMPERATURE_HEATING_THRESHOLD].value = 21 - helper.characteristics[ - CURRENT_HEATER_COOLER_STATE - ].value = CurrentHeaterCoolerStateValues.IDLE - helper.characteristics[ - TARGET_HEATER_COOLER_STATE - ].value = TargetHeaterCoolerStateValues.HEAT - helper.characteristics[SWING_MODE].value = SwingModeValues.DISABLED + await helper.async_update( + ServicesTypes.HEATER_COOLER, + { + CharacteristicsTypes.TEMPERATURE_CURRENT: 22, + CharacteristicsTypes.TEMPERATURE_HEATING_THRESHOLD: 21, + CharacteristicsTypes.CURRENT_HEATER_COOLER_STATE: CurrentHeaterCoolerStateValues.IDLE, + CharacteristicsTypes.TARGET_HEATER_COOLER_STATE: TargetHeaterCoolerStateValues.HEAT, + CharacteristicsTypes.SWING_MODE: SwingModeValues.DISABLED, + }, + ) state = await helper.poll_and_get_state() assert state.state == "heat" @@ -729,10 +831,16 @@ async def test_heater_cooler_hvac_mode_vs_hvac_action(hass, utcnow): # Simulate that current temperature is below target temp # Heating might be on and hvac_action currently 'heat' - helper.characteristics[HEATER_COOLER_TEMPERATURE_CURRENT].value = 19 - helper.characteristics[ - CURRENT_HEATER_COOLER_STATE - ].value = CurrentHeaterCoolerStateValues.HEATING + await helper.async_update( + ServicesTypes.HEATER_COOLER, + { + CharacteristicsTypes.TEMPERATURE_CURRENT: 19, + CharacteristicsTypes.TEMPERATURE_HEATING_THRESHOLD: 21, + CharacteristicsTypes.CURRENT_HEATER_COOLER_STATE: CurrentHeaterCoolerStateValues.HEATING, + CharacteristicsTypes.TARGET_HEATER_COOLER_STATE: TargetHeaterCoolerStateValues.HEAT, + CharacteristicsTypes.SWING_MODE: SwingModeValues.DISABLED, + }, + ) state = await helper.poll_and_get_state() assert state.state == "heat" @@ -749,7 +857,12 @@ async def test_heater_cooler_change_swing_mode(hass, utcnow): {"entity_id": "climate.testdevice", "swing_mode": "vertical"}, blocking=True, ) - assert helper.characteristics[SWING_MODE].value == SwingModeValues.ENABLED + helper.async_assert_service_values( + ServicesTypes.HEATER_COOLER, + { + CharacteristicsTypes.SWING_MODE: SwingModeValues.ENABLED, + }, + ) await hass.services.async_call( DOMAIN, @@ -757,20 +870,28 @@ async def test_heater_cooler_change_swing_mode(hass, utcnow): {"entity_id": "climate.testdevice", "swing_mode": "off"}, blocking=True, ) - assert helper.characteristics[SWING_MODE].value == SwingModeValues.DISABLED + helper.async_assert_service_values( + ServicesTypes.HEATER_COOLER, + { + CharacteristicsTypes.SWING_MODE: SwingModeValues.DISABLED, + }, + ) async def test_heater_cooler_turn_off(hass, utcnow): """Test that both hvac_action and hvac_mode return "off" when turned off.""" helper = await setup_test_component(hass, create_heater_cooler_service) + # Simulate that the device is turned off but CURRENT_HEATER_COOLER_STATE still returns HEATING/COOLING - helper.characteristics[HEATER_COOLER_ACTIVE].value = ActivationStateValues.INACTIVE - helper.characteristics[ - CURRENT_HEATER_COOLER_STATE - ].value = CurrentHeaterCoolerStateValues.HEATING - helper.characteristics[ - TARGET_HEATER_COOLER_STATE - ].value = TargetHeaterCoolerStateValues.HEAT + await helper.async_update( + ServicesTypes.HEATER_COOLER, + { + CharacteristicsTypes.ACTIVE: ActivationStateValues.INACTIVE, + CharacteristicsTypes.CURRENT_HEATER_COOLER_STATE: CurrentHeaterCoolerStateValues.HEATING, + CharacteristicsTypes.TARGET_HEATER_COOLER_STATE: TargetHeaterCoolerStateValues.HEAT, + }, + ) + state = await helper.poll_and_get_state() assert state.state == "off" assert state.attributes["hvac_action"] == "off" diff --git a/tests/components/homekit_controller/test_cover.py b/tests/components/homekit_controller/test_cover.py index 45514b29122..35e6933f2cd 100644 --- a/tests/components/homekit_controller/test_cover.py +++ b/tests/components/homekit_controller/test_cover.py @@ -4,23 +4,6 @@ from aiohomekit.model.services import ServicesTypes from tests.components.homekit_controller.common import setup_test_component -POSITION_STATE = ("window-covering", "position.state") -POSITION_CURRENT = ("window-covering", "position.current") -POSITION_TARGET = ("window-covering", "position.target") -POSITION_HOLD = ("window-covering", "position.hold") - -H_TILT_CURRENT = ("window-covering", "horizontal-tilt.current") -H_TILT_TARGET = ("window-covering", "horizontal-tilt.target") - -V_TILT_CURRENT = ("window-covering", "vertical-tilt.current") -V_TILT_TARGET = ("window-covering", "vertical-tilt.target") - -WINDOW_OBSTRUCTION = ("window-covering", "obstruction-detected") - -DOOR_CURRENT = ("garage-door-opener", "door-state.current") -DOOR_TARGET = ("garage-door-opener", "door-state.target") -DOOR_OBSTRUCTION = ("garage-door-opener", "obstruction-detected") - def create_window_covering_service(accessory): """Define a window-covering characteristics as per page 219 of HAP spec.""" @@ -76,31 +59,53 @@ async def test_change_window_cover_state(hass, utcnow): await hass.services.async_call( "cover", "open_cover", {"entity_id": helper.entity_id}, blocking=True ) - assert helper.characteristics[POSITION_TARGET].value == 100 + helper.async_assert_service_values( + ServicesTypes.WINDOW_COVERING, + { + CharacteristicsTypes.POSITION_TARGET: 100, + }, + ) await hass.services.async_call( "cover", "close_cover", {"entity_id": helper.entity_id}, blocking=True ) - assert helper.characteristics[POSITION_TARGET].value == 0 + helper.async_assert_service_values( + ServicesTypes.WINDOW_COVERING, + { + CharacteristicsTypes.POSITION_TARGET: 0, + }, + ) async def test_read_window_cover_state(hass, utcnow): """Test that we can read the state of a HomeKit alarm accessory.""" helper = await setup_test_component(hass, create_window_covering_service) - helper.characteristics[POSITION_STATE].value = 0 + await helper.async_update( + ServicesTypes.WINDOW_COVERING, + {CharacteristicsTypes.POSITION_STATE: 0}, + ) state = await helper.poll_and_get_state() assert state.state == "closing" - helper.characteristics[POSITION_STATE].value = 1 + await helper.async_update( + ServicesTypes.WINDOW_COVERING, + {CharacteristicsTypes.POSITION_STATE: 1}, + ) state = await helper.poll_and_get_state() assert state.state == "opening" - helper.characteristics[POSITION_STATE].value = 2 + await helper.async_update( + ServicesTypes.WINDOW_COVERING, + {CharacteristicsTypes.POSITION_STATE: 2}, + ) state = await helper.poll_and_get_state() assert state.state == "closed" - helper.characteristics[WINDOW_OBSTRUCTION].value = True + await helper.async_update( + ServicesTypes.WINDOW_COVERING, + {CharacteristicsTypes.OBSTRUCTION_DETECTED: True}, + ) state = await helper.poll_and_get_state() assert state.attributes["obstruction-detected"] is True @@ -111,7 +116,10 @@ async def test_read_window_cover_tilt_horizontal(hass, utcnow): hass, create_window_covering_service_with_h_tilt ) - helper.characteristics[H_TILT_CURRENT].value = 75 + await helper.async_update( + ServicesTypes.WINDOW_COVERING, + {CharacteristicsTypes.HORIZONTAL_TILT_CURRENT: 75}, + ) state = await helper.poll_and_get_state() assert state.attributes["current_tilt_position"] == 75 @@ -122,7 +130,10 @@ async def test_read_window_cover_tilt_vertical(hass, utcnow): hass, create_window_covering_service_with_v_tilt ) - helper.characteristics[V_TILT_CURRENT].value = 75 + await helper.async_update( + ServicesTypes.WINDOW_COVERING, + {CharacteristicsTypes.VERTICAL_TILT_CURRENT: 75}, + ) state = await helper.poll_and_get_state() assert state.attributes["current_tilt_position"] == 75 @@ -139,7 +150,12 @@ async def test_write_window_cover_tilt_horizontal(hass, utcnow): {"entity_id": helper.entity_id, "tilt_position": 90}, blocking=True, ) - assert helper.characteristics[H_TILT_TARGET].value == 90 + helper.async_assert_service_values( + ServicesTypes.WINDOW_COVERING, + { + CharacteristicsTypes.HORIZONTAL_TILT_TARGET: 90, + }, + ) async def test_write_window_cover_tilt_vertical(hass, utcnow): @@ -154,7 +170,12 @@ async def test_write_window_cover_tilt_vertical(hass, utcnow): {"entity_id": helper.entity_id, "tilt_position": 90}, blocking=True, ) - assert helper.characteristics[V_TILT_TARGET].value == 90 + helper.async_assert_service_values( + ServicesTypes.WINDOW_COVERING, + { + CharacteristicsTypes.VERTICAL_TILT_TARGET: 90, + }, + ) async def test_window_cover_stop(hass, utcnow): @@ -166,7 +187,12 @@ async def test_window_cover_stop(hass, utcnow): await hass.services.async_call( "cover", "stop_cover", {"entity_id": helper.entity_id}, blocking=True ) - assert helper.characteristics[POSITION_HOLD].value == 1 + helper.async_assert_service_values( + ServicesTypes.WINDOW_COVERING, + { + CharacteristicsTypes.POSITION_HOLD: True, + }, + ) def create_garage_door_opener_service(accessory): @@ -195,34 +221,59 @@ async def test_change_door_state(hass, utcnow): await hass.services.async_call( "cover", "open_cover", {"entity_id": helper.entity_id}, blocking=True ) - assert helper.characteristics[DOOR_TARGET].value == 0 + helper.async_assert_service_values( + ServicesTypes.GARAGE_DOOR_OPENER, + { + CharacteristicsTypes.DOOR_STATE_TARGET: 0, + }, + ) await hass.services.async_call( "cover", "close_cover", {"entity_id": helper.entity_id}, blocking=True ) - assert helper.characteristics[DOOR_TARGET].value == 1 + helper.async_assert_service_values( + ServicesTypes.GARAGE_DOOR_OPENER, + { + CharacteristicsTypes.DOOR_STATE_TARGET: 1, + }, + ) async def test_read_door_state(hass, utcnow): """Test that we can read the state of a HomeKit garage door.""" helper = await setup_test_component(hass, create_garage_door_opener_service) - helper.characteristics[DOOR_CURRENT].value = 0 + await helper.async_update( + ServicesTypes.GARAGE_DOOR_OPENER, + {CharacteristicsTypes.DOOR_STATE_CURRENT: 0}, + ) state = await helper.poll_and_get_state() assert state.state == "open" - helper.characteristics[DOOR_CURRENT].value = 1 + await helper.async_update( + ServicesTypes.GARAGE_DOOR_OPENER, + {CharacteristicsTypes.DOOR_STATE_CURRENT: 1}, + ) state = await helper.poll_and_get_state() assert state.state == "closed" - helper.characteristics[DOOR_CURRENT].value = 2 + await helper.async_update( + ServicesTypes.GARAGE_DOOR_OPENER, + {CharacteristicsTypes.DOOR_STATE_CURRENT: 2}, + ) state = await helper.poll_and_get_state() assert state.state == "opening" - helper.characteristics[DOOR_CURRENT].value = 3 + await helper.async_update( + ServicesTypes.GARAGE_DOOR_OPENER, + {CharacteristicsTypes.DOOR_STATE_CURRENT: 3}, + ) state = await helper.poll_and_get_state() assert state.state == "closing" - helper.characteristics[DOOR_OBSTRUCTION].value = True + await helper.async_update( + ServicesTypes.GARAGE_DOOR_OPENER, + {CharacteristicsTypes.OBSTRUCTION_DETECTED: True}, + ) state = await helper.poll_and_get_state() assert state.attributes["obstruction-detected"] is True diff --git a/tests/components/homekit_controller/test_fan.py b/tests/components/homekit_controller/test_fan.py index d66ce81d534..252e7f87bed 100644 --- a/tests/components/homekit_controller/test_fan.py +++ b/tests/components/homekit_controller/test_fan.py @@ -4,15 +4,6 @@ from aiohomekit.model.services import ServicesTypes from tests.components.homekit_controller.common import setup_test_component -V1_ON = ("fan", "on") -V1_ROTATION_DIRECTION = ("fan", "rotation.direction") -V1_ROTATION_SPEED = ("fan", "rotation.speed") - -V2_ACTIVE = ("fanv2", "active") -V2_ROTATION_DIRECTION = ("fanv2", "rotation.direction") -V2_ROTATION_SPEED = ("fanv2", "rotation.speed") -V2_SWING_MODE = ("fanv2", "swing-mode") - def create_fan_service(accessory): """ @@ -86,12 +77,14 @@ async def test_fan_read_state(hass, utcnow): """Test that we can read the state of a HomeKit fan accessory.""" helper = await setup_test_component(hass, create_fan_service) - helper.characteristics[V1_ON].value = False - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN, {CharacteristicsTypes.ON: False} + ) assert state.state == "off" - helper.characteristics[V1_ON].value = True - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN, {CharacteristicsTypes.ON: True} + ) assert state.state == "on" @@ -105,8 +98,13 @@ async def test_turn_on(hass, utcnow): {"entity_id": "fan.testdevice", "speed": "high"}, blocking=True, ) - assert helper.characteristics[V1_ON].value == 1 - assert helper.characteristics[V1_ROTATION_SPEED].value == 100 + helper.async_assert_service_values( + ServicesTypes.FAN, + { + CharacteristicsTypes.ON: 1, + CharacteristicsTypes.ROTATION_SPEED: 100, + }, + ) await hass.services.async_call( "fan", @@ -114,8 +112,13 @@ async def test_turn_on(hass, utcnow): {"entity_id": "fan.testdevice", "speed": "medium"}, blocking=True, ) - assert helper.characteristics[V1_ON].value == 1 - assert helper.characteristics[V1_ROTATION_SPEED].value == 66.0 + helper.async_assert_service_values( + ServicesTypes.FAN, + { + CharacteristicsTypes.ON: 1, + CharacteristicsTypes.ROTATION_SPEED: 66.0, + }, + ) await hass.services.async_call( "fan", @@ -123,8 +126,13 @@ async def test_turn_on(hass, utcnow): {"entity_id": "fan.testdevice", "speed": "low"}, blocking=True, ) - assert helper.characteristics[V1_ON].value == 1 - assert helper.characteristics[V1_ROTATION_SPEED].value == 33.0 + helper.async_assert_service_values( + ServicesTypes.FAN, + { + CharacteristicsTypes.ON: 1, + CharacteristicsTypes.ROTATION_SPEED: 33.0, + }, + ) async def test_turn_on_off_without_rotation_speed(hass, utcnow): @@ -139,7 +147,12 @@ async def test_turn_on_off_without_rotation_speed(hass, utcnow): {"entity_id": "fan.testdevice"}, blocking=True, ) - assert helper.characteristics[V2_ACTIVE].value == 1 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ACTIVE: 1, + }, + ) await hass.services.async_call( "fan", @@ -147,14 +160,19 @@ async def test_turn_on_off_without_rotation_speed(hass, utcnow): {"entity_id": "fan.testdevice"}, blocking=True, ) - assert helper.characteristics[V2_ACTIVE].value == 0 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ACTIVE: 0, + }, + ) async def test_turn_off(hass, utcnow): """Test that we can turn a fan off.""" helper = await setup_test_component(hass, create_fan_service) - helper.characteristics[V1_ON].value = 1 + await helper.async_update(ServicesTypes.FAN, {CharacteristicsTypes.ON: 1}) await hass.services.async_call( "fan", @@ -162,14 +180,19 @@ async def test_turn_off(hass, utcnow): {"entity_id": "fan.testdevice"}, blocking=True, ) - assert helper.characteristics[V1_ON].value == 0 + helper.async_assert_service_values( + ServicesTypes.FAN, + { + CharacteristicsTypes.ON: 0, + }, + ) async def test_set_speed(hass, utcnow): """Test that we set fan speed.""" helper = await setup_test_component(hass, create_fan_service) - helper.characteristics[V1_ON].value = 1 + await helper.async_update(ServicesTypes.FAN, {CharacteristicsTypes.ON: 1}) await hass.services.async_call( "fan", @@ -177,7 +200,12 @@ async def test_set_speed(hass, utcnow): {"entity_id": "fan.testdevice", "speed": "high"}, blocking=True, ) - assert helper.characteristics[V1_ROTATION_SPEED].value == 100 + helper.async_assert_service_values( + ServicesTypes.FAN, + { + CharacteristicsTypes.ROTATION_SPEED: 100.0, + }, + ) await hass.services.async_call( "fan", @@ -185,7 +213,12 @@ async def test_set_speed(hass, utcnow): {"entity_id": "fan.testdevice", "speed": "medium"}, blocking=True, ) - assert helper.characteristics[V1_ROTATION_SPEED].value == 66.0 + helper.async_assert_service_values( + ServicesTypes.FAN, + { + CharacteristicsTypes.ROTATION_SPEED: 66.0, + }, + ) await hass.services.async_call( "fan", @@ -193,7 +226,12 @@ async def test_set_speed(hass, utcnow): {"entity_id": "fan.testdevice", "speed": "low"}, blocking=True, ) - assert helper.characteristics[V1_ROTATION_SPEED].value == 33.0 + helper.async_assert_service_values( + ServicesTypes.FAN, + { + CharacteristicsTypes.ROTATION_SPEED: 33.0, + }, + ) await hass.services.async_call( "fan", @@ -201,14 +239,19 @@ async def test_set_speed(hass, utcnow): {"entity_id": "fan.testdevice", "speed": "off"}, blocking=True, ) - assert helper.characteristics[V1_ON].value == 0 + helper.async_assert_service_values( + ServicesTypes.FAN, + { + CharacteristicsTypes.ON: 0, + }, + ) async def test_set_percentage(hass, utcnow): """Test that we set fan speed by percentage.""" helper = await setup_test_component(hass, create_fan_service) - helper.characteristics[V1_ON].value = 1 + await helper.async_update(ServicesTypes.FAN, {CharacteristicsTypes.ON: 1}) await hass.services.async_call( "fan", @@ -216,7 +259,12 @@ async def test_set_percentage(hass, utcnow): {"entity_id": "fan.testdevice", "percentage": 66}, blocking=True, ) - assert helper.characteristics[V1_ROTATION_SPEED].value == 66 + helper.async_assert_service_values( + ServicesTypes.FAN, + { + CharacteristicsTypes.ROTATION_SPEED: 66, + }, + ) await hass.services.async_call( "fan", @@ -224,33 +272,54 @@ async def test_set_percentage(hass, utcnow): {"entity_id": "fan.testdevice", "percentage": 0}, blocking=True, ) - assert helper.characteristics[V1_ON].value == 0 + helper.async_assert_service_values( + ServicesTypes.FAN, + { + CharacteristicsTypes.ON: 0, + }, + ) async def test_speed_read(hass, utcnow): """Test that we can read a fans oscillation.""" helper = await setup_test_component(hass, create_fan_service) - helper.characteristics[V1_ON].value = 1 - helper.characteristics[V1_ROTATION_SPEED].value = 100 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN, + { + CharacteristicsTypes.ON: 1, + CharacteristicsTypes.ROTATION_SPEED: 100, + }, + ) assert state.attributes["speed"] == "high" assert state.attributes["percentage"] == 100 assert state.attributes["percentage_step"] == 1.0 - helper.characteristics[V1_ROTATION_SPEED].value = 50 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN, + { + CharacteristicsTypes.ROTATION_SPEED: 50, + }, + ) assert state.attributes["speed"] == "medium" assert state.attributes["percentage"] == 50 - helper.characteristics[V1_ROTATION_SPEED].value = 25 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN, + { + CharacteristicsTypes.ROTATION_SPEED: 25, + }, + ) assert state.attributes["speed"] == "low" assert state.attributes["percentage"] == 25 - helper.characteristics[V1_ON].value = 0 - helper.characteristics[V1_ROTATION_SPEED].value = 0 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN, + { + CharacteristicsTypes.ON: 0, + CharacteristicsTypes.ROTATION_SPEED: 0, + }, + ) assert state.attributes["speed"] == "off" assert state.attributes["percentage"] == 0 @@ -265,7 +334,12 @@ async def test_set_direction(hass, utcnow): {"entity_id": "fan.testdevice", "direction": "reverse"}, blocking=True, ) - assert helper.characteristics[V1_ROTATION_DIRECTION].value == 1 + helper.async_assert_service_values( + ServicesTypes.FAN, + { + CharacteristicsTypes.ROTATION_DIRECTION: 1, + }, + ) await hass.services.async_call( "fan", @@ -273,19 +347,26 @@ async def test_set_direction(hass, utcnow): {"entity_id": "fan.testdevice", "direction": "forward"}, blocking=True, ) - assert helper.characteristics[V1_ROTATION_DIRECTION].value == 0 + helper.async_assert_service_values( + ServicesTypes.FAN, + { + CharacteristicsTypes.ROTATION_DIRECTION: 0, + }, + ) async def test_direction_read(hass, utcnow): """Test that we can read a fans oscillation.""" helper = await setup_test_component(hass, create_fan_service) - helper.characteristics[V1_ROTATION_DIRECTION].value = 0 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN, {CharacteristicsTypes.ROTATION_DIRECTION: 0} + ) assert state.attributes["direction"] == "forward" - helper.characteristics[V1_ROTATION_DIRECTION].value = 1 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN, {CharacteristicsTypes.ROTATION_DIRECTION: 1} + ) assert state.attributes["direction"] == "reverse" @@ -293,12 +374,14 @@ async def test_fanv2_read_state(hass, utcnow): """Test that we can read the state of a HomeKit fan accessory.""" helper = await setup_test_component(hass, create_fanv2_service) - helper.characteristics[V2_ACTIVE].value = False - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN_V2, {CharacteristicsTypes.ACTIVE: False} + ) assert state.state == "off" - helper.characteristics[V2_ACTIVE].value = True - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN_V2, {CharacteristicsTypes.ACTIVE: True} + ) assert state.state == "on" @@ -312,8 +395,13 @@ async def test_v2_turn_on(hass, utcnow): {"entity_id": "fan.testdevice", "speed": "high"}, blocking=True, ) - assert helper.characteristics[V2_ACTIVE].value == 1 - assert helper.characteristics[V2_ROTATION_SPEED].value == 100 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ACTIVE: 1, + CharacteristicsTypes.ROTATION_SPEED: 100, + }, + ) await hass.services.async_call( "fan", @@ -321,8 +409,13 @@ async def test_v2_turn_on(hass, utcnow): {"entity_id": "fan.testdevice", "speed": "medium"}, blocking=True, ) - assert helper.characteristics[V2_ACTIVE].value == 1 - assert helper.characteristics[V2_ROTATION_SPEED].value == 66.0 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ACTIVE: 1, + CharacteristicsTypes.ROTATION_SPEED: 66, + }, + ) await hass.services.async_call( "fan", @@ -330,8 +423,13 @@ async def test_v2_turn_on(hass, utcnow): {"entity_id": "fan.testdevice", "speed": "low"}, blocking=True, ) - assert helper.characteristics[V2_ACTIVE].value == 1 - assert helper.characteristics[V2_ROTATION_SPEED].value == 33.0 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ACTIVE: 1, + CharacteristicsTypes.ROTATION_SPEED: 33, + }, + ) await hass.services.async_call( "fan", @@ -339,8 +437,13 @@ async def test_v2_turn_on(hass, utcnow): {"entity_id": "fan.testdevice"}, blocking=True, ) - assert helper.characteristics[V2_ACTIVE].value == 0 - assert helper.characteristics[V2_ROTATION_SPEED].value == 33.0 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ACTIVE: 0, + CharacteristicsTypes.ROTATION_SPEED: 33, + }, + ) await hass.services.async_call( "fan", @@ -348,15 +451,20 @@ async def test_v2_turn_on(hass, utcnow): {"entity_id": "fan.testdevice"}, blocking=True, ) - assert helper.characteristics[V2_ACTIVE].value == 1 - assert helper.characteristics[V2_ROTATION_SPEED].value == 33.0 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ACTIVE: 1, + CharacteristicsTypes.ROTATION_SPEED: 33, + }, + ) async def test_v2_turn_off(hass, utcnow): """Test that we can turn a fan off.""" helper = await setup_test_component(hass, create_fanv2_service) - helper.characteristics[V2_ACTIVE].value = 1 + await helper.async_update(ServicesTypes.FAN_V2, {CharacteristicsTypes.ACTIVE: 1}) await hass.services.async_call( "fan", @@ -364,14 +472,19 @@ async def test_v2_turn_off(hass, utcnow): {"entity_id": "fan.testdevice"}, blocking=True, ) - assert helper.characteristics[V2_ACTIVE].value == 0 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ACTIVE: 0, + }, + ) async def test_v2_set_speed(hass, utcnow): """Test that we set fan speed.""" helper = await setup_test_component(hass, create_fanv2_service) - helper.characteristics[V2_ACTIVE].value = 1 + await helper.async_update(ServicesTypes.FAN_V2, {CharacteristicsTypes.ACTIVE: 1}) await hass.services.async_call( "fan", @@ -379,7 +492,12 @@ async def test_v2_set_speed(hass, utcnow): {"entity_id": "fan.testdevice", "speed": "high"}, blocking=True, ) - assert helper.characteristics[V2_ROTATION_SPEED].value == 100 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ROTATION_SPEED: 100, + }, + ) await hass.services.async_call( "fan", @@ -387,7 +505,12 @@ async def test_v2_set_speed(hass, utcnow): {"entity_id": "fan.testdevice", "speed": "medium"}, blocking=True, ) - assert helper.characteristics[V2_ROTATION_SPEED].value == 66 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ROTATION_SPEED: 66, + }, + ) await hass.services.async_call( "fan", @@ -395,7 +518,12 @@ async def test_v2_set_speed(hass, utcnow): {"entity_id": "fan.testdevice", "speed": "low"}, blocking=True, ) - assert helper.characteristics[V2_ROTATION_SPEED].value == 33 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ROTATION_SPEED: 33, + }, + ) await hass.services.async_call( "fan", @@ -403,14 +531,19 @@ async def test_v2_set_speed(hass, utcnow): {"entity_id": "fan.testdevice", "speed": "off"}, blocking=True, ) - assert helper.characteristics[V2_ACTIVE].value == 0 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ACTIVE: 0, + }, + ) async def test_v2_set_percentage(hass, utcnow): """Test that we set fan speed by percentage.""" helper = await setup_test_component(hass, create_fanv2_service) - helper.characteristics[V2_ACTIVE].value = 1 + await helper.async_update(ServicesTypes.FAN_V2, {CharacteristicsTypes.ACTIVE: 1}) await hass.services.async_call( "fan", @@ -418,7 +551,12 @@ async def test_v2_set_percentage(hass, utcnow): {"entity_id": "fan.testdevice", "percentage": 66}, blocking=True, ) - assert helper.characteristics[V2_ROTATION_SPEED].value == 66 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ROTATION_SPEED: 66, + }, + ) await hass.services.async_call( "fan", @@ -426,14 +564,19 @@ async def test_v2_set_percentage(hass, utcnow): {"entity_id": "fan.testdevice", "percentage": 0}, blocking=True, ) - assert helper.characteristics[V2_ACTIVE].value == 0 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ACTIVE: 0, + }, + ) async def test_v2_set_percentage_with_min_step(hass, utcnow): """Test that we set fan speed by percentage.""" helper = await setup_test_component(hass, create_fanv2_service_with_min_step) - helper.characteristics[V2_ACTIVE].value = 1 + await helper.async_update(ServicesTypes.FAN_V2, {CharacteristicsTypes.ACTIVE: 1}) await hass.services.async_call( "fan", @@ -441,7 +584,12 @@ async def test_v2_set_percentage_with_min_step(hass, utcnow): {"entity_id": "fan.testdevice", "percentage": 66}, blocking=True, ) - assert helper.characteristics[V2_ROTATION_SPEED].value == 75 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ROTATION_SPEED: 75, + }, + ) await hass.services.async_call( "fan", @@ -449,32 +597,53 @@ async def test_v2_set_percentage_with_min_step(hass, utcnow): {"entity_id": "fan.testdevice", "percentage": 0}, blocking=True, ) - assert helper.characteristics[V2_ACTIVE].value == 0 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ACTIVE: 0, + }, + ) async def test_v2_speed_read(hass, utcnow): """Test that we can read a fans oscillation.""" helper = await setup_test_component(hass, create_fanv2_service) - helper.characteristics[V2_ACTIVE].value = 1 - helper.characteristics[V2_ROTATION_SPEED].value = 100 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ACTIVE: 1, + CharacteristicsTypes.ROTATION_SPEED: 100, + }, + ) assert state.attributes["speed"] == "high" assert state.attributes["percentage"] == 100 - helper.characteristics[V2_ROTATION_SPEED].value = 50 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ROTATION_SPEED: 50, + }, + ) assert state.attributes["speed"] == "medium" assert state.attributes["percentage"] == 50 - helper.characteristics[V2_ROTATION_SPEED].value = 25 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ROTATION_SPEED: 25, + }, + ) assert state.attributes["speed"] == "low" assert state.attributes["percentage"] == 25 - helper.characteristics[V2_ACTIVE].value = 0 - helper.characteristics[V2_ROTATION_SPEED].value = 0 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ACTIVE: 0, + CharacteristicsTypes.ROTATION_SPEED: 0, + }, + ) assert state.attributes["speed"] == "off" assert state.attributes["percentage"] == 0 @@ -489,7 +658,12 @@ async def test_v2_set_direction(hass, utcnow): {"entity_id": "fan.testdevice", "direction": "reverse"}, blocking=True, ) - assert helper.characteristics[V2_ROTATION_DIRECTION].value == 1 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ROTATION_DIRECTION: 1, + }, + ) await hass.services.async_call( "fan", @@ -497,19 +671,26 @@ async def test_v2_set_direction(hass, utcnow): {"entity_id": "fan.testdevice", "direction": "forward"}, blocking=True, ) - assert helper.characteristics[V2_ROTATION_DIRECTION].value == 0 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.ROTATION_DIRECTION: 0, + }, + ) async def test_v2_direction_read(hass, utcnow): """Test that we can read a fans oscillation.""" helper = await setup_test_component(hass, create_fanv2_service) - helper.characteristics[V2_ROTATION_DIRECTION].value = 0 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN_V2, {CharacteristicsTypes.ROTATION_DIRECTION: 0} + ) assert state.attributes["direction"] == "forward" - helper.characteristics[V2_ROTATION_DIRECTION].value = 1 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN_V2, {CharacteristicsTypes.ROTATION_DIRECTION: 1} + ) assert state.attributes["direction"] == "reverse" @@ -523,7 +704,12 @@ async def test_v2_oscillate(hass, utcnow): {"entity_id": "fan.testdevice", "oscillating": True}, blocking=True, ) - assert helper.characteristics[V2_SWING_MODE].value == 1 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.SWING_MODE: 1, + }, + ) await hass.services.async_call( "fan", @@ -531,17 +717,24 @@ async def test_v2_oscillate(hass, utcnow): {"entity_id": "fan.testdevice", "oscillating": False}, blocking=True, ) - assert helper.characteristics[V2_SWING_MODE].value == 0 + helper.async_assert_service_values( + ServicesTypes.FAN_V2, + { + CharacteristicsTypes.SWING_MODE: 0, + }, + ) async def test_v2_oscillate_read(hass, utcnow): """Test that we can read a fans oscillation.""" helper = await setup_test_component(hass, create_fanv2_service) - helper.characteristics[V2_SWING_MODE].value = 0 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN_V2, {CharacteristicsTypes.SWING_MODE: 0} + ) assert state.attributes["oscillating"] is False - helper.characteristics[V2_SWING_MODE].value = 1 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.FAN_V2, {CharacteristicsTypes.SWING_MODE: 1} + ) assert state.attributes["oscillating"] is True diff --git a/tests/components/homekit_controller/test_humidifier.py b/tests/components/homekit_controller/test_humidifier.py index 0af795e2ce9..ea32b1931c2 100644 --- a/tests/components/homekit_controller/test_humidifier.py +++ b/tests/components/homekit_controller/test_humidifier.py @@ -7,25 +7,6 @@ from homeassistant.components.humidifier.const import MODE_AUTO, MODE_NORMAL from tests.components.homekit_controller.common import setup_test_component -ACTIVE = ("humidifier-dehumidifier", "active") -CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE = ( - "humidifier-dehumidifier", - "humidifier-dehumidifier.state.current", -) -TARGET_HUMIDIFIER_DEHUMIDIFIER_STATE = ( - "humidifier-dehumidifier", - "humidifier-dehumidifier.state.target", -) -RELATIVE_HUMIDITY_CURRENT = ("humidifier-dehumidifier", "relative-humidity.current") -RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD = ( - "humidifier-dehumidifier", - "relative-humidity.humidifier-threshold", -) -RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD = ( - "humidifier-dehumidifier", - "relative-humidity.dehumidifier-threshold", -) - def create_humidifier_service(accessory): """Define a humidifier characteristics as per page 219 of HAP spec.""" @@ -89,13 +70,19 @@ async def test_humidifier_active_state(hass, utcnow): DOMAIN, "turn_on", {"entity_id": helper.entity_id}, blocking=True ) - assert helper.characteristics[ACTIVE].value == 1 + helper.async_assert_service_values( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + {CharacteristicsTypes.ACTIVE: 1}, + ) await hass.services.async_call( DOMAIN, "turn_off", {"entity_id": helper.entity_id}, blocking=True ) - assert helper.characteristics[ACTIVE].value == 0 + helper.async_assert_service_values( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + {CharacteristicsTypes.ACTIVE: 0}, + ) async def test_dehumidifier_active_state(hass, utcnow): @@ -106,54 +93,85 @@ async def test_dehumidifier_active_state(hass, utcnow): DOMAIN, "turn_on", {"entity_id": helper.entity_id}, blocking=True ) - assert helper.characteristics[ACTIVE].value == 1 + helper.async_assert_service_values( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + {CharacteristicsTypes.ACTIVE: 1}, + ) await hass.services.async_call( DOMAIN, "turn_off", {"entity_id": helper.entity_id}, blocking=True ) - assert helper.characteristics[ACTIVE].value == 0 + helper.async_assert_service_values( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + {CharacteristicsTypes.ACTIVE: 0}, + ) async def test_humidifier_read_humidity(hass, utcnow): """Test that we can read the state of a HomeKit humidifier accessory.""" helper = await setup_test_component(hass, create_humidifier_service) - helper.characteristics[ACTIVE].value = True - helper.characteristics[RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD].value = 75 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.ACTIVE: True, + CharacteristicsTypes.RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD: 75, + }, + ) assert state.state == "on" assert state.attributes["humidity"] == 75 - helper.characteristics[ACTIVE].value = False - helper.characteristics[RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD].value = 10 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.ACTIVE: False, + CharacteristicsTypes.RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD: 10, + }, + ) assert state.state == "off" assert state.attributes["humidity"] == 10 - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 3 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 3, + }, + ) assert state.attributes["humidity"] == 10 + assert state.state == "off" async def test_dehumidifier_read_humidity(hass, utcnow): """Test that we can read the state of a HomeKit dehumidifier accessory.""" helper = await setup_test_component(hass, create_dehumidifier_service) - helper.characteristics[ACTIVE].value = True - helper.characteristics[RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD].value = 75 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.ACTIVE: True, + CharacteristicsTypes.RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD: 75, + }, + ) assert state.state == "on" assert state.attributes["humidity"] == 75 - helper.characteristics[ACTIVE].value = False - helper.characteristics[RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD].value = 40 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.ACTIVE: False, + CharacteristicsTypes.RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD: 40, + }, + ) assert state.state == "off" assert state.attributes["humidity"] == 40 - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 2 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 2, + }, + ) assert state.attributes["humidity"] == 40 @@ -167,7 +185,10 @@ async def test_humidifier_set_humidity(hass, utcnow): {"entity_id": helper.entity_id, "humidity": 20}, blocking=True, ) - assert helper.characteristics[RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD].value == 20 + helper.async_assert_service_values( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + {CharacteristicsTypes.RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD: 20}, + ) async def test_dehumidifier_set_humidity(hass, utcnow): @@ -180,7 +201,10 @@ async def test_dehumidifier_set_humidity(hass, utcnow): {"entity_id": helper.entity_id, "humidity": 20}, blocking=True, ) - assert helper.characteristics[RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD].value == 20 + helper.async_assert_service_values( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + {CharacteristicsTypes.RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD: 20}, + ) async def test_humidifier_set_mode(hass, utcnow): @@ -193,8 +217,13 @@ async def test_humidifier_set_mode(hass, utcnow): {"entity_id": helper.entity_id, "mode": MODE_AUTO}, blocking=True, ) - assert helper.characteristics[TARGET_HUMIDIFIER_DEHUMIDIFIER_STATE].value == 0 - assert helper.characteristics[ACTIVE].value == 1 + helper.async_assert_service_values( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.ACTIVE: 1, + CharacteristicsTypes.TARGET_HUMIDIFIER_DEHUMIDIFIER_STATE: 0, + }, + ) await hass.services.async_call( DOMAIN, @@ -202,8 +231,13 @@ async def test_humidifier_set_mode(hass, utcnow): {"entity_id": helper.entity_id, "mode": MODE_NORMAL}, blocking=True, ) - assert helper.characteristics[TARGET_HUMIDIFIER_DEHUMIDIFIER_STATE].value == 1 - assert helper.characteristics[ACTIVE].value == 1 + helper.async_assert_service_values( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.ACTIVE: 1, + CharacteristicsTypes.TARGET_HUMIDIFIER_DEHUMIDIFIER_STATE: 1, + }, + ) async def test_dehumidifier_set_mode(hass, utcnow): @@ -216,8 +250,13 @@ async def test_dehumidifier_set_mode(hass, utcnow): {"entity_id": helper.entity_id, "mode": MODE_AUTO}, blocking=True, ) - assert helper.characteristics[TARGET_HUMIDIFIER_DEHUMIDIFIER_STATE].value == 0 - assert helper.characteristics[ACTIVE].value == 1 + helper.async_assert_service_values( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.ACTIVE: 1, + CharacteristicsTypes.TARGET_HUMIDIFIER_DEHUMIDIFIER_STATE: 0, + }, + ) await hass.services.async_call( DOMAIN, @@ -225,8 +264,13 @@ async def test_dehumidifier_set_mode(hass, utcnow): {"entity_id": helper.entity_id, "mode": MODE_NORMAL}, blocking=True, ) - assert helper.characteristics[TARGET_HUMIDIFIER_DEHUMIDIFIER_STATE].value == 2 - assert helper.characteristics[ACTIVE].value == 1 + helper.async_assert_service_values( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.ACTIVE: 1, + CharacteristicsTypes.TARGET_HUMIDIFIER_DEHUMIDIFIER_STATE: 2, + }, + ) async def test_humidifier_read_only_mode(hass, utcnow): @@ -236,20 +280,36 @@ async def test_humidifier_read_only_mode(hass, utcnow): state = await helper.poll_and_get_state() assert state.attributes["mode"] == "normal" - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 0 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 0, + }, + ) assert state.attributes["mode"] == "normal" - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 1 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 1, + }, + ) assert state.attributes["mode"] == "auto" - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 2 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 2, + }, + ) assert state.attributes["mode"] == "normal" - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 3 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 3, + }, + ) assert state.attributes["mode"] == "normal" @@ -260,20 +320,36 @@ async def test_dehumidifier_read_only_mode(hass, utcnow): state = await helper.poll_and_get_state() assert state.attributes["mode"] == "normal" - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 0 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 0, + }, + ) assert state.attributes["mode"] == "normal" - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 1 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 1, + }, + ) assert state.attributes["mode"] == "auto" - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 2 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 2, + }, + ) assert state.attributes["mode"] == "normal" - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 3 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 3, + }, + ) assert state.attributes["mode"] == "normal" @@ -281,26 +357,41 @@ async def test_humidifier_target_humidity_modes(hass, utcnow): """Test that we can read the state of a HomeKit humidifier accessory.""" helper = await setup_test_component(hass, create_humidifier_service) - helper.characteristics[RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD].value = 37 - helper.characteristics[RELATIVE_HUMIDITY_CURRENT].value = 51 - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 1 - - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD: 37, + CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT: 51, + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 1, + }, + ) assert state.attributes["mode"] == "auto" assert state.attributes["humidity"] == 37 - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 3 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 3, + }, + ) assert state.attributes["mode"] == "normal" assert state.attributes["humidity"] == 37 - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 2 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 2, + }, + ) assert state.attributes["mode"] == "normal" assert state.attributes["humidity"] == 37 - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 0 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 0, + }, + ) assert state.attributes["mode"] == "normal" assert state.attributes["humidity"] == 37 @@ -309,25 +400,40 @@ async def test_dehumidifier_target_humidity_modes(hass, utcnow): """Test that we can read the state of a HomeKit dehumidifier accessory.""" helper = await setup_test_component(hass, create_dehumidifier_service) - helper.characteristics[RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD].value = 73 - helper.characteristics[RELATIVE_HUMIDITY_CURRENT].value = 51 - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 1 - - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD: 73, + CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT: 51, + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 1, + }, + ) assert state.attributes["mode"] == "auto" assert state.attributes["humidity"] == 73 - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 3 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 3, + }, + ) assert state.attributes["mode"] == "normal" assert state.attributes["humidity"] == 73 - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 2 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 2, + }, + ) assert state.attributes["mode"] == "normal" assert state.attributes["humidity"] == 73 - helper.characteristics[CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE].value = 0 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDIFIER_DEHUMIDIFIER, + { + CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE: 0, + }, + ) assert state.attributes["mode"] == "normal" assert state.attributes["humidity"] == 73 diff --git a/tests/components/homekit_controller/test_light.py b/tests/components/homekit_controller/test_light.py index f4950512063..8d094c4eb70 100644 --- a/tests/components/homekit_controller/test_light.py +++ b/tests/components/homekit_controller/test_light.py @@ -10,12 +10,6 @@ from tests.components.homekit_controller.common import setup_test_component LIGHT_BULB_NAME = "Light Bulb" LIGHT_BULB_ENTITY_ID = "light.testdevice" -LIGHT_ON = ("lightbulb", "on") -LIGHT_BRIGHTNESS = ("lightbulb", "brightness") -LIGHT_HUE = ("lightbulb", "hue") -LIGHT_SATURATION = ("lightbulb", "saturation") -LIGHT_COLOR_TEMP = ("lightbulb", "color-temperature") - def create_lightbulb_service(accessory): """Define lightbulb characteristics.""" @@ -63,16 +57,25 @@ async def test_switch_change_light_state(hass, utcnow): {"entity_id": "light.testdevice", "brightness": 255, "hs_color": [4, 5]}, blocking=True, ) - - assert helper.characteristics[LIGHT_ON].value == 1 - assert helper.characteristics[LIGHT_BRIGHTNESS].value == 100 - assert helper.characteristics[LIGHT_HUE].value == 4 - assert helper.characteristics[LIGHT_SATURATION].value == 5 + helper.async_assert_service_values( + ServicesTypes.LIGHTBULB, + { + CharacteristicsTypes.ON: True, + CharacteristicsTypes.BRIGHTNESS: 100, + CharacteristicsTypes.HUE: 4, + CharacteristicsTypes.SATURATION: 5, + }, + ) await hass.services.async_call( "light", "turn_off", {"entity_id": "light.testdevice"}, blocking=True ) - assert helper.characteristics[LIGHT_ON].value == 0 + helper.async_assert_service_values( + ServicesTypes.LIGHTBULB, + { + CharacteristicsTypes.ON: False, + }, + ) async def test_switch_change_light_state_color_temp(hass, utcnow): @@ -85,9 +88,14 @@ async def test_switch_change_light_state_color_temp(hass, utcnow): {"entity_id": "light.testdevice", "brightness": 255, "color_temp": 400}, blocking=True, ) - assert helper.characteristics[LIGHT_ON].value == 1 - assert helper.characteristics[LIGHT_BRIGHTNESS].value == 100 - assert helper.characteristics[LIGHT_COLOR_TEMP].value == 400 + helper.async_assert_service_values( + ServicesTypes.LIGHTBULB, + { + CharacteristicsTypes.ON: True, + CharacteristicsTypes.BRIGHTNESS: 100, + CharacteristicsTypes.COLOR_TEMPERATURE: 400, + }, + ) async def test_switch_read_light_state(hass, utcnow): @@ -99,18 +107,26 @@ async def test_switch_read_light_state(hass, utcnow): assert state.state == "off" # Simulate that someone switched on the device in the real world not via HA - helper.characteristics[LIGHT_ON].set_value(True) - helper.characteristics[LIGHT_BRIGHTNESS].value = 100 - helper.characteristics[LIGHT_HUE].value = 4 - helper.characteristics[LIGHT_SATURATION].value = 5 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.LIGHTBULB, + { + CharacteristicsTypes.ON: True, + CharacteristicsTypes.BRIGHTNESS: 100, + CharacteristicsTypes.HUE: 4, + CharacteristicsTypes.SATURATION: 5, + }, + ) assert state.state == "on" assert state.attributes["brightness"] == 255 assert state.attributes["hs_color"] == (4, 5) # Simulate that device switched off in the real world not via HA - helper.characteristics[LIGHT_ON].set_value(False) - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.LIGHTBULB, + { + CharacteristicsTypes.ON: False, + }, + ) assert state.state == "off" @@ -122,8 +138,8 @@ async def test_switch_push_light_state(hass, utcnow): state = hass.states.get(LIGHT_BULB_ENTITY_ID) assert state.state == "off" - await helper.update_named_service( - LIGHT_BULB_NAME, + state = await helper.async_update( + ServicesTypes.LIGHTBULB, { CharacteristicsTypes.ON: True, CharacteristicsTypes.BRIGHTNESS: 100, @@ -131,15 +147,17 @@ async def test_switch_push_light_state(hass, utcnow): CharacteristicsTypes.SATURATION: 5, }, ) - - state = hass.states.get(LIGHT_BULB_ENTITY_ID) assert state.state == "on" assert state.attributes["brightness"] == 255 assert state.attributes["hs_color"] == (4, 5) # Simulate that device switched off in the real world not via HA - await helper.update_named_service(LIGHT_BULB_NAME, {CharacteristicsTypes.ON: False}) - state = hass.states.get(LIGHT_BULB_ENTITY_ID) + state = await helper.async_update( + ServicesTypes.LIGHTBULB, + { + CharacteristicsTypes.ON: False, + }, + ) assert state.state == "off" @@ -152,11 +170,14 @@ async def test_switch_read_light_state_color_temp(hass, utcnow): assert state.state == "off" # Simulate that someone switched on the device in the real world not via HA - helper.characteristics[LIGHT_ON].set_value(True) - helper.characteristics[LIGHT_BRIGHTNESS].value = 100 - helper.characteristics[LIGHT_COLOR_TEMP].value = 400 - - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.LIGHTBULB, + { + CharacteristicsTypes.ON: True, + CharacteristicsTypes.BRIGHTNESS: 100, + CharacteristicsTypes.COLOR_TEMPERATURE: 400, + }, + ) assert state.state == "on" assert state.attributes["brightness"] == 255 assert state.attributes["color_temp"] == 400 @@ -170,16 +191,14 @@ async def test_switch_push_light_state_color_temp(hass, utcnow): state = hass.states.get(LIGHT_BULB_ENTITY_ID) assert state.state == "off" - await helper.update_named_service( - LIGHT_BULB_NAME, + state = await helper.async_update( + ServicesTypes.LIGHTBULB, { CharacteristicsTypes.ON: True, CharacteristicsTypes.BRIGHTNESS: 100, CharacteristicsTypes.COLOR_TEMPERATURE: 400, }, ) - - state = hass.states.get(LIGHT_BULB_ENTITY_ID) assert state.state == "on" assert state.attributes["brightness"] == 255 assert state.attributes["color_temp"] == 400 @@ -199,12 +218,15 @@ async def test_light_becomes_unavailable_but_recovers(hass, utcnow): assert state.state == "unavailable" # Simulate that someone switched on the device in the real world not via HA - helper.characteristics[LIGHT_ON].set_value(True) - helper.characteristics[LIGHT_BRIGHTNESS].value = 100 - helper.characteristics[LIGHT_COLOR_TEMP].value = 400 helper.pairing.available = True - - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.LIGHTBULB, + { + CharacteristicsTypes.ON: True, + CharacteristicsTypes.BRIGHTNESS: 100, + CharacteristicsTypes.COLOR_TEMPERATURE: 400, + }, + ) assert state.state == "on" assert state.attributes["brightness"] == 255 assert state.attributes["color_temp"] == 400 diff --git a/tests/components/homekit_controller/test_lock.py b/tests/components/homekit_controller/test_lock.py index 15e645bf181..8f996cea8e3 100644 --- a/tests/components/homekit_controller/test_lock.py +++ b/tests/components/homekit_controller/test_lock.py @@ -4,9 +4,6 @@ from aiohomekit.model.services import ServicesTypes from tests.components.homekit_controller.common import setup_test_component -LOCK_CURRENT_STATE = ("lock-mechanism", "lock-mechanism.current-state") -LOCK_TARGET_STATE = ("lock-mechanism", "lock-mechanism.target-state") - def create_lock_service(accessory): """Define a lock characteristics as per page 219 of HAP spec.""" @@ -35,45 +32,83 @@ async def test_switch_change_lock_state(hass, utcnow): await hass.services.async_call( "lock", "lock", {"entity_id": "lock.testdevice"}, blocking=True ) - assert helper.characteristics[LOCK_TARGET_STATE].value == 1 + helper.async_assert_service_values( + ServicesTypes.LOCK_MECHANISM, + { + CharacteristicsTypes.LOCK_MECHANISM_TARGET_STATE: 1, + }, + ) await hass.services.async_call( "lock", "unlock", {"entity_id": "lock.testdevice"}, blocking=True ) - assert helper.characteristics[LOCK_TARGET_STATE].value == 0 + helper.async_assert_service_values( + ServicesTypes.LOCK_MECHANISM, + { + CharacteristicsTypes.LOCK_MECHANISM_TARGET_STATE: 0, + }, + ) async def test_switch_read_lock_state(hass, utcnow): """Test that we can read the state of a HomeKit lock accessory.""" helper = await setup_test_component(hass, create_lock_service) - helper.characteristics[LOCK_CURRENT_STATE].value = 0 - helper.characteristics[LOCK_TARGET_STATE].value = 0 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.LOCK_MECHANISM, + { + CharacteristicsTypes.LOCK_MECHANISM_CURRENT_STATE: 0, + CharacteristicsTypes.LOCK_MECHANISM_TARGET_STATE: 0, + }, + ) assert state.state == "unlocked" assert state.attributes["battery_level"] == 50 - helper.characteristics[LOCK_CURRENT_STATE].value = 1 - helper.characteristics[LOCK_TARGET_STATE].value = 1 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.LOCK_MECHANISM, + { + CharacteristicsTypes.LOCK_MECHANISM_CURRENT_STATE: 1, + CharacteristicsTypes.LOCK_MECHANISM_TARGET_STATE: 1, + }, + ) assert state.state == "locked" - helper.characteristics[LOCK_CURRENT_STATE].value = 2 - helper.characteristics[LOCK_TARGET_STATE].value = 1 + await helper.async_update( + ServicesTypes.LOCK_MECHANISM, + { + CharacteristicsTypes.LOCK_MECHANISM_CURRENT_STATE: 2, + CharacteristicsTypes.LOCK_MECHANISM_TARGET_STATE: 1, + }, + ) state = await helper.poll_and_get_state() assert state.state == "jammed" - helper.characteristics[LOCK_CURRENT_STATE].value = 3 - helper.characteristics[LOCK_TARGET_STATE].value = 1 + await helper.async_update( + ServicesTypes.LOCK_MECHANISM, + { + CharacteristicsTypes.LOCK_MECHANISM_CURRENT_STATE: 3, + CharacteristicsTypes.LOCK_MECHANISM_TARGET_STATE: 1, + }, + ) state = await helper.poll_and_get_state() assert state.state == "unknown" - helper.characteristics[LOCK_CURRENT_STATE].value = 0 - helper.characteristics[LOCK_TARGET_STATE].value = 1 + await helper.async_update( + ServicesTypes.LOCK_MECHANISM, + { + CharacteristicsTypes.LOCK_MECHANISM_CURRENT_STATE: 0, + CharacteristicsTypes.LOCK_MECHANISM_TARGET_STATE: 1, + }, + ) state = await helper.poll_and_get_state() assert state.state == "locking" - helper.characteristics[LOCK_CURRENT_STATE].value = 1 - helper.characteristics[LOCK_TARGET_STATE].value = 0 + await helper.async_update( + ServicesTypes.LOCK_MECHANISM, + { + CharacteristicsTypes.LOCK_MECHANISM_CURRENT_STATE: 1, + CharacteristicsTypes.LOCK_MECHANISM_TARGET_STATE: 0, + }, + ) state = await helper.poll_and_get_state() assert state.state == "unlocking" diff --git a/tests/components/homekit_controller/test_media_player.py b/tests/components/homekit_controller/test_media_player.py index 44c53af02da..d45e785f315 100644 --- a/tests/components/homekit_controller/test_media_player.py +++ b/tests/components/homekit_controller/test_media_player.py @@ -8,11 +8,6 @@ import pytest from tests.components.homekit_controller.common import setup_test_component -CURRENT_MEDIA_STATE = ("television", "current-media-state") -TARGET_MEDIA_STATE = ("television", "target-media-state") -REMOTE_KEY = ("television", "remote-key") -ACTIVE_IDENTIFIER = ("television", "active-identifier") - def create_tv_service(accessory): """ @@ -26,10 +21,12 @@ def create_tv_service(accessory): cur_state = tv_service.add_char(CharacteristicsTypes.CURRENT_MEDIA_STATE) cur_state.value = 0 + cur_state.perms.append(CharacteristicPermissions.events) remote = tv_service.add_char(CharacteristicsTypes.REMOTE_KEY) remote.value = None remote.perms.append(CharacteristicPermissions.paired_write) + remote.perms.append(CharacteristicPermissions.events) # Add a HDMI 1 channel input_source_1 = accessory.add_service(ServicesTypes.INPUT_SOURCE) @@ -66,16 +63,28 @@ async def test_tv_read_state(hass, utcnow): """Test that we can read the state of a HomeKit fan accessory.""" helper = await setup_test_component(hass, create_tv_service) - helper.characteristics[CURRENT_MEDIA_STATE].value = 0 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.CURRENT_MEDIA_STATE: 0, + }, + ) assert state.state == "playing" - helper.characteristics[CURRENT_MEDIA_STATE].value = 1 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.CURRENT_MEDIA_STATE: 1, + }, + ) assert state.state == "paused" - helper.characteristics[CURRENT_MEDIA_STATE].value = 2 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.CURRENT_MEDIA_STATE: 2, + }, + ) assert state.state == "idle" @@ -92,8 +101,12 @@ async def test_play_remote_key(hass, utcnow): """Test that we can play media on a media player.""" helper = await setup_test_component(hass, create_tv_service) - helper.characteristics[CURRENT_MEDIA_STATE].value = 1 - await helper.poll_and_get_state() + await helper.async_update( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.CURRENT_MEDIA_STATE: 1, + }, + ) await hass.services.async_call( "media_player", @@ -101,28 +114,46 @@ async def test_play_remote_key(hass, utcnow): {"entity_id": "media_player.testdevice"}, blocking=True, ) - assert helper.characteristics[REMOTE_KEY].value == 11 + helper.async_assert_service_values( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.REMOTE_KEY: 11, + }, + ) # Second time should be a no-op - helper.characteristics[CURRENT_MEDIA_STATE].value = 0 - await helper.poll_and_get_state() + await helper.async_update( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.CURRENT_MEDIA_STATE: 0, + CharacteristicsTypes.REMOTE_KEY: None, + }, + ) - helper.characteristics[REMOTE_KEY].value = None await hass.services.async_call( "media_player", "media_play", {"entity_id": "media_player.testdevice"}, blocking=True, ) - assert helper.characteristics[REMOTE_KEY].value is None + helper.async_assert_service_values( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.REMOTE_KEY: None, + }, + ) async def test_pause_remote_key(hass, utcnow): """Test that we can pause a media player.""" helper = await setup_test_component(hass, create_tv_service) - helper.characteristics[CURRENT_MEDIA_STATE].value = 0 - await helper.poll_and_get_state() + await helper.async_update( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.CURRENT_MEDIA_STATE: 0, + }, + ) await hass.services.async_call( "media_player", @@ -130,28 +161,46 @@ async def test_pause_remote_key(hass, utcnow): {"entity_id": "media_player.testdevice"}, blocking=True, ) - assert helper.characteristics[REMOTE_KEY].value == 11 + helper.async_assert_service_values( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.REMOTE_KEY: 11, + }, + ) # Second time should be a no-op - helper.characteristics[CURRENT_MEDIA_STATE].value = 1 - await helper.poll_and_get_state() + await helper.async_update( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.CURRENT_MEDIA_STATE: 1, + CharacteristicsTypes.REMOTE_KEY: None, + }, + ) - helper.characteristics[REMOTE_KEY].value = None await hass.services.async_call( "media_player", "media_pause", {"entity_id": "media_player.testdevice"}, blocking=True, ) - assert helper.characteristics[REMOTE_KEY].value is None + helper.async_assert_service_values( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.REMOTE_KEY: None, + }, + ) async def test_play(hass, utcnow): """Test that we can play media on a media player.""" helper = await setup_test_component(hass, create_tv_service_with_target_media_state) - helper.characteristics[CURRENT_MEDIA_STATE].value = 1 - await helper.poll_and_get_state() + await helper.async_update( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.CURRENT_MEDIA_STATE: 1, + }, + ) await hass.services.async_call( "media_player", @@ -159,30 +208,48 @@ async def test_play(hass, utcnow): {"entity_id": "media_player.testdevice"}, blocking=True, ) - assert helper.characteristics[REMOTE_KEY].value is None - assert helper.characteristics[TARGET_MEDIA_STATE].value == 0 + helper.async_assert_service_values( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.REMOTE_KEY: None, + CharacteristicsTypes.TARGET_MEDIA_STATE: 0, + }, + ) # Second time should be a no-op - helper.characteristics[CURRENT_MEDIA_STATE].value = 0 - await helper.poll_and_get_state() + await helper.async_update( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.CURRENT_MEDIA_STATE: 0, + CharacteristicsTypes.TARGET_MEDIA_STATE: None, + }, + ) - helper.characteristics[TARGET_MEDIA_STATE].value = None await hass.services.async_call( "media_player", "media_play", {"entity_id": "media_player.testdevice"}, blocking=True, ) - assert helper.characteristics[REMOTE_KEY].value is None - assert helper.characteristics[TARGET_MEDIA_STATE].value is None + helper.async_assert_service_values( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.REMOTE_KEY: None, + CharacteristicsTypes.TARGET_MEDIA_STATE: None, + }, + ) async def test_pause(hass, utcnow): """Test that we can turn pause a media player.""" helper = await setup_test_component(hass, create_tv_service_with_target_media_state) - helper.characteristics[CURRENT_MEDIA_STATE].value = 0 - await helper.poll_and_get_state() + await helper.async_update( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.CURRENT_MEDIA_STATE: 0, + }, + ) await hass.services.async_call( "media_player", @@ -190,21 +257,35 @@ async def test_pause(hass, utcnow): {"entity_id": "media_player.testdevice"}, blocking=True, ) - assert helper.characteristics[REMOTE_KEY].value is None - assert helper.characteristics[TARGET_MEDIA_STATE].value == 1 + helper.async_assert_service_values( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.REMOTE_KEY: None, + CharacteristicsTypes.TARGET_MEDIA_STATE: 1, + }, + ) # Second time should be a no-op - helper.characteristics[CURRENT_MEDIA_STATE].value = 1 - await helper.poll_and_get_state() + await helper.async_update( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.CURRENT_MEDIA_STATE: 1, + CharacteristicsTypes.REMOTE_KEY: None, + }, + ) - helper.characteristics[REMOTE_KEY].value = None await hass.services.async_call( "media_player", "media_pause", {"entity_id": "media_player.testdevice"}, blocking=True, ) - assert helper.characteristics[REMOTE_KEY].value is None + helper.async_assert_service_values( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.REMOTE_KEY: None, + }, + ) async def test_stop(hass, utcnow): @@ -217,21 +298,35 @@ async def test_stop(hass, utcnow): {"entity_id": "media_player.testdevice"}, blocking=True, ) - assert helper.characteristics[TARGET_MEDIA_STATE].value == 2 + helper.async_assert_service_values( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.TARGET_MEDIA_STATE: 2, + }, + ) # Second time should be a no-op - helper.characteristics[CURRENT_MEDIA_STATE].value = 2 - await helper.poll_and_get_state() + await helper.async_update( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.CURRENT_MEDIA_STATE: 2, + CharacteristicsTypes.TARGET_MEDIA_STATE: None, + }, + ) - helper.characteristics[TARGET_MEDIA_STATE].value = None await hass.services.async_call( "media_player", "media_stop", {"entity_id": "media_player.testdevice"}, blocking=True, ) - assert helper.characteristics[REMOTE_KEY].value is None - assert helper.characteristics[TARGET_MEDIA_STATE].value is None + helper.async_assert_service_values( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.REMOTE_KEY: None, + CharacteristicsTypes.TARGET_MEDIA_STATE: None, + }, + ) async def test_tv_set_source(hass, utcnow): @@ -244,7 +339,12 @@ async def test_tv_set_source(hass, utcnow): {"entity_id": "media_player.testdevice", "source": "HDMI 2"}, blocking=True, ) - assert helper.characteristics[ACTIVE_IDENTIFIER].value == 2 + helper.async_assert_service_values( + ServicesTypes.TELEVISION, + { + CharacteristicsTypes.ACTIVE_IDENTIFIER: 2, + }, + ) state = await helper.poll_and_get_state() assert state.attributes["source"] == "HDMI 2" diff --git a/tests/components/homekit_controller/test_number.py b/tests/components/homekit_controller/test_number.py index d83b4195241..a8a40bfa732 100644 --- a/tests/components/homekit_controller/test_number.py +++ b/tests/components/homekit_controller/test_number.py @@ -13,6 +13,7 @@ def create_switch_with_spray_level(accessory): CharacteristicsTypes.Vendor.VOCOLINC_HUMIDIFIER_SPRAY_LEVEL ) + spray_level.perms.append("ev") spray_level.value = 1 spray_level.minStep = 1 spray_level.minValue = 1 @@ -48,10 +49,9 @@ def create_switch_with_ecobee_fan_mode(accessory): async def test_read_number(hass, utcnow): """Test a switch service that has a sensor characteristic is correctly handled.""" helper = await setup_test_component(hass, create_switch_with_spray_level) - outlet = helper.accessory.services.first(service_type=ServicesTypes.OUTLET) # Helper will be for the primary entity, which is the outlet. Make a helper for the sensor. - energy_helper = Helper( + spray_level = Helper( hass, "number.testdevice_spray_quantity", helper.pairing, @@ -59,27 +59,25 @@ async def test_read_number(hass, utcnow): helper.config_entry, ) - outlet = energy_helper.accessory.services.first(service_type=ServicesTypes.OUTLET) - spray_level = outlet[CharacteristicsTypes.Vendor.VOCOLINC_HUMIDIFIER_SPRAY_LEVEL] - - state = await energy_helper.poll_and_get_state() + state = await spray_level.poll_and_get_state() assert state.state == "1" assert state.attributes["step"] == 1 assert state.attributes["min"] == 1 assert state.attributes["max"] == 5 - spray_level.value = 5 - state = await energy_helper.poll_and_get_state() + state = await spray_level.async_update( + ServicesTypes.OUTLET, + {CharacteristicsTypes.Vendor.VOCOLINC_HUMIDIFIER_SPRAY_LEVEL: 5}, + ) assert state.state == "5" async def test_write_number(hass, utcnow): """Test a switch service that has a sensor characteristic is correctly handled.""" helper = await setup_test_component(hass, create_switch_with_spray_level) - outlet = helper.accessory.services.first(service_type=ServicesTypes.OUTLET) # Helper will be for the primary entity, which is the outlet. Make a helper for the sensor. - energy_helper = Helper( + spray_level = Helper( hass, "number.testdevice_spray_quantity", helper.pairing, @@ -87,16 +85,16 @@ async def test_write_number(hass, utcnow): helper.config_entry, ) - outlet = energy_helper.accessory.services.first(service_type=ServicesTypes.OUTLET) - spray_level = outlet[CharacteristicsTypes.Vendor.VOCOLINC_HUMIDIFIER_SPRAY_LEVEL] - await hass.services.async_call( "number", "set_value", {"entity_id": "number.testdevice_spray_quantity", "value": 5}, blocking=True, ) - assert spray_level.value == 5 + spray_level.async_assert_service_values( + ServicesTypes.OUTLET, + {CharacteristicsTypes.Vendor.VOCOLINC_HUMIDIFIER_SPRAY_LEVEL: 5}, + ) await hass.services.async_call( "number", @@ -104,16 +102,18 @@ async def test_write_number(hass, utcnow): {"entity_id": "number.testdevice_spray_quantity", "value": 3}, blocking=True, ) - assert spray_level.value == 3 + spray_level.async_assert_service_values( + ServicesTypes.OUTLET, + {CharacteristicsTypes.Vendor.VOCOLINC_HUMIDIFIER_SPRAY_LEVEL: 3}, + ) async def test_write_ecobee_fan_mode_number(hass, utcnow): """Test a switch service that has a sensor characteristic is correctly handled.""" helper = await setup_test_component(hass, create_switch_with_ecobee_fan_mode) - outlet = helper.accessory.services.first(service_type=ServicesTypes.OUTLET) # Helper will be for the primary entity, which is the outlet. Make a helper for the sensor. - energy_helper = Helper( + fan_mode = Helper( hass, "number.testdevice_fan_mode", helper.pairing, @@ -121,16 +121,16 @@ async def test_write_ecobee_fan_mode_number(hass, utcnow): helper.config_entry, ) - outlet = energy_helper.accessory.services.first(service_type=ServicesTypes.OUTLET) - ecobee_fan_mode = outlet[CharacteristicsTypes.Vendor.ECOBEE_FAN_WRITE_SPEED] - await hass.services.async_call( "number", "set_value", {"entity_id": "number.testdevice_fan_mode", "value": 1}, blocking=True, ) - assert ecobee_fan_mode.value == 1 + fan_mode.async_assert_service_values( + ServicesTypes.OUTLET, + {CharacteristicsTypes.Vendor.ECOBEE_FAN_WRITE_SPEED: 1}, + ) await hass.services.async_call( "number", @@ -138,7 +138,10 @@ async def test_write_ecobee_fan_mode_number(hass, utcnow): {"entity_id": "number.testdevice_fan_mode", "value": 2}, blocking=True, ) - assert ecobee_fan_mode.value == 2 + fan_mode.async_assert_service_values( + ServicesTypes.OUTLET, + {CharacteristicsTypes.Vendor.ECOBEE_FAN_WRITE_SPEED: 2}, + ) await hass.services.async_call( "number", @@ -146,7 +149,10 @@ async def test_write_ecobee_fan_mode_number(hass, utcnow): {"entity_id": "number.testdevice_fan_mode", "value": 99}, blocking=True, ) - assert ecobee_fan_mode.value == 99 + fan_mode.async_assert_service_values( + ServicesTypes.OUTLET, + {CharacteristicsTypes.Vendor.ECOBEE_FAN_WRITE_SPEED: 99}, + ) await hass.services.async_call( "number", @@ -154,7 +160,10 @@ async def test_write_ecobee_fan_mode_number(hass, utcnow): {"entity_id": "number.testdevice_fan_mode", "value": 100}, blocking=True, ) - assert ecobee_fan_mode.value == 100 + fan_mode.async_assert_service_values( + ServicesTypes.OUTLET, + {CharacteristicsTypes.Vendor.ECOBEE_FAN_WRITE_SPEED: 100}, + ) await hass.services.async_call( "number", @@ -162,4 +171,7 @@ async def test_write_ecobee_fan_mode_number(hass, utcnow): {"entity_id": "number.testdevice_fan_mode", "value": 0}, blocking=True, ) - assert ecobee_fan_mode.value == 0 + fan_mode.async_assert_service_values( + ServicesTypes.OUTLET, + {CharacteristicsTypes.Vendor.ECOBEE_FAN_WRITE_SPEED: 0}, + ) diff --git a/tests/components/homekit_controller/test_select.py b/tests/components/homekit_controller/test_select.py index ea22bf68c54..6cc7f5336b4 100644 --- a/tests/components/homekit_controller/test_select.py +++ b/tests/components/homekit_controller/test_select.py @@ -12,6 +12,7 @@ def create_service_with_ecobee_mode(accessory: Accessory): current_mode = service.add_char(CharacteristicsTypes.Vendor.ECOBEE_CURRENT_MODE) current_mode.value = 0 + current_mode.perms.append("ev") service.add_char(CharacteristicsTypes.Vendor.ECOBEE_SET_HOLD_SCHEDULE) @@ -21,10 +22,9 @@ def create_service_with_ecobee_mode(accessory: Accessory): async def test_read_current_mode(hass, utcnow): """Test that Ecobee mode can be correctly read and show as human readable text.""" helper = await setup_test_component(hass, create_service_with_ecobee_mode) - service = helper.accessory.services.first(service_type=ServicesTypes.THERMOSTAT) # Helper will be for the primary entity, which is the service. Make a helper for the sensor. - energy_helper = Helper( + ecobee_mode = Helper( hass, "select.testdevice_current_mode", helper.pairing, @@ -32,27 +32,38 @@ async def test_read_current_mode(hass, utcnow): helper.config_entry, ) - mode = service[CharacteristicsTypes.Vendor.ECOBEE_CURRENT_MODE] - - state = await energy_helper.poll_and_get_state() + state = await ecobee_mode.async_update( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.Vendor.ECOBEE_CURRENT_MODE: 0, + }, + ) assert state.state == "home" - mode.value = 1 - state = await energy_helper.poll_and_get_state() + state = await ecobee_mode.async_update( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.Vendor.ECOBEE_CURRENT_MODE: 1, + }, + ) assert state.state == "sleep" - mode.value = 2 - state = await energy_helper.poll_and_get_state() + state = await ecobee_mode.async_update( + ServicesTypes.THERMOSTAT, + { + CharacteristicsTypes.Vendor.ECOBEE_CURRENT_MODE: 2, + }, + ) assert state.state == "away" async def test_write_current_mode(hass, utcnow): """Test can set a specific mode.""" helper = await setup_test_component(hass, create_service_with_ecobee_mode) - service = helper.accessory.services.first(service_type=ServicesTypes.THERMOSTAT) + helper.accessory.services.first(service_type=ServicesTypes.THERMOSTAT) # Helper will be for the primary entity, which is the service. Make a helper for the sensor. - energy_helper = Helper( + current_mode = Helper( hass, "select.testdevice_current_mode", helper.pairing, @@ -60,18 +71,16 @@ async def test_write_current_mode(hass, utcnow): helper.config_entry, ) - service = energy_helper.accessory.services.first( - service_type=ServicesTypes.THERMOSTAT - ) - mode = service[CharacteristicsTypes.Vendor.ECOBEE_SET_HOLD_SCHEDULE] - await hass.services.async_call( "select", "select_option", {"entity_id": "select.testdevice_current_mode", "option": "home"}, blocking=True, ) - assert mode.value == 0 + current_mode.async_assert_service_values( + ServicesTypes.THERMOSTAT, + {CharacteristicsTypes.Vendor.ECOBEE_SET_HOLD_SCHEDULE: 0}, + ) await hass.services.async_call( "select", @@ -79,7 +88,10 @@ async def test_write_current_mode(hass, utcnow): {"entity_id": "select.testdevice_current_mode", "option": "sleep"}, blocking=True, ) - assert mode.value == 1 + current_mode.async_assert_service_values( + ServicesTypes.THERMOSTAT, + {CharacteristicsTypes.Vendor.ECOBEE_SET_HOLD_SCHEDULE: 1}, + ) await hass.services.async_call( "select", @@ -87,4 +99,7 @@ async def test_write_current_mode(hass, utcnow): {"entity_id": "select.testdevice_current_mode", "option": "away"}, blocking=True, ) - assert mode.value == 2 + current_mode.async_assert_service_values( + ServicesTypes.THERMOSTAT, + {CharacteristicsTypes.Vendor.ECOBEE_SET_HOLD_SCHEDULE: 2}, + ) diff --git a/tests/components/homekit_controller/test_sensor.py b/tests/components/homekit_controller/test_sensor.py index 4c57d94b2b8..fc1a48f0f5d 100644 --- a/tests/components/homekit_controller/test_sensor.py +++ b/tests/components/homekit_controller/test_sensor.py @@ -7,15 +7,6 @@ from homeassistant.components.sensor import SensorDeviceClass from tests.components.homekit_controller.common import Helper, setup_test_component -TEMPERATURE = ("temperature", "temperature.current") -HUMIDITY = ("humidity", "relative-humidity.current") -LIGHT_LEVEL = ("light", "light-level.current") -CARBON_DIOXIDE_LEVEL = ("carbon-dioxide", "carbon-dioxide.level") -BATTERY_LEVEL = ("battery", "battery-level") -CHARGING_STATE = ("battery", "charging-state") -LO_BATT = ("battery", "status-lo-batt") -ON = ("outlet", "on") - def create_temperature_sensor_service(accessory): """Define temperature characteristics.""" @@ -71,12 +62,20 @@ async def test_temperature_sensor_read_state(hass, utcnow): hass, create_temperature_sensor_service, suffix="temperature" ) - helper.characteristics[TEMPERATURE].value = 10 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.TEMPERATURE_SENSOR, + { + CharacteristicsTypes.TEMPERATURE_CURRENT: 10, + }, + ) assert state.state == "10" - helper.characteristics[TEMPERATURE].value = 20 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.TEMPERATURE_SENSOR, + { + CharacteristicsTypes.TEMPERATURE_CURRENT: 20, + }, + ) assert state.state == "20" assert state.attributes["device_class"] == SensorDeviceClass.TEMPERATURE @@ -100,12 +99,20 @@ async def test_humidity_sensor_read_state(hass, utcnow): hass, create_humidity_sensor_service, suffix="humidity" ) - helper.characteristics[HUMIDITY].value = 10 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDITY_SENSOR, + { + CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT: 10, + }, + ) assert state.state == "10" - helper.characteristics[HUMIDITY].value = 20 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.HUMIDITY_SENSOR, + { + CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT: 20, + }, + ) assert state.state == "20" assert state.attributes["device_class"] == SensorDeviceClass.HUMIDITY @@ -117,12 +124,20 @@ async def test_light_level_sensor_read_state(hass, utcnow): hass, create_light_level_sensor_service, suffix="light_level" ) - helper.characteristics[LIGHT_LEVEL].value = 10 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.LIGHT_SENSOR, + { + CharacteristicsTypes.LIGHT_LEVEL_CURRENT: 10, + }, + ) assert state.state == "10" - helper.characteristics[LIGHT_LEVEL].value = 20 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.LIGHT_SENSOR, + { + CharacteristicsTypes.LIGHT_LEVEL_CURRENT: 20, + }, + ) assert state.state == "20" assert state.attributes["device_class"] == SensorDeviceClass.ILLUMINANCE @@ -134,12 +149,20 @@ async def test_carbon_dioxide_level_sensor_read_state(hass, utcnow): hass, create_carbon_dioxide_level_sensor_service, suffix="co2" ) - helper.characteristics[CARBON_DIOXIDE_LEVEL].value = 10 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.CARBON_DIOXIDE_SENSOR, + { + CharacteristicsTypes.CARBON_DIOXIDE_LEVEL: 10, + }, + ) assert state.state == "10" - helper.characteristics[CARBON_DIOXIDE_LEVEL].value = 20 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.CARBON_DIOXIDE_SENSOR, + { + CharacteristicsTypes.CARBON_DIOXIDE_LEVEL: 20, + }, + ) assert state.state == "20" @@ -149,13 +172,21 @@ async def test_battery_level_sensor(hass, utcnow): hass, create_battery_level_sensor, suffix="battery" ) - helper.characteristics[BATTERY_LEVEL].value = 100 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.BATTERY_SERVICE, + { + CharacteristicsTypes.BATTERY_LEVEL: 100, + }, + ) assert state.state == "100" assert state.attributes["icon"] == "mdi:battery" - helper.characteristics[BATTERY_LEVEL].value = 20 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.BATTERY_SERVICE, + { + CharacteristicsTypes.BATTERY_LEVEL: 20, + }, + ) assert state.state == "20" assert state.attributes["icon"] == "mdi:battery-20" @@ -168,13 +199,21 @@ async def test_battery_charging(hass, utcnow): hass, create_battery_level_sensor, suffix="battery" ) - helper.characteristics[BATTERY_LEVEL].value = 0 - helper.characteristics[CHARGING_STATE].value = 1 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.BATTERY_SERVICE, + { + CharacteristicsTypes.BATTERY_LEVEL: 0, + CharacteristicsTypes.CHARGING_STATE: 1, + }, + ) assert state.attributes["icon"] == "mdi:battery-outline" - helper.characteristics[BATTERY_LEVEL].value = 20 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.BATTERY_SERVICE, + { + CharacteristicsTypes.BATTERY_LEVEL: 20, + }, + ) assert state.attributes["icon"] == "mdi:battery-charging-20" @@ -184,13 +223,22 @@ async def test_battery_low(hass, utcnow): hass, create_battery_level_sensor, suffix="battery" ) - helper.characteristics[LO_BATT].value = 0 - helper.characteristics[BATTERY_LEVEL].value = 1 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.BATTERY_SERVICE, + { + CharacteristicsTypes.BATTERY_LEVEL: 1, + CharacteristicsTypes.STATUS_LO_BATT: 0, + }, + ) assert state.attributes["icon"] == "mdi:battery-10" - helper.characteristics[LO_BATT].value = 1 - state = await helper.poll_and_get_state() + state = await helper.async_update( + ServicesTypes.BATTERY_SERVICE, + { + CharacteristicsTypes.BATTERY_LEVEL: 1, + CharacteristicsTypes.STATUS_LO_BATT: 1, + }, + ) assert state.attributes["icon"] == "mdi:battery-alert" @@ -203,6 +251,7 @@ def create_switch_with_sensor(accessory): ) realtime_energy.value = 0 realtime_energy.format = "float" + realtime_energy.perms.append("ev") cur_state = service.add_char(CharacteristicsTypes.ON) cur_state.value = True @@ -213,7 +262,6 @@ def create_switch_with_sensor(accessory): async def test_switch_with_sensor(hass, utcnow): """Test a switch service that has a sensor characteristic is correctly handled.""" helper = await setup_test_component(hass, create_switch_with_sensor) - outlet = helper.accessory.services.first(service_type=ServicesTypes.OUTLET) # Helper will be for the primary entity, which is the outlet. Make a helper for the sensor. energy_helper = Helper( @@ -224,15 +272,20 @@ async def test_switch_with_sensor(hass, utcnow): helper.config_entry, ) - outlet = energy_helper.accessory.services.first(service_type=ServicesTypes.OUTLET) - realtime_energy = outlet[CharacteristicsTypes.Vendor.KOOGEEK_REALTIME_ENERGY] - - realtime_energy.value = 1 - state = await energy_helper.poll_and_get_state() + state = await energy_helper.async_update( + ServicesTypes.OUTLET, + { + CharacteristicsTypes.Vendor.KOOGEEK_REALTIME_ENERGY: 1, + }, + ) assert state.state == "1" - realtime_energy.value = 50 - state = await energy_helper.poll_and_get_state() + state = await energy_helper.async_update( + ServicesTypes.OUTLET, + { + CharacteristicsTypes.Vendor.KOOGEEK_REALTIME_ENERGY: 50, + }, + ) assert state.state == "50" diff --git a/tests/components/homekit_controller/test_switch.py b/tests/components/homekit_controller/test_switch.py index 5c737e63edc..fbea04171cb 100644 --- a/tests/components/homekit_controller/test_switch.py +++ b/tests/components/homekit_controller/test_switch.py @@ -43,6 +43,7 @@ def create_char_switch_service(accessory): service = accessory.add_service(ServicesTypes.OUTLET) on_char = service.add_char(CharacteristicsTypes.Vendor.AQARA_PAIRING_MODE) + on_char.perms.append("ev") on_char.value = False @@ -53,12 +54,22 @@ async def test_switch_change_outlet_state(hass, utcnow): await hass.services.async_call( "switch", "turn_on", {"entity_id": "switch.testdevice"}, blocking=True ) - assert helper.characteristics[("outlet", "on")].value == 1 + helper.async_assert_service_values( + ServicesTypes.OUTLET, + { + CharacteristicsTypes.ON: 1, + }, + ) await hass.services.async_call( "switch", "turn_off", {"entity_id": "switch.testdevice"}, blocking=True ) - assert helper.characteristics[("outlet", "on")].value == 0 + helper.async_assert_service_values( + ServicesTypes.OUTLET, + { + CharacteristicsTypes.ON: 0, + }, + ) async def test_switch_read_outlet_state(hass, utcnow): @@ -71,19 +82,25 @@ async def test_switch_read_outlet_state(hass, utcnow): assert switch_1.attributes["outlet_in_use"] is False # Simulate that someone switched on the device in the real world not via HA - helper.characteristics[("outlet", "on")].set_value(True) - switch_1 = await helper.poll_and_get_state() + switch_1 = await helper.async_update( + ServicesTypes.OUTLET, + {CharacteristicsTypes.ON: True}, + ) assert switch_1.state == "on" assert switch_1.attributes["outlet_in_use"] is False # Simulate that device switched off in the real world not via HA - helper.characteristics[("outlet", "on")].set_value(False) - switch_1 = await helper.poll_and_get_state() + switch_1 = await helper.async_update( + ServicesTypes.OUTLET, + {CharacteristicsTypes.ON: False}, + ) assert switch_1.state == "off" # Simulate that someone plugged something into the device - helper.characteristics[("outlet", "outlet-in-use")].value = True - switch_1 = await helper.poll_and_get_state() + switch_1 = await helper.async_update( + ServicesTypes.OUTLET, + {CharacteristicsTypes.OUTLET_IN_USE: True}, + ) assert switch_1.state == "off" assert switch_1.attributes["outlet_in_use"] is True @@ -95,12 +112,22 @@ async def test_valve_change_active_state(hass, utcnow): await hass.services.async_call( "switch", "turn_on", {"entity_id": "switch.testdevice"}, blocking=True ) - assert helper.characteristics[("valve", "active")].value == 1 + helper.async_assert_service_values( + ServicesTypes.VALVE, + { + CharacteristicsTypes.ACTIVE: 1, + }, + ) await hass.services.async_call( "switch", "turn_off", {"entity_id": "switch.testdevice"}, blocking=True ) - assert helper.characteristics[("valve", "active")].value == 0 + helper.async_assert_service_values( + ServicesTypes.VALVE, + { + CharacteristicsTypes.ACTIVE: 0, + }, + ) async def test_valve_read_state(hass, utcnow): @@ -115,20 +142,24 @@ async def test_valve_read_state(hass, utcnow): assert switch_1.attributes["remaining_duration"] == 99 # Simulate that someone switched on the device in the real world not via HA - helper.characteristics[("valve", "active")].set_value(True) - switch_1 = await helper.poll_and_get_state() + switch_1 = await helper.async_update( + ServicesTypes.VALVE, + {CharacteristicsTypes.ACTIVE: True}, + ) assert switch_1.state == "on" # Simulate that someone configured the device in the real world not via HA - helper.characteristics[ - ("valve", "is-configured") - ].value = IsConfiguredValues.NOT_CONFIGURED - switch_1 = await helper.poll_and_get_state() + switch_1 = await helper.async_update( + ServicesTypes.VALVE, + {CharacteristicsTypes.IS_CONFIGURED: IsConfiguredValues.NOT_CONFIGURED}, + ) assert switch_1.attributes["is_configured"] is False # Simulate that someone using the device in the real world not via HA - helper.characteristics[("valve", "in-use")].value = InUseValues.NOT_IN_USE - switch_1 = await helper.poll_and_get_state() + switch_1 = await helper.async_update( + ServicesTypes.VALVE, + {CharacteristicsTypes.IN_USE: InUseValues.NOT_IN_USE}, + ) assert switch_1.attributes["in_use"] is False @@ -137,8 +168,6 @@ async def test_char_switch_change_state(hass, utcnow): helper = await setup_test_component( hass, create_char_switch_service, suffix="pairing_mode" ) - svc = helper.accessory.services.first(service_type=ServicesTypes.OUTLET) - pairing_mode = svc[CharacteristicsTypes.Vendor.AQARA_PAIRING_MODE] await hass.services.async_call( "switch", @@ -146,7 +175,12 @@ async def test_char_switch_change_state(hass, utcnow): {"entity_id": "switch.testdevice_pairing_mode"}, blocking=True, ) - assert pairing_mode.value is True + helper.async_assert_service_values( + ServicesTypes.OUTLET, + { + CharacteristicsTypes.Vendor.AQARA_PAIRING_MODE: True, + }, + ) await hass.services.async_call( "switch", @@ -154,7 +188,12 @@ async def test_char_switch_change_state(hass, utcnow): {"entity_id": "switch.testdevice_pairing_mode"}, blocking=True, ) - assert pairing_mode.value is False + helper.async_assert_service_values( + ServicesTypes.OUTLET, + { + CharacteristicsTypes.Vendor.AQARA_PAIRING_MODE: False, + }, + ) async def test_char_switch_read_state(hass, utcnow): @@ -162,19 +201,17 @@ async def test_char_switch_read_state(hass, utcnow): helper = await setup_test_component( hass, create_char_switch_service, suffix="pairing_mode" ) - svc = helper.accessory.services.first(service_type=ServicesTypes.OUTLET) - pairing_mode = svc[CharacteristicsTypes.Vendor.AQARA_PAIRING_MODE] - - # Initial state is that the switch is off - switch_1 = await helper.poll_and_get_state() - assert switch_1.state == "off" # Simulate that someone switched on the device in the real world not via HA - pairing_mode.set_value(True) - switch_1 = await helper.poll_and_get_state() + switch_1 = await helper.async_update( + ServicesTypes.OUTLET, + {CharacteristicsTypes.Vendor.AQARA_PAIRING_MODE: True}, + ) assert switch_1.state == "on" # Simulate that device switched off in the real world not via HA - pairing_mode.set_value(False) - switch_1 = await helper.poll_and_get_state() + switch_1 = await helper.async_update( + ServicesTypes.OUTLET, + {CharacteristicsTypes.Vendor.AQARA_PAIRING_MODE: False}, + ) assert switch_1.state == "off"