Improve homekit_controller tests (#65266)

This commit is contained in:
Jc2k 2022-01-30 22:59:39 +00:00 committed by GitHub
parent eb94fe1ca7
commit 58b8c30221
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 1487 additions and 650 deletions

View File

@ -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)

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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,
},
)

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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},
)

View File

@ -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},
)

View File

@ -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"

View File

@ -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"