Add timers and switches to Tuya irrigation systems (#149236)

This commit is contained in:
yufeng
2025-08-12 16:53:08 +08:00
committed by GitHub
parent db81610983
commit 5b232226e9
10 changed files with 1570 additions and 0 deletions

View File

@@ -66,6 +66,7 @@ PLATFORMS = [
Platform.SIREN, Platform.SIREN,
Platform.SWITCH, Platform.SWITCH,
Platform.VACUUM, Platform.VACUUM,
Platform.VALVE,
] ]
@@ -166,6 +167,14 @@ class DPCode(StrEnum):
CONTROL_BACK = "control_back" CONTROL_BACK = "control_back"
CONTROL_BACK_MODE = "control_back_mode" CONTROL_BACK_MODE = "control_back_mode"
COUNTDOWN = "countdown" # Countdown COUNTDOWN = "countdown" # Countdown
COUNTDOWN_1 = "countdown_1"
COUNTDOWN_2 = "countdown_2"
COUNTDOWN_3 = "countdown_3"
COUNTDOWN_4 = "countdown_4"
COUNTDOWN_5 = "countdown_5"
COUNTDOWN_6 = "countdown_6"
COUNTDOWN_7 = "countdown_7"
COUNTDOWN_8 = "countdown_8"
COUNTDOWN_LEFT = "countdown_left" COUNTDOWN_LEFT = "countdown_left"
COUNTDOWN_SET = "countdown_set" # Countdown setting COUNTDOWN_SET = "countdown_set" # Countdown setting
CRY_DETECTION_SWITCH = "cry_detection_switch" CRY_DETECTION_SWITCH = "cry_detection_switch"

View File

