Home IO Control
ESPHome add-on for IO-Homecontrol devices
Loading...
Searching...
No Matches
cover.py
Go to the documentation of this file.
1## @file
2## @brief ESPHome cover platform schema and code generation.
3## @ingroup hioc_codegen
4##
5## Bridges the YAML ``cover:`` platform declaration to the runtime IOHomeCover entity.
6## Shared device-binding logic lives in platform_common.py; cover-specific extras — the
7## ``invert_position`` option and the favorite/ventilation companion buttons — stay here.
8
9import esphome.codegen as cg
10import esphome.config_validation as cv
11from esphome.components import button, cover
12from esphome.const import (
13 CONF_DISABLED_BY_DEFAULT,
14 CONF_ID,
15 CONF_NAME,
16)
17from esphome.core import ID
18
19from . import home_io_control_ns
20from .platform_common import (
21 companion_id_base,
22 create_companion_sensors,
23 inject_companion_sensor_ids,
24 platform_schema_extension,
25 wire_device_binding,
26 CONF_DEVICE_ID,
27 CONF_DEVICE_TYPE,
28 CONF_HOME_IO_CONTROL_ID,
29)
30
31DEPENDENCIES = ["home_io_control"]
32
33CONF_INVERT_POSITION = "invert_position"
34CONF_OPTIMISTIC_STATE = "optimistic_state"
35
36# Internal config keys for the cover-only companion button IDs (injected by post-validator).
37CONF_FAVORITE_BUTTON_ID = "_favorite_button_id"
38CONF_VENT_BUTTON_ID = "_vent_button_id"
39
40IOHomeCover = home_io_control_ns.class_("IOHomeCover", cover.Cover, cg.Component)
41IOHomeCoverFavoriteButton = home_io_control_ns.class_(
42 "IOHomeCoverFavoriteButton", button.Button, cg.Component
43)
44IOHomeCoverVentButton = home_io_control_ns.class_(
45 "IOHomeCoverVentButton", button.Button, cg.Component
46)
47
48# Device types that support 0-100% position control (maps to DeviceCapabilityClass::COVER in C++).
49# Used to decide whether a favorite-position button companion should be generated.
50POSITION_CONTROL_DEVICE_TYPES = {
51 0x01, # venetian_blind
52 0x02, # roller_shutter
53 0x03, # awning
54 0x04, # window_opener
55 0x05, # garage_opener
56 0x07, # gate_opener
57 0x08, # rolling_door_opener
58 0x0A, # blind
59 0x0B, # screen
60 0x0D, # dual_shutter
61 0x10, # horizontal_awning
62 0x11, # external_venetian_blind
63 0x12, # louvre_blind
64 0x13, # curtain_track
65 0x18, # swinging_shutter
66}
67
68
70 """Check if the given device type value supports 0-100% position control."""
71 return value in POSITION_CONTROL_DEVICE_TYPES
72
73
74# Device types that support the ventilation position command.
75# These are window-type actuators that can move to a predefined vent opening.
76VENT_DEVICE_TYPES = {
77 0x04, # window_opener
78 0x14, # ventilation_point
79}
80
81
83 """Check if the given device type value supports the ventilation command."""
84 return value in VENT_DEVICE_TYPES
85
86
88 """Derive the favorite-position button name from the parent cover name."""
89 base_name = config.get(CONF_NAME, "")
90 if base_name:
91 return f"{base_name} Favorite Position"
92 return "Favorite Position"
93
94
95def vent_button_name(config):
96 """Derive the ventilation-position button name from the parent cover name."""
97 base_name = config.get(CONF_NAME, "")
98 if base_name:
99 return f"{base_name} Ventilation Position"
100 return "Ventilation Position"
101
102
104 """Declare cover companion entity IDs during schema validation for StaticVector sizing.
105
106 The favorite and ventilation buttons are cover-only and gated on device capability, so
107 their injection stays here. The always-present companion sensor IDs are delegated to the
108 shared helper. See platform_common.companion_id_base() for the StaticVector rationale.
109 """
110 base = companion_id_base(config, CONF_ID)
111
112 # Favorite-position button — only for position-capable device types.
113 if CONF_DEVICE_TYPE in config and device_supports_position_control(
114 config[CONF_DEVICE_TYPE]
115 ):
116 config[CONF_FAVORITE_BUTTON_ID] = ID(
117 f"{base}_favorite_button",
118 is_declaration=True,
119 type=IOHomeCoverFavoriteButton,
120 )
121
122 # Ventilation-position button — only for window-type device types.
123 if CONF_DEVICE_TYPE in config and device_supports_vent(config[CONF_DEVICE_TYPE]):
124 config[CONF_VENT_BUTTON_ID] = ID(
125 f"{base}_vent_button",
126 is_declaration=True,
127 type=IOHomeCoverVentButton,
128 )
129
130 # Companion diagnostic sensors — always generated (shared with other platforms).
131 return inject_companion_sensor_ids(config, CONF_ID)
132
133
134CONFIG_SCHEMA = cv.All(
135 cover.cover_schema(IOHomeCover)
136 .extend(platform_schema_extension())
137 .extend({cv.Optional(CONF_INVERT_POSITION): cv.boolean})
138 .extend({cv.Optional(CONF_OPTIMISTIC_STATE, default=True): cv.boolean})
139 .extend(cv.COMPONENT_SCHEMA),
140 _inject_companion_ids,
141)
142
143
144async def to_code(config):
145 var = await cover.new_cover(config)
146 await cg.register_component(var, config)
147
148 parent = await cg.get_variable(config[CONF_HOME_IO_CONTROL_ID])
149 await wire_device_binding(var, parent, config)
150
151 if CONF_INVERT_POSITION in config:
152 cg.add(var.set_invert_position(config[CONF_INVERT_POSITION]))
153
154 cg.add(var.set_optimistic_state(config[CONF_OPTIMISTIC_STATE]))
155
156 if CONF_FAVORITE_BUTTON_ID in config:
157 favorite_config = {
158 CONF_ID: config[CONF_FAVORITE_BUTTON_ID],
159 CONF_NAME: favorite_button_name(config),
160 CONF_DISABLED_BY_DEFAULT: False,
161 }
162 favorite = await button.new_button(favorite_config)
163 await cg.register_component(favorite, favorite_config)
164 cg.add(favorite.set_parent(parent))
165 cg.add(favorite.set_device_id(config[CONF_DEVICE_ID]))
166
167 if CONF_VENT_BUTTON_ID in config:
168 vent_config = {
169 CONF_ID: config[CONF_VENT_BUTTON_ID],
170 CONF_NAME: vent_button_name(config),
171 CONF_DISABLED_BY_DEFAULT: False,
172 }
173 vent = await button.new_button(vent_config)
174 await cg.register_component(vent, vent_config)
175 cg.add(vent.set_parent(parent))
176 cg.add(vent.set_device_id(config[CONF_DEVICE_ID]))
177
178 await create_companion_sensors(config, parent)
_inject_companion_ids(config)
Definition cover.py:103
vent_button_name(config)
Definition cover.py:95
device_supports_position_control(value)
Definition cover.py:69
device_supports_vent(value)
Definition cover.py:82
favorite_button_name(config)
Definition cover.py:87