mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Improve homekit_controller tests (#65266)
This commit is contained in:
parent
eb94fe1ca7
commit
58b8c30221
@ -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)
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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,
|
||||
},
|
||||
)
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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},
|
||||
)
|
||||
|
@ -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},
|
||||
)
|
||||
|
@ -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"
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user