@@ -224,6 +224,66 @@ NUMBERS: dict[str, tuple[NumberEntityDescription, ...]] = {
entity_category=EntityCategory.CONFIG, entity_category=EntityCategory.CONFIG,
), ),
), ),
# Smart Water Timer
"sfkzq": (
# Controls the irrigation duration for the water valve
NumberEntityDescription(
key=DPCode.COUNTDOWN_1,
translation_key="indexed_irrigation_duration",
translation_placeholders={"index": "1"},
device_class=NumberDeviceClass.DURATION,
entity_category=EntityCategory.CONFIG,
),
NumberEntityDescription(
key=DPCode.COUNTDOWN_2,
translation_key="indexed_irrigation_duration",
translation_placeholders={"index": "2"},
device_class=NumberDeviceClass.DURATION,
entity_category=EntityCategory.CONFIG,
),
NumberEntityDescription(
key=DPCode.COUNTDOWN_3,
translation_key="indexed_irrigation_duration",
translation_placeholders={"index": "3"},
device_class=NumberDeviceClass.DURATION,
entity_category=EntityCategory.CONFIG,
),
NumberEntityDescription(
key=DPCode.COUNTDOWN_4,
translation_key="indexed_irrigation_duration",
translation_placeholders={"index": "4"},
device_class=NumberDeviceClass.DURATION,
entity_category=EntityCategory.CONFIG,
),
NumberEntityDescription(
key=DPCode.COUNTDOWN_5,
translation_key="indexed_irrigation_duration",
translation_placeholders={"index": "5"},
device_class=NumberDeviceClass.DURATION,
entity_category=EntityCategory.CONFIG,
),
NumberEntityDescription(
key=DPCode.COUNTDOWN_6,
translation_key="indexed_irrigation_duration",
translation_placeholders={"index": "6"},
device_class=NumberDeviceClass.DURATION,
entity_category=EntityCategory.CONFIG,
),
NumberEntityDescription(
key=DPCode.COUNTDOWN_7,
translation_key="indexed_irrigation_duration",
translation_placeholders={"index": "7"},
device_class=NumberDeviceClass.DURATION,
entity_category=EntityCategory.CONFIG,
),
NumberEntityDescription(
key=DPCode.COUNTDOWN_8,
translation_key="indexed_irrigation_duration",
translation_placeholders={"index": "8"},
device_class=NumberDeviceClass.DURATION,
entity_category=EntityCategory.CONFIG,
),
),
# Siren Alarm # Siren Alarm
# https://developer.tuya.com/en/docs/iot/categorysgbj?id=Kaiuz37tlpbnu # https://developer.tuya.com/en/docs/iot/categorysgbj?id=Kaiuz37tlpbnu
"sgbj": ( "sgbj": (

View File

@@ -148,6 +148,9 @@
"heat_preservation_time": { "heat_preservation_time": {
"name": "Heat preservation time" "name": "Heat preservation time"
}, },
"indexed_irrigation_duration": {
"name": "Irrigation duration {index}"
},
"feed": { "feed": {
"name": "Feed" "name": "Feed"
}, },
@@ -899,6 +902,11 @@
"frost_protection": { "frost_protection": {
"name": "Frost protection" "name": "Frost protection"
} }
},
"valve": {
"indexed_valve": {
"name": "Valve {index}"
}
} }
}, },
"exceptions": { "exceptions": {

View File

@@ -0,0 +1,140 @@
"""Support for Tuya valves."""
from __future__ import annotations
from tuya_sharing import CustomerDevice, Manager
from homeassistant.components.valve import (
ValveDeviceClass,
ValveEntity,
ValveEntityDescription,
ValveEntityFeature,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import TuyaConfigEntry
from .const import TUYA_DISCOVERY_NEW, DPCode
from .entity import TuyaEntity
# All descriptions can be found here. Mostly the Boolean data types in the
# default instruction set of each category end up being a Valve.
# https://developer.tuya.com/en/docs/iot/standarddescription?id=K9i5ql6waswzq
VALVES: dict[str, tuple[ValveEntityDescription, ...]] = {
# Smart Water Timer
"sfkzq": (
ValveEntityDescription(
key=DPCode.SWITCH_1,
translation_key="indexed_valve",
translation_placeholders={"index": "1"},
device_class=ValveDeviceClass.WATER,
),
ValveEntityDescription(
key=DPCode.SWITCH_2,
translation_key="indexed_valve",
translation_placeholders={"index": "2"},
device_class=ValveDeviceClass.WATER,
),
ValveEntityDescription(
key=DPCode.SWITCH_3,
translation_key="indexed_valve",
translation_placeholders={"index": "3"},
device_class=ValveDeviceClass.WATER,
),
ValveEntityDescription(
key=DPCode.SWITCH_4,
translation_key="indexed_valve",
translation_placeholders={"index": "4"},
device_class=ValveDeviceClass.WATER,
),
ValveEntityDescription(
key=DPCode.SWITCH_5,
translation_key="indexed_valve",
translation_placeholders={"index": "5"},
device_class=ValveDeviceClass.WATER,
),
ValveEntityDescription(
key=DPCode.SWITCH_6,
translation_key="indexed_valve",
translation_placeholders={"index": "6"},
device_class=ValveDeviceClass.WATER,
),
ValveEntityDescription(
key=DPCode.SWITCH_7,
translation_key="indexed_valve",
translation_placeholders={"index": "7"},
device_class=ValveDeviceClass.WATER,
),
ValveEntityDescription(
key=DPCode.SWITCH_8,
translation_key="indexed_valve",
translation_placeholders={"index": "8"},
device_class=ValveDeviceClass.WATER,
),
),
}
async def async_setup_entry(
hass: HomeAssistant,
entry: TuyaConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up tuya valves dynamically through tuya discovery."""
hass_data = entry.runtime_data
@callback
def async_discover_device(device_ids: list[str]) -> None:
"""Discover and add a discovered tuya valve."""
entities: list[TuyaValveEntity] = []
for device_id in device_ids:
device = hass_data.manager.device_map[device_id]
if descriptions := VALVES.get(device.category):
entities.extend(
TuyaValveEntity(device, hass_data.manager, description)
for description in descriptions
if description.key in device.status
)
async_add_entities(entities)
async_discover_device([*hass_data.manager.device_map])
entry.async_on_unload(
async_dispatcher_connect(hass, TUYA_DISCOVERY_NEW, async_discover_device)
)
class TuyaValveEntity(TuyaEntity, ValveEntity):
"""Tuya Valve Device."""
_attr_supported_features = ValveEntityFeature.OPEN | ValveEntityFeature.CLOSE
def __init__(
self,
device: CustomerDevice,
device_manager: Manager,
description: ValveEntityDescription,
) -> None:
"""Init TuyaValveEntity."""
super().__init__(device, device_manager)
self.entity_description = description
self._attr_unique_id = f"{super().unique_id}{description.key}"
@property
def is_closed(self) -> bool:
"""Return if the valve is closed."""
return not self.device.status.get(self.entity_description.key, False)
async def async_open_valve(self) -> None:
"""Open the valve."""
await self.hass.async_add_executor_job(
self._send_command, [{"code": self.entity_description.key, "value": True}]
)
async def async_close_valve(self) -> None:
"""Close the valve."""
await self.hass.async_add_executor_job(
self._send_command, [{"code": self.entity_description.key, "value": False}]
)

View File

@@ -140,6 +140,7 @@ DEVICE_MOCKS = [
"sd_i6hyjg3af7doaswm", # https://github.com/orgs/home-assistant/discussions/539 "sd_i6hyjg3af7doaswm", # https://github.com/orgs/home-assistant/discussions/539
"sd_lr33znaodtyarrrz", # https://github.com/home-assistant/core/issues/141278 "sd_lr33znaodtyarrrz", # https://github.com/home-assistant/core/issues/141278
"sfkzq_1fcnd8xk", # https://github.com/orgs/home-assistant/discussions/539 "sfkzq_1fcnd8xk", # https://github.com/orgs/home-assistant/discussions/539
"sfkzq_ed7frwissyqrejic", # https://github.com/home-assistant/core/pull/149236
"sfkzq_o6dagifntoafakst", # https://github.com/home-assistant/core/issues/148116 "sfkzq_o6dagifntoafakst", # https://github.com/home-assistant/core/issues/148116
"sfkzq_rzklytdei8i8vo37", # https://github.com/home-assistant/core/issues/146164 "sfkzq_rzklytdei8i8vo37", # https://github.com/home-assistant/core/issues/146164
"sgbj_ulv4nnue7gqp0rjk", # https://github.com/home-assistant/core/issues/149704 "sgbj_ulv4nnue7gqp0rjk", # https://github.com/home-assistant/core/issues/149704

View File

@@ -0,0 +1,282 @@
{
"endpoint": "https://apigw.tuyacn.com",
"mqtt_connected": true,
"disabled_by": null,
"disabled_polling": false,
"name": "\u63a5HA\u6c34\u9600",
"category": "sfkzq",
"product_id": "ed7frwissyqrejic",
"product_name": "\u63a5HA\u6c34\u9600",
"online": true,
"sub": false,
"time_zone": "+08:00",
"active_time": "2025-07-14T06:32:48+00:00",
"create_time": "2025-07-14T06:32:48+00:00",
"update_time": "2025-07-14T06:32:48+00:00",
"function": {
"switch_1": {
"type": "Boolean",
"value": {}
},
"switch_2": {
"type": "Boolean",
"value": {}
},
"switch_3": {
"type": "Boolean",
"value": {}
},
"switch_4": {
"type": "Boolean",
"value": {}
},
"switch_5": {
"type": "Boolean",
"value": {}
},
"switch_6": {
"type": "Boolean",
"value": {}
},
"switch_7": {
"type": "Boolean",
"value": {}
},
"switch_8": {
"type": "Boolean",
"value": {}
},
"countdown_1": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
},
"countdown_2": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
},
"countdown_3": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
},
"countdown_4": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
},
"countdown_5": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
},
"countdown_6": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
},
"countdown_7": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
},
"countdown_8": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
}
},
"status_range": {
"switch_1": {
"type": "Boolean",
"value": {}
},
"switch_2": {
"type": "Boolean",
"value": {}
},
"switch_3": {
"type": "Boolean",
"value": {}
},
"switch_4": {
"type": "Boolean",
"value": {}
},
"switch_5": {
"type": "Boolean",
"value": {}
},
"switch_6": {
"type": "Boolean",
"value": {}
},
"switch_7": {
"type": "Boolean",
"value": {}
},
"switch_8": {
"type": "Boolean",
"value": {}
},
"countdown_1": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
},
"countdown_2": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
},
"countdown_3": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
},
"countdown_4": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
},
"countdown_5": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
},
"countdown_6": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
},
"countdown_7": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
},
"countdown_8": {
"type": "Integer",
"value": {
"unit": "min",
"min": 1,
"max": 1439,
"scale": 0,
"step": 1
}
},
"battery_percentage": {
"type": "Integer",
"value": {
"unit": "%",
"min": 0,
"max": 100,
"scale": 0,
"step": 1
}
},
"battery_state": {
"type": "Enum",
"value": {
"range": ["low", "middle", "high"]
}
}
},
"status": {
"switch_1": true,
"switch_2": false,
"switch_3": true,
"switch_4": false,
"switch_5": true,
"switch_6": false,
"switch_7": true,
"switch_8": false,
"countdown_1": 1,
"countdown_2": 1,
"countdown_3": 3,
"countdown_4": 2,
"countdown_5": 2,
"countdown_6": 3,
"countdown_7": 1,
"countdown_8": 1,
"battery_percentage": 0,
"battery_state": "low"
},
"set_up": true,
"support_local": true
}

View File

@@ -643,6 +643,478 @@
'state': '3.0', 'state': '3.0',
}) })
# --- # ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_1-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_1',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <NumberDeviceClass.DURATION: 'duration'>,
'original_icon': None,
'original_name': 'Irrigation duration 1',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'indexed_irrigation_duration',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfscountdown_1',
'unit_of_measurement': 'min',
})
# ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_1-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': '接HA水阀 Irrigation duration 1',
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
'unit_of_measurement': 'min',
}),
'context': <ANY>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_1',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '1.0',
})
# ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_2-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_2',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <NumberDeviceClass.DURATION: 'duration'>,
'original_icon': None,
'original_name': 'Irrigation duration 2',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'indexed_irrigation_duration',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfscountdown_2',
'unit_of_measurement': 'min',
})
# ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_2-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': '接HA水阀 Irrigation duration 2',
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
'unit_of_measurement': 'min',
}),
'context': <ANY>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_2',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '1.0',
})
# ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_3-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_3',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <NumberDeviceClass.DURATION: 'duration'>,
'original_icon': None,
'original_name': 'Irrigation duration 3',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'indexed_irrigation_duration',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfscountdown_3',
'unit_of_measurement': 'min',
})
# ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_3-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': '接HA水阀 Irrigation duration 3',
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
'unit_of_measurement': 'min',
}),
'context': <ANY>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_3',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '3.0',
})
# ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_4-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_4',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <NumberDeviceClass.DURATION: 'duration'>,
'original_icon': None,
'original_name': 'Irrigation duration 4',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'indexed_irrigation_duration',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfscountdown_4',
'unit_of_measurement': 'min',
})
# ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_4-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': '接HA水阀 Irrigation duration 4',
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
'unit_of_measurement': 'min',
}),
'context': <ANY>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_4',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2.0',
})
# ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_5-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_5',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <NumberDeviceClass.DURATION: 'duration'>,
'original_icon': None,
'original_name': 'Irrigation duration 5',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'indexed_irrigation_duration',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfscountdown_5',
'unit_of_measurement': 'min',
})
# ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_5-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': '接HA水阀 Irrigation duration 5',
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
'unit_of_measurement': 'min',
}),
'context': <ANY>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_5',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2.0',
})
# ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_6-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_6',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <NumberDeviceClass.DURATION: 'duration'>,
'original_icon': None,
'original_name': 'Irrigation duration 6',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'indexed_irrigation_duration',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfscountdown_6',
'unit_of_measurement': 'min',
})
# ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_6-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': '接HA水阀 Irrigation duration 6',
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
'unit_of_measurement': 'min',
}),
'context': <ANY>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_6',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '3.0',
})
# ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_7-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_7',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <NumberDeviceClass.DURATION: 'duration'>,
'original_icon': None,
'original_name': 'Irrigation duration 7',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'indexed_irrigation_duration',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfscountdown_7',
'unit_of_measurement': 'min',
})
# ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_7-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': '接HA水阀 Irrigation duration 7',
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
'unit_of_measurement': 'min',
}),
'context': <ANY>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_7',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '1.0',
})
# ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_8-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_8',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <NumberDeviceClass.DURATION: 'duration'>,
'original_icon': None,
'original_name': 'Irrigation duration 8',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'indexed_irrigation_duration',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfscountdown_8',
'unit_of_measurement': 'min',
})
# ---
# name: test_platform_setup_and_discovery[number.jie_hashui_fa_irrigation_duration_8-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': '接HA水阀 Irrigation duration 8',
'max': 1439.0,
'min': 1.0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1.0,
'unit_of_measurement': 'min',
}),
'context': <ANY>,
'entity_id': 'number.jie_hashui_fa_irrigation_duration_8',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '1.0',
})
# ---
# name: test_platform_setup_and_discovery[number.kabinet_temperature_correction-entry] # name: test_platform_setup_and_discovery[number.kabinet_temperature_correction-entry]
EntityRegistryEntrySnapshot({ EntityRegistryEntrySnapshot({
'aliases': set({ 'aliases': set({

View File

@@ -6094,6 +6094,107 @@
'state': '9.0', 'state': '9.0',
}) })
# --- # ---
# name: test_platform_setup_and_discovery[sensor.jie_hashui_fa_battery-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.jie_hashui_fa_battery',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.BATTERY: 'battery'>,
'original_icon': None,
'original_name': 'Battery',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'battery',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfsbattery_percentage',
'unit_of_measurement': '%',
})
# ---
# name: test_platform_setup_and_discovery[sensor.jie_hashui_fa_battery-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'battery',
'friendly_name': '接HA水阀 Battery',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': '%',
}),
'context': <ANY>,
'entity_id': 'sensor.jie_hashui_fa_battery',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0.0',
})
# ---
# name: test_platform_setup_and_discovery[sensor.jie_hashui_fa_battery_state-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.jie_hashui_fa_battery_state',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Battery state',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'battery_state',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfsbattery_state',
'unit_of_measurement': None,
})
# ---
# name: test_platform_setup_and_discovery[sensor.jie_hashui_fa_battery_state-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': '接HA水阀 Battery state',
}),
'context': <ANY>,
'entity_id': 'sensor.jie_hashui_fa_battery_state',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'low',
})
# ---
# name: test_platform_setup_and_discovery[sensor.kalado_air_purifier_air_quality-entry] # name: test_platform_setup_and_discovery[sensor.kalado_air_purifier_air_quality-entry]
EntityRegistryEntrySnapshot({ EntityRegistryEntrySnapshot({
'aliases': set({ 'aliases': set({

View File

@@ -0,0 +1,401 @@
# serializer version: 1
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_1-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'valve',
'entity_category': None,
'entity_id': 'valve.jie_hashui_fa_valve_1',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <ValveDeviceClass.WATER: 'water'>,
'original_icon': None,
'original_name': 'Valve 1',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': <ValveEntityFeature: 3>,
'translation_key': 'indexed_valve',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfsswitch_1',
'unit_of_measurement': None,
})
# ---
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_1-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'water',
'friendly_name': '接HA水阀 Valve 1',
'supported_features': <ValveEntityFeature: 3>,
}),
'context': <ANY>,
'entity_id': 'valve.jie_hashui_fa_valve_1',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'open',
})
# ---
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_2-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'valve',
'entity_category': None,
'entity_id': 'valve.jie_hashui_fa_valve_2',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <ValveDeviceClass.WATER: 'water'>,
'original_icon': None,
'original_name': 'Valve 2',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': <ValveEntityFeature: 3>,
'translation_key': 'indexed_valve',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfsswitch_2',
'unit_of_measurement': None,
})
# ---
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_2-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'water',
'friendly_name': '接HA水阀 Valve 2',
'supported_features': <ValveEntityFeature: 3>,
}),
'context': <ANY>,
'entity_id': 'valve.jie_hashui_fa_valve_2',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'closed',
})
# ---
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_3-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'valve',
'entity_category': None,
'entity_id': 'valve.jie_hashui_fa_valve_3',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <ValveDeviceClass.WATER: 'water'>,
'original_icon': None,
'original_name': 'Valve 3',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': <ValveEntityFeature: 3>,
'translation_key': 'indexed_valve',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfsswitch_3',
'unit_of_measurement': None,
})
# ---
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_3-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'water',
'friendly_name': '接HA水阀 Valve 3',
'supported_features': <ValveEntityFeature: 3>,
}),
'context': <ANY>,
'entity_id': 'valve.jie_hashui_fa_valve_3',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'open',
})
# ---
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_4-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'valve',
'entity_category': None,
'entity_id': 'valve.jie_hashui_fa_valve_4',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <ValveDeviceClass.WATER: 'water'>,
'original_icon': None,
'original_name': 'Valve 4',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': <ValveEntityFeature: 3>,
'translation_key': 'indexed_valve',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfsswitch_4',
'unit_of_measurement': None,
})
# ---
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_4-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'water',
'friendly_name': '接HA水阀 Valve 4',
'supported_features': <ValveEntityFeature: 3>,
}),
'context': <ANY>,
'entity_id': 'valve.jie_hashui_fa_valve_4',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'closed',
})
# ---
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_5-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'valve',
'entity_category': None,
'entity_id': 'valve.jie_hashui_fa_valve_5',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <ValveDeviceClass.WATER: 'water'>,
'original_icon': None,
'original_name': 'Valve 5',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': <ValveEntityFeature: 3>,
'translation_key': 'indexed_valve',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfsswitch_5',
'unit_of_measurement': None,
})
# ---
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_5-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'water',
'friendly_name': '接HA水阀 Valve 5',
'supported_features': <ValveEntityFeature: 3>,
}),
'context': <ANY>,
'entity_id': 'valve.jie_hashui_fa_valve_5',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'open',
})
# ---
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_6-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'valve',
'entity_category': None,
'entity_id': 'valve.jie_hashui_fa_valve_6',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <ValveDeviceClass.WATER: 'water'>,
'original_icon': None,
'original_name': 'Valve 6',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': <ValveEntityFeature: 3>,
'translation_key': 'indexed_valve',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfsswitch_6',
'unit_of_measurement': None,
})
# ---
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_6-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'water',
'friendly_name': '接HA水阀 Valve 6',
'supported_features': <ValveEntityFeature: 3>,
}),
'context': <ANY>,
'entity_id': 'valve.jie_hashui_fa_valve_6',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'closed',
})
# ---
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_7-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'valve',
'entity_category': None,
'entity_id': 'valve.jie_hashui_fa_valve_7',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <ValveDeviceClass.WATER: 'water'>,
'original_icon': None,
'original_name': 'Valve 7',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': <ValveEntityFeature: 3>,
'translation_key': 'indexed_valve',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfsswitch_7',
'unit_of_measurement': None,
})
# ---
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_7-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'water',
'friendly_name': '接HA水阀 Valve 7',
'supported_features': <ValveEntityFeature: 3>,
}),
'context': <ANY>,
'entity_id': 'valve.jie_hashui_fa_valve_7',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'open',
})
# ---
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_8-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'valve',
'entity_category': None,
'entity_id': 'valve.jie_hashui_fa_valve_8',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <ValveDeviceClass.WATER: 'water'>,
'original_icon': None,
'original_name': 'Valve 8',
'platform': 'tuya',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': <ValveEntityFeature: 3>,
'translation_key': 'indexed_valve',
'unique_id': 'tuya.cijerqyssiwrf7deqzkfsswitch_8',
'unit_of_measurement': None,
})
# ---
# name: test_platform_setup_and_discovery[valve.jie_hashui_fa_valve_8-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'water',
'friendly_name': '接HA水阀 Valve 8',
'supported_features': <ValveEntityFeature: 3>,
}),
'context': <ANY>,
'entity_id': 'valve.jie_hashui_fa_valve_8',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'closed',
})
# ---

View File

@@ -0,0 +1,96 @@
"""Test Tuya valve platform."""
from __future__ import annotations
from unittest.mock import patch
import pytest
from syrupy.assertion import SnapshotAssertion
from tuya_sharing import CustomerDevice
from homeassistant.components.tuya import ManagerCompat
from homeassistant.components.valve import (
DOMAIN as VALVE_DOMAIN,
SERVICE_CLOSE_VALVE,
SERVICE_OPEN_VALVE,
)
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import initialize_entry
from tests.common import MockConfigEntry, snapshot_platform
@patch("homeassistant.components.tuya.PLATFORMS", [Platform.VALVE])
async def test_platform_setup_and_discovery(
hass: HomeAssistant,
mock_manager: ManagerCompat,
mock_config_entry: MockConfigEntry,
mock_devices: list[CustomerDevice],
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
) -> None:
"""Test platform setup and discovery."""
await initialize_entry(hass, mock_manager, mock_config_entry, mock_devices)
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
@pytest.mark.parametrize(
"mock_device_code",
["sfkzq_ed7frwissyqrejic"],
)
async def test_open_valve(
hass: HomeAssistant,
mock_manager: ManagerCompat,
mock_config_entry: MockConfigEntry,
mock_device: CustomerDevice,
) -> None:
"""Test opening a valve."""
entity_id = "valve.jie_hashui_fa_valve_1"
await initialize_entry(hass, mock_manager, mock_config_entry, mock_device)
state = hass.states.get(entity_id)
assert state is not None, f"{entity_id} does not exist"
await hass.services.async_call(
VALVE_DOMAIN,
SERVICE_OPEN_VALVE,
{
"entity_id": entity_id,
},
blocking=True,
)
mock_manager.send_commands.assert_called_once_with(
mock_device.id, [{"code": "switch_1", "value": True}]
)
@pytest.mark.parametrize(
"mock_device_code",
["sfkzq_ed7frwissyqrejic"],
)
async def test_close_valve(
hass: HomeAssistant,
mock_manager: ManagerCompat,
mock_config_entry: MockConfigEntry,
mock_device: CustomerDevice,
) -> None:
"""Test closing a valve."""
entity_id = "valve.jie_hashui_fa_valve_1"
await initialize_entry(hass, mock_manager, mock_config_entry, mock_device)
state = hass.states.get(entity_id)
assert state is not None, f"{entity_id} does not exist"
await hass.services.async_call(
VALVE_DOMAIN,
SERVICE_CLOSE_VALVE,
{
"entity_id": entity_id,
},
blocking=True,
)
mock_manager.send_commands.assert_called_once_with(
mock_device.id, [{"code": "switch_1", "value": False}]
)