mirror of
https://github.com/esphome/esphome.git
synced 2026-06-24 12:53:26 +00:00
[automation] Add CallbackAutomation dataclass and build_callback_automations helper (#15246)
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
from dataclasses import dataclass, field
|
||||
import logging
|
||||
|
||||
import esphome.codegen as cg
|
||||
@@ -715,3 +716,35 @@ async def build_callback_automation(
|
||||
# MockObjs (not user input), and there's no Expression type for positional
|
||||
# aggregate initialization (StructInitializer uses named fields).
|
||||
cg.add(getattr(parent, callback_method)(cg.RawExpression(f"{forwarder}{{{obj}}}")))
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class CallbackAutomation:
|
||||
"""A single callback automation entry for build_callback_automations."""
|
||||
|
||||
conf_key: str
|
||||
callback_method: str
|
||||
args: TemplateArgsType = field(default_factory=list)
|
||||
forwarder: MockObj | MockObjClass | None = None
|
||||
|
||||
|
||||
async def build_callback_automations(
|
||||
parent: MockObj,
|
||||
config: ConfigType,
|
||||
entries: tuple[CallbackAutomation, ...],
|
||||
) -> None:
|
||||
"""Build multiple callback automations from a tuple of entries.
|
||||
|
||||
:param parent: The component object (e.g., button, sensor).
|
||||
:param config: The full component config dict.
|
||||
:param entries: Tuple of CallbackAutomation entries to process.
|
||||
"""
|
||||
for entry in entries:
|
||||
for conf in config.get(entry.conf_key, []):
|
||||
await build_callback_automation(
|
||||
parent,
|
||||
entry.callback_method,
|
||||
entry.args,
|
||||
conf,
|
||||
forwarder=entry.forwarder,
|
||||
)
|
||||
|
||||
@@ -111,42 +111,66 @@ ALARM_CONTROL_PANEL_CONDITION_SCHEMA = maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_STATE, "add_on_state_callback", forwarder=StateAnyForwarder
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_TRIGGERED,
|
||||
"add_on_state_callback",
|
||||
forwarder=StateEnterForwarder.template(
|
||||
AlarmControlPanelState.ACP_STATE_TRIGGERED
|
||||
),
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_ARMING,
|
||||
"add_on_state_callback",
|
||||
forwarder=StateEnterForwarder.template(AlarmControlPanelState.ACP_STATE_ARMING),
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_PENDING,
|
||||
"add_on_state_callback",
|
||||
forwarder=StateEnterForwarder.template(
|
||||
AlarmControlPanelState.ACP_STATE_PENDING
|
||||
),
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_ARMED_HOME,
|
||||
"add_on_state_callback",
|
||||
forwarder=StateEnterForwarder.template(
|
||||
AlarmControlPanelState.ACP_STATE_ARMED_HOME
|
||||
),
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_ARMED_NIGHT,
|
||||
"add_on_state_callback",
|
||||
forwarder=StateEnterForwarder.template(
|
||||
AlarmControlPanelState.ACP_STATE_ARMED_NIGHT
|
||||
),
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_ARMED_AWAY,
|
||||
"add_on_state_callback",
|
||||
forwarder=StateEnterForwarder.template(
|
||||
AlarmControlPanelState.ACP_STATE_ARMED_AWAY
|
||||
),
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_DISARMED,
|
||||
"add_on_state_callback",
|
||||
forwarder=StateEnterForwarder.template(
|
||||
AlarmControlPanelState.ACP_STATE_DISARMED
|
||||
),
|
||||
),
|
||||
automation.CallbackAutomation(CONF_ON_CLEARED, "add_on_cleared_callback"),
|
||||
automation.CallbackAutomation(CONF_ON_CHIME, "add_on_chime_callback"),
|
||||
automation.CallbackAutomation(CONF_ON_READY, "add_on_ready_callback"),
|
||||
)
|
||||
|
||||
|
||||
@setup_entity("alarm_control_panel")
|
||||
async def setup_alarm_control_panel_core_(var, config):
|
||||
for conf in config.get(CONF_ON_STATE, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_state_callback", [], conf, forwarder=StateAnyForwarder
|
||||
)
|
||||
_STATE_ENTER_MAP = {
|
||||
CONF_ON_TRIGGERED: AlarmControlPanelState.ACP_STATE_TRIGGERED,
|
||||
CONF_ON_ARMING: AlarmControlPanelState.ACP_STATE_ARMING,
|
||||
CONF_ON_PENDING: AlarmControlPanelState.ACP_STATE_PENDING,
|
||||
CONF_ON_ARMED_HOME: AlarmControlPanelState.ACP_STATE_ARMED_HOME,
|
||||
CONF_ON_ARMED_NIGHT: AlarmControlPanelState.ACP_STATE_ARMED_NIGHT,
|
||||
CONF_ON_ARMED_AWAY: AlarmControlPanelState.ACP_STATE_ARMED_AWAY,
|
||||
CONF_ON_DISARMED: AlarmControlPanelState.ACP_STATE_DISARMED,
|
||||
}
|
||||
for conf_key, state_enum in _STATE_ENTER_MAP.items():
|
||||
for conf in config.get(conf_key, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_on_state_callback",
|
||||
[],
|
||||
conf,
|
||||
forwarder=StateEnterForwarder.template(state_enum),
|
||||
)
|
||||
for conf in config.get(CONF_ON_CLEARED, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_cleared_callback", [], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_CHIME, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_chime_callback", [], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_READY, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_ready_callback", [], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
if web_server_config := config.get(CONF_WEB_SERVER):
|
||||
await web_server.add_entity_config(var, web_server_config)
|
||||
if mqtt_id := config.get(CONF_MQTT_ID):
|
||||
|
||||
@@ -531,16 +531,31 @@ def binary_sensor_schema(
|
||||
return _BINARY_SENSOR_SCHEMA.extend(schema)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_PRESS,
|
||||
"add_on_state_callback",
|
||||
forwarder=automation.TriggerOnTrueForwarder,
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_RELEASE,
|
||||
"add_on_state_callback",
|
||||
forwarder=automation.TriggerOnFalseForwarder,
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_STATE, "add_on_state_callback", [(bool, "x")]
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_STATE_CHANGE,
|
||||
"add_full_state_callback",
|
||||
[(cg.optional.template(bool), "x_previous"), (cg.optional.template(bool), "x")],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.AUTOMATION)
|
||||
async def _build_binary_sensor_automations(var, config):
|
||||
for conf_key, forwarder in (
|
||||
(CONF_ON_PRESS, automation.TriggerOnTrueForwarder),
|
||||
(CONF_ON_RELEASE, automation.TriggerOnFalseForwarder),
|
||||
):
|
||||
for conf in config.get(conf_key, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_state_callback", [], conf, forwarder=forwarder
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
for conf in config.get(CONF_ON_CLICK, []):
|
||||
trigger = cg.new_Pvariable(
|
||||
@@ -572,22 +587,6 @@ async def _build_binary_sensor_automations(var, config):
|
||||
await cg.register_component(trigger, conf)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
|
||||
for conf in config.get(CONF_ON_STATE, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_state_callback", [(bool, "x")], conf
|
||||
)
|
||||
|
||||
for conf in config.get(CONF_ON_STATE_CHANGE, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_full_state_callback",
|
||||
[
|
||||
(cg.optional.template(bool), "x_previous"),
|
||||
(cg.optional.template(bool), "x"),
|
||||
],
|
||||
conf,
|
||||
)
|
||||
|
||||
|
||||
@setup_entity("binary_sensor")
|
||||
async def setup_binary_sensor_core_(var, config):
|
||||
|
||||
@@ -79,12 +79,14 @@ def button_schema(
|
||||
return _BUTTON_SCHEMA.extend(schema)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(CONF_ON_PRESS, "add_on_press_callback"),
|
||||
)
|
||||
|
||||
|
||||
@setup_entity("button")
|
||||
async def setup_button_core_(var, config):
|
||||
for conf in config.get(CONF_ON_PRESS, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_press_callback", [], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
setup_device_class(config)
|
||||
|
||||
|
||||
@@ -64,15 +64,19 @@ FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
|
||||
)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_FINISHED_PLAYBACK, "add_on_finished_playback_callback"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await uart.register_uart_device(var, config)
|
||||
|
||||
for conf in config.get(CONF_ON_FINISHED_PLAYBACK, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_finished_playback_callback", [], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
|
||||
@@ -82,12 +82,16 @@ def event_schema(
|
||||
return _EVENT_SCHEMA.extend(schema)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_EVENT, "add_on_event_callback", [(cg.StringRef, "event_type")]
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@setup_entity("event")
|
||||
async def setup_event_core_(var, config, *, event_types: list[str]):
|
||||
for conf in config.get(CONF_ON_EVENT, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_event_callback", [(cg.StringRef, "event_type")], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
cg.add(var.set_event_types(event_types))
|
||||
|
||||
|
||||
@@ -38,33 +38,30 @@ CONFIG_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_CUSTOM, "add_custom_callback", [(cg.std_string, "x")]
|
||||
),
|
||||
automation.CallbackAutomation(CONF_ON_LED, "add_led_state_callback", [(bool, "x")]),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_DEVICE_INFORMATION,
|
||||
"add_device_infomation_callback",
|
||||
[(cg.std_string, "x")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_SLOPE, "add_slope_callback", [(cg.std_string, "x")]
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_CALIBRATION, "add_calibration_callback", [(cg.std_string, "x")]
|
||||
),
|
||||
automation.CallbackAutomation(CONF_ON_T, "add_t_callback", [(cg.std_string, "x")]),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await sensor.register_sensor(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
|
||||
for conf in config.get(CONF_ON_CUSTOM, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_custom_callback", [(cg.std_string, "x")], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_LED, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_led_state_callback", [(bool, "x")], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_DEVICE_INFORMATION, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_device_infomation_callback", [(cg.std_string, "x")], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_SLOPE, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_slope_callback", [(cg.std_string, "x")], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_CALIBRATION, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_calibration_callback", [(cg.std_string, "x")], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_T, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_t_callback", [(cg.std_string, "x")], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
@@ -73,6 +73,15 @@ def _final_validate(config):
|
||||
FINAL_VALIDATE_SCHEMA = _final_validate
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_INCREMENT,
|
||||
"add_increment_callback",
|
||||
[(cg.uint8, "x"), (cg.uint8, "target")],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
if reset_count := config.get(CONF_RESETS_REQUIRED):
|
||||
var = cg.new_Pvariable(
|
||||
@@ -81,10 +90,4 @@ async def to_code(config):
|
||||
config[CONF_MAX_DELAY].total_seconds,
|
||||
)
|
||||
await cg.register_component(var, config)
|
||||
for conf in config.get(CONF_ON_INCREMENT, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_increment_callback",
|
||||
[(cg.uint8, "x"), (cg.uint8, "target")],
|
||||
conf,
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
@@ -116,6 +116,44 @@ CONFIG_SCHEMA = cv.All(
|
||||
)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_FINGER_SCAN_START, "add_on_finger_scan_start_callback"
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_FINGER_SCAN_MATCHED,
|
||||
"add_on_finger_scan_matched_callback",
|
||||
[(cg.uint16, "finger_id"), (cg.uint16, "confidence")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_FINGER_SCAN_UNMATCHED,
|
||||
"add_on_finger_scan_unmatched_callback",
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_FINGER_SCAN_MISPLACED,
|
||||
"add_on_finger_scan_misplaced_callback",
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_FINGER_SCAN_INVALID, "add_on_finger_scan_invalid_callback"
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_ENROLLMENT_SCAN,
|
||||
"add_on_enrollment_scan_callback",
|
||||
[(cg.uint8, "scan_num"), (cg.uint16, "finger_id")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_ENROLLMENT_DONE,
|
||||
"add_on_enrollment_done_callback",
|
||||
[(cg.uint16, "finger_id")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_ENROLLMENT_FAILED,
|
||||
"add_on_enrollment_failed_callback",
|
||||
[(cg.uint16, "finger_id")],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
@@ -140,44 +178,7 @@ async def to_code(config):
|
||||
idle_period_to_sleep_ms = config[CONF_IDLE_PERIOD_TO_SLEEP]
|
||||
cg.add(var.set_idle_period_to_sleep_ms(idle_period_to_sleep_ms))
|
||||
|
||||
for conf in config.get(CONF_ON_FINGER_SCAN_START, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_finger_scan_start_callback", [], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_FINGER_SCAN_MATCHED, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_on_finger_scan_matched_callback",
|
||||
[(cg.uint16, "finger_id"), (cg.uint16, "confidence")],
|
||||
conf,
|
||||
)
|
||||
for conf in config.get(CONF_ON_FINGER_SCAN_UNMATCHED, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_finger_scan_unmatched_callback", [], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_FINGER_SCAN_MISPLACED, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_finger_scan_misplaced_callback", [], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_FINGER_SCAN_INVALID, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_finger_scan_invalid_callback", [], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_ENROLLMENT_SCAN, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_on_enrollment_scan_callback",
|
||||
[(cg.uint8, "scan_num"), (cg.uint16, "finger_id")],
|
||||
conf,
|
||||
)
|
||||
for conf in config.get(CONF_ON_ENROLLMENT_DONE, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_enrollment_done_callback", [(cg.uint16, "finger_id")], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_ENROLLMENT_FAILED, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_enrollment_failed_callback", [(cg.uint16, "finger_id")], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
|
||||
@@ -456,6 +456,25 @@ def _final_validate(config):
|
||||
FINAL_VALIDATE_SCHEMA = _final_validate
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_ALARM_START,
|
||||
"add_alarm_start_callback",
|
||||
[(cg.uint8, "code"), (cg.const_char_ptr, "message")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_ALARM_END,
|
||||
"add_alarm_end_callback",
|
||||
[(cg.uint8, "code"), (cg.const_char_ptr, "message")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_STATUS_MESSAGE,
|
||||
"add_status_message_callback",
|
||||
[(cg.const_char_ptr, "data"), (cg.size_t, "data_size")],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
cg.add(haier_ns.init_haier_protocol_logging())
|
||||
var = await climate.new_climate(config)
|
||||
@@ -497,26 +516,6 @@ async def to_code(config):
|
||||
cg.add(
|
||||
var.set_status_message_header_size(config[CONF_STATUS_MESSAGE_HEADER_SIZE])
|
||||
)
|
||||
for conf in config.get(CONF_ON_ALARM_START, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_alarm_start_callback",
|
||||
[(cg.uint8, "code"), (cg.const_char_ptr, "message")],
|
||||
conf,
|
||||
)
|
||||
for conf in config.get(CONF_ON_ALARM_END, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_alarm_end_callback",
|
||||
[(cg.uint8, "code"), (cg.const_char_ptr, "message")],
|
||||
conf,
|
||||
)
|
||||
for conf in config.get(CONF_ON_STATUS_MESSAGE, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_status_message_callback",
|
||||
[(cg.const_char_ptr, "data"), (cg.size_t, "data_size")],
|
||||
conf,
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
# https://github.com/paveldn/HaierProtocol
|
||||
cg.add_library("pavlodn/HaierProtocol", "0.9.31")
|
||||
|
||||
@@ -52,58 +52,53 @@ CONFIG_SCHEMA = cv.All(
|
||||
)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_FACE_SCAN_MATCHED,
|
||||
"add_on_face_scan_matched_callback",
|
||||
[(cg.int16, "face_id"), (cg.std_string, "name")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_FACE_SCAN_UNMATCHED, "add_on_face_scan_unmatched_callback"
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_FACE_SCAN_INVALID,
|
||||
"add_on_face_scan_invalid_callback",
|
||||
[(cg.uint8, "error")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_FACE_INFO,
|
||||
"add_on_face_info_callback",
|
||||
[
|
||||
(cg.int16, "status"),
|
||||
(cg.int16, "left"),
|
||||
(cg.int16, "top"),
|
||||
(cg.int16, "right"),
|
||||
(cg.int16, "bottom"),
|
||||
(cg.int16, "yaw"),
|
||||
(cg.int16, "pitch"),
|
||||
(cg.int16, "roll"),
|
||||
],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_ENROLLMENT_DONE,
|
||||
"add_on_enrollment_done_callback",
|
||||
[(cg.int16, "face_id"), (cg.uint8, "direction")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_ENROLLMENT_FAILED,
|
||||
"add_on_enrollment_failed_callback",
|
||||
[(cg.uint8, "error")],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await uart.register_uart_device(var, config)
|
||||
|
||||
for conf in config.get(CONF_ON_FACE_SCAN_MATCHED, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_on_face_scan_matched_callback",
|
||||
[(cg.int16, "face_id"), (cg.std_string, "name")],
|
||||
conf,
|
||||
)
|
||||
|
||||
for conf in config.get(CONF_ON_FACE_SCAN_UNMATCHED, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_face_scan_unmatched_callback", [], conf
|
||||
)
|
||||
|
||||
for conf in config.get(CONF_ON_FACE_SCAN_INVALID, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_face_scan_invalid_callback", [(cg.uint8, "error")], conf
|
||||
)
|
||||
|
||||
for conf in config.get(CONF_ON_FACE_INFO, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_on_face_info_callback",
|
||||
[
|
||||
(cg.int16, "status"),
|
||||
(cg.int16, "left"),
|
||||
(cg.int16, "top"),
|
||||
(cg.int16, "right"),
|
||||
(cg.int16, "bottom"),
|
||||
(cg.int16, "yaw"),
|
||||
(cg.int16, "pitch"),
|
||||
(cg.int16, "roll"),
|
||||
],
|
||||
conf,
|
||||
)
|
||||
|
||||
for conf in config.get(CONF_ON_ENROLLMENT_DONE, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_on_enrollment_done_callback",
|
||||
[(cg.int16, "face_id"), (cg.uint8, "direction")],
|
||||
conf,
|
||||
)
|
||||
|
||||
for conf in config.get(CONF_ON_ENROLLMENT_FAILED, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_enrollment_failed_callback", [(cg.uint8, "error")], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
|
||||
@@ -44,11 +44,13 @@ FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
|
||||
)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(CONF_ON_DATA, "add_on_data_callback"),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await uart.register_uart_device(var, config)
|
||||
for conf in config.get(CONF_ON_DATA, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_data_callback", [], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
@@ -81,20 +81,23 @@ def lock_schema(
|
||||
return _LOCK_SCHEMA.extend(schema)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_LOCK,
|
||||
"add_on_state_callback",
|
||||
forwarder=LockStateForwarder.template(LockState.LOCK_STATE_LOCKED),
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_UNLOCK,
|
||||
"add_on_state_callback",
|
||||
forwarder=LockStateForwarder.template(LockState.LOCK_STATE_UNLOCKED),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@setup_entity("lock")
|
||||
async def _setup_lock_core(var, config):
|
||||
for conf_key, state_enum in (
|
||||
(CONF_ON_LOCK, LockState.LOCK_STATE_LOCKED),
|
||||
(CONF_ON_UNLOCK, LockState.LOCK_STATE_UNLOCKED),
|
||||
):
|
||||
for conf in config.get(conf_key, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_on_state_callback",
|
||||
[],
|
||||
conf,
|
||||
forwarder=LockStateForwarder.template(state_enum),
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
if mqtt_id := config.get(CONF_MQTT_ID):
|
||||
mqtt_ = cg.new_Pvariable(mqtt_id, var)
|
||||
|
||||
@@ -211,6 +211,16 @@ CONFIG_SCHEMA = cv.All(
|
||||
)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_PS_HIGH_THRESHOLD, "add_on_ps_high_trigger_callback"
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_PS_LOW_THRESHOLD, "add_on_ps_low_trigger_callback"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
@@ -240,14 +250,7 @@ async def to_code(config):
|
||||
sens = await sensor.new_sensor(prox_cnt_config)
|
||||
cg.add(var.set_proximity_counts_sensor(sens))
|
||||
|
||||
for conf in config.get(CONF_ON_PS_HIGH_THRESHOLD, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_ps_high_trigger_callback", [], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_PS_LOW_THRESHOLD, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_ps_low_trigger_callback", [], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
cg.add(var.set_ltr_type(config[CONF_TYPE]))
|
||||
|
||||
|
||||
@@ -201,6 +201,16 @@ CONFIG_SCHEMA = cv.All(
|
||||
)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_PS_HIGH_THRESHOLD, "add_on_ps_high_trigger_callback"
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_PS_LOW_THRESHOLD, "add_on_ps_low_trigger_callback"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
@@ -230,14 +240,7 @@ async def to_code(config):
|
||||
sens = await sensor.new_sensor(prox_cnt_config)
|
||||
cg.add(var.set_proximity_counts_sensor(sens))
|
||||
|
||||
for conf in config.get(CONF_ON_PS_HIGH_THRESHOLD, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_ps_high_trigger_callback", [], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_PS_LOW_THRESHOLD, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_ps_low_trigger_callback", [], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
cg.add(var.set_ltr_type(config[CONF_TYPE]))
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ StateEnterForwarder = media_player_ns.class_("StateEnterForwarder")
|
||||
MediaPlayerState = media_player_ns.enum("MediaPlayerState")
|
||||
|
||||
# State triggers: (config_key, state enum or None for any-state)
|
||||
_STATE_TRIGGERS = [
|
||||
_STATE_TRIGGERS = (
|
||||
(CONF_ON_STATE, None),
|
||||
(CONF_ON_IDLE, MediaPlayerState.MEDIA_PLAYER_STATE_IDLE),
|
||||
(CONF_ON_PLAY, MediaPlayerState.MEDIA_PLAYER_STATE_PLAYING),
|
||||
@@ -77,7 +77,7 @@ _STATE_TRIGGERS = [
|
||||
(CONF_ON_ANNOUNCEMENT, MediaPlayerState.MEDIA_PLAYER_STATE_ANNOUNCING),
|
||||
(CONF_ON_TURN_ON, MediaPlayerState.MEDIA_PLAYER_STATE_ON),
|
||||
(CONF_ON_TURN_OFF, MediaPlayerState.MEDIA_PLAYER_STATE_OFF),
|
||||
]
|
||||
)
|
||||
|
||||
# State conditions that all share the same schema and codegen handler
|
||||
_STATE_CONDITIONS = [
|
||||
@@ -102,17 +102,54 @@ VolumeSetAction = media_player_ns.class_(
|
||||
)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_STATE, "add_on_state_callback", forwarder=StateAnyForwarder
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_IDLE,
|
||||
"add_on_state_callback",
|
||||
forwarder=StateEnterForwarder.template(
|
||||
MediaPlayerState.MEDIA_PLAYER_STATE_IDLE
|
||||
),
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_PLAY,
|
||||
"add_on_state_callback",
|
||||
forwarder=StateEnterForwarder.template(
|
||||
MediaPlayerState.MEDIA_PLAYER_STATE_PLAYING
|
||||
),
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_PAUSE,
|
||||
"add_on_state_callback",
|
||||
forwarder=StateEnterForwarder.template(
|
||||
MediaPlayerState.MEDIA_PLAYER_STATE_PAUSED
|
||||
),
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_ANNOUNCEMENT,
|
||||
"add_on_state_callback",
|
||||
forwarder=StateEnterForwarder.template(
|
||||
MediaPlayerState.MEDIA_PLAYER_STATE_ANNOUNCING
|
||||
),
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_TURN_ON,
|
||||
"add_on_state_callback",
|
||||
forwarder=StateEnterForwarder.template(MediaPlayerState.MEDIA_PLAYER_STATE_ON),
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_TURN_OFF,
|
||||
"add_on_state_callback",
|
||||
forwarder=StateEnterForwarder.template(MediaPlayerState.MEDIA_PLAYER_STATE_OFF),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@setup_entity("media_player")
|
||||
async def setup_media_player_core_(var, config):
|
||||
for conf_key, state_enum in _STATE_TRIGGERS:
|
||||
for conf in config.get(conf_key, []):
|
||||
if state_enum is None:
|
||||
forwarder = StateAnyForwarder
|
||||
else:
|
||||
forwarder = StateEnterForwarder.template(state_enum)
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_state_callback", [], conf, forwarder=forwarder
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
async def register_media_player(var, config):
|
||||
|
||||
@@ -205,6 +205,25 @@ async def add_modbus_base_properties(
|
||||
cg.add(var.set_template(template_))
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_COMMAND_SENT,
|
||||
"add_on_command_sent_callback",
|
||||
[(cg.int_, "function_code"), (cg.int_, "address")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_ONLINE,
|
||||
"add_on_online_callback",
|
||||
[(cg.int_, "function_code"), (cg.int_, "address")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_OFFLINE,
|
||||
"add_on_offline_callback",
|
||||
[(cg.int_, "function_code"), (cg.int_, "address")],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
cg.add(var.set_allow_duplicate_commands(config[CONF_ALLOW_DUPLICATE_COMMANDS]))
|
||||
@@ -257,27 +276,7 @@ async def to_code(config):
|
||||
)
|
||||
cg.add(var.add_server_register(server_register_var))
|
||||
await register_modbus_device(var, config)
|
||||
for conf in config.get(CONF_ON_COMMAND_SENT, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_on_command_sent_callback",
|
||||
[(cg.int_, "function_code"), (cg.int_, "address")],
|
||||
conf,
|
||||
)
|
||||
for conf in config.get(CONF_ON_ONLINE, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_on_online_callback",
|
||||
[(cg.int_, "function_code"), (cg.int_, "address")],
|
||||
conf,
|
||||
)
|
||||
for conf in config.get(CONF_ON_OFFLINE, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_on_offline_callback",
|
||||
[(cg.int_, "function_code"), (cg.int_, "address")],
|
||||
conf,
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
async def register_modbus_device(var, config):
|
||||
|
||||
@@ -144,6 +144,28 @@ async def nextion_set_brightness_to_code(config, action_id, template_arg, args):
|
||||
return var
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(CONF_ON_SETUP, "add_setup_state_callback"),
|
||||
automation.CallbackAutomation(CONF_ON_SLEEP, "add_sleep_state_callback"),
|
||||
automation.CallbackAutomation(CONF_ON_WAKE, "add_wake_state_callback"),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_PAGE, "add_new_page_callback", [(cg.uint8, "x")]
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_TOUCH,
|
||||
"add_touch_event_callback",
|
||||
[
|
||||
(cg.uint8, "page_id"),
|
||||
(cg.uint8, "component_id"),
|
||||
(cg.bool_, "touch_event"),
|
||||
],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_BUFFER_OVERFLOW, "add_buffer_overflow_event_callback"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await uart.register_uart_device(var, config)
|
||||
@@ -232,34 +254,4 @@ async def to_code(config):
|
||||
|
||||
await display.register_display(var, config)
|
||||
|
||||
for conf in config.get(CONF_ON_SETUP, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_setup_state_callback", [], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_SLEEP, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_sleep_state_callback", [], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_WAKE, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_wake_state_callback", [], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_PAGE, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_new_page_callback", [(cg.uint8, "x")], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_TOUCH, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_touch_event_callback",
|
||||
[
|
||||
(cg.uint8, "page_id"),
|
||||
(cg.uint8, "component_id"),
|
||||
(cg.bool_, "touch_event"),
|
||||
],
|
||||
conf,
|
||||
)
|
||||
for conf in config.get(CONF_ON_BUFFER_OVERFLOW, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_buffer_overflow_event_callback", [], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
@@ -243,12 +243,16 @@ def number_schema(
|
||||
return _NUMBER_SCHEMA.extend(schema)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_VALUE, "add_on_state_callback", [(float, "x")]
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.AUTOMATION)
|
||||
async def _build_number_automations(var, config):
|
||||
for conf in config.get(CONF_ON_VALUE, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_state_callback", [(float, "x")], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
for conf in config.get(CONF_ON_VALUE_RANGE, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await cg.register_component(trigger, conf)
|
||||
|
||||
@@ -105,6 +105,14 @@ async def online_image_action_to_code(config, action_id, template_arg, args):
|
||||
return var
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_DOWNLOAD_FINISHED, "add_on_finished_callback", [(bool, "cached")]
|
||||
),
|
||||
automation.CallbackAutomation(CONF_ON_ERROR, "add_on_error_callback"),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
# Use the enhanced helper function to get all runtime image parameters
|
||||
settings = await runtime_image.process_runtime_image_config(config)
|
||||
@@ -139,12 +147,4 @@ async def to_code(config):
|
||||
else:
|
||||
cg.add(var.add_request_header(key, value))
|
||||
|
||||
for conf in config.get(CONF_ON_DOWNLOAD_FINISHED, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_finished_callback", [(bool, "cached")], conf
|
||||
)
|
||||
|
||||
for conf in config.get(CONF_ON_ERROR, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_error_callback", [], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
@@ -49,6 +49,13 @@ def CONFIG_SCHEMA(conf):
|
||||
)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_FINISHED_WRITE, "add_on_finished_write_callback"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def setup_pn532(var, config):
|
||||
await cg.register_component(var, config)
|
||||
|
||||
@@ -66,10 +73,7 @@ async def setup_pn532(var, config):
|
||||
trigger, [(cg.std_string, "x"), (nfc.NfcTag, "tag")], conf
|
||||
)
|
||||
|
||||
for conf in config.get(CONF_ON_FINISHED_WRITE, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_finished_write_callback", [], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
@automation.register_condition(
|
||||
|
||||
@@ -164,6 +164,16 @@ async def pn7150_simple_action_to_code(config, action_id, template_arg, args):
|
||||
return var
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_EMULATED_TAG_SCAN, "add_on_emulated_tag_scan_callback"
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_FINISHED_WRITE, "add_on_finished_write_callback"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def setup_pn7150(var, config):
|
||||
await cg.register_component(var, config)
|
||||
|
||||
@@ -194,15 +204,7 @@ async def setup_pn7150(var, config):
|
||||
trigger, [(cg.std_string, "x"), (nfc.NfcTag, "tag")], conf
|
||||
)
|
||||
|
||||
for conf in config.get(CONF_ON_EMULATED_TAG_SCAN, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_emulated_tag_scan_callback", [], conf
|
||||
)
|
||||
|
||||
for conf in config.get(CONF_ON_FINISHED_WRITE, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_finished_write_callback", [], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
@automation.register_condition(
|
||||
|
||||
@@ -168,6 +168,16 @@ async def pn7160_simple_action_to_code(config, action_id, template_arg, args):
|
||||
return var
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_EMULATED_TAG_SCAN, "add_on_emulated_tag_scan_callback"
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_FINISHED_WRITE, "add_on_finished_write_callback"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def setup_pn7160(var, config):
|
||||
await cg.register_component(var, config)
|
||||
|
||||
@@ -206,15 +216,7 @@ async def setup_pn7160(var, config):
|
||||
trigger, [(cg.std_string, "x"), (nfc.NfcTag, "tag")], conf
|
||||
)
|
||||
|
||||
for conf in config.get(CONF_ON_EMULATED_TAG_SCAN, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_emulated_tag_scan_callback", [], conf
|
||||
)
|
||||
|
||||
for conf in config.get(CONF_ON_FINISHED_WRITE, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_finished_write_callback", [], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
@automation.register_condition(
|
||||
|
||||
@@ -67,22 +67,26 @@ CONFIG_SCHEMA = cv.All(
|
||||
)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_CODE_RECEIVED,
|
||||
"add_on_code_received_callback",
|
||||
[(RFBridgeData, "data")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_ADVANCED_CODE_RECEIVED,
|
||||
"add_on_advanced_code_received_callback",
|
||||
[(RFBridgeAdvancedData, "data")],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await uart.register_uart_device(var, config)
|
||||
|
||||
for conf in config.get(CONF_ON_CODE_RECEIVED, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_code_received_callback", [(RFBridgeData, "data")], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_ADVANCED_CODE_RECEIVED, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_on_advanced_code_received_callback",
|
||||
[(RFBridgeAdvancedData, "data")],
|
||||
conf,
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
RFBRIDGE_SEND_CODE_SCHEMA = cv.Schema(
|
||||
|
||||
@@ -84,6 +84,14 @@ CONFIG_SCHEMA = cv.All(
|
||||
)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(CONF_ON_CLOCKWISE, "add_on_clockwise_callback"),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_ANTICLOCKWISE, "add_on_anticlockwise_callback"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = await sensor.new_sensor(config)
|
||||
await cg.register_component(var, config)
|
||||
@@ -104,14 +112,7 @@ async def to_code(config):
|
||||
if CONF_MAX_VALUE in config:
|
||||
cg.add(var.set_max_value(config[CONF_MAX_VALUE]))
|
||||
|
||||
for conf in config.get(CONF_ON_CLOCKWISE, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_clockwise_callback", [], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_ANTICLOCKWISE, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_anticlockwise_callback", [], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
|
||||
@@ -71,6 +71,13 @@ FINAL_VALIDATE_SCHEMA = cv.Schema(
|
||||
)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_FINISHED_PLAYBACK, "add_on_finished_playback_callback"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
@@ -86,10 +93,7 @@ async def to_code(config):
|
||||
|
||||
cg.add(var.set_gain(config[CONF_GAIN]))
|
||||
|
||||
for conf in config.get(CONF_ON_FINISHED_PLAYBACK, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_finished_playback_callback", [], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
|
||||
@@ -65,18 +65,22 @@ async def safe_mode_mark_successful_to_code(config, action_id, template_arg, arg
|
||||
return var
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(CONF_ON_SAFE_MODE, "add_on_safe_mode_callback"),
|
||||
)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.APPLICATION)
|
||||
async def to_code(config):
|
||||
if not config[CONF_DISABLED]:
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
|
||||
if on_safe_mode_config := config.get(CONF_ON_SAFE_MODE):
|
||||
if config.get(CONF_ON_SAFE_MODE):
|
||||
cg.add_define("USE_SAFE_MODE_CALLBACK")
|
||||
for conf in on_safe_mode_config:
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_safe_mode_callback", [], conf
|
||||
)
|
||||
await automation.build_callback_automations(
|
||||
var, config, _CALLBACK_AUTOMATIONS
|
||||
)
|
||||
|
||||
condition = var.should_enter_safe_mode(
|
||||
config[CONF_NUM_ATTEMPTS],
|
||||
|
||||
@@ -892,16 +892,19 @@ async def build_filters(config):
|
||||
return await cg.build_registry_list(FILTER_REGISTRY, config)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_VALUE, "add_on_state_callback", [(float, "x")]
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_RAW_VALUE, "add_on_raw_state_callback", [(float, "x")]
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.AUTOMATION)
|
||||
async def _build_sensor_automations(var, config):
|
||||
for conf_key, callback in (
|
||||
(CONF_ON_VALUE, "add_on_state_callback"),
|
||||
(CONF_ON_RAW_VALUE, "add_on_raw_state_callback"),
|
||||
):
|
||||
for conf in config.get(conf_key, []):
|
||||
await automation.build_callback_automation(
|
||||
var, callback, [(float, "x")], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
for conf in config.get(CONF_ON_VALUE_RANGE, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await cg.register_component(trigger, conf)
|
||||
|
||||
@@ -48,34 +48,37 @@ FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
|
||||
)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_SMS_RECEIVED,
|
||||
"add_on_sms_received_callback",
|
||||
[(cg.std_string, "message"), (cg.std_string, "sender")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_INCOMING_CALL,
|
||||
"add_on_incoming_call_callback",
|
||||
[(cg.std_string, "caller_id")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_CALL_CONNECTED, "add_on_call_connected_callback"
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_CALL_DISCONNECTED, "add_on_call_disconnected_callback"
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_USSD_RECEIVED,
|
||||
"add_on_ussd_received_callback",
|
||||
[(cg.std_string, "ussd")],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await uart.register_uart_device(var, config)
|
||||
|
||||
for conf in config.get(CONF_ON_SMS_RECEIVED, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_on_sms_received_callback",
|
||||
[(cg.std_string, "message"), (cg.std_string, "sender")],
|
||||
conf,
|
||||
)
|
||||
for conf in config.get(CONF_ON_INCOMING_CALL, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_incoming_call_callback", [(cg.std_string, "caller_id")], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_CALL_CONNECTED, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_call_connected_callback", [], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_CALL_DISCONNECTED, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_call_disconnected_callback", [], conf
|
||||
)
|
||||
for conf in config.get(CONF_ON_USSD_RECEIVED, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_ussd_received_callback", [(cg.std_string, "ussd")], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
SIM800L_SEND_SMS_SCHEMA = cv.Schema(
|
||||
|
||||
@@ -31,23 +31,26 @@ CONFIG_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_DATA,
|
||||
"add_on_data_callback",
|
||||
[
|
||||
(
|
||||
cg.std_vector.template(cg.uint8).operator("ref").operator("const"),
|
||||
"bytes",
|
||||
),
|
||||
(cg.bool_, "valid"),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await uart.register_uart_device(var, config)
|
||||
for conf in config.get(CONF_ON_DATA, []):
|
||||
await automation.build_callback_automation(
|
||||
var,
|
||||
"add_on_data_callback",
|
||||
[
|
||||
(
|
||||
cg.std_vector.template(cg.uint8).operator("ref").operator("const"),
|
||||
"bytes",
|
||||
),
|
||||
(cg.bool_, "valid"),
|
||||
],
|
||||
conf,
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
def obis_code(value):
|
||||
|
||||
@@ -121,17 +121,26 @@ def switch_schema(
|
||||
return _SWITCH_SCHEMA.extend(schema)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_STATE, "add_on_state_callback", [(bool, "x")]
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_TURN_ON,
|
||||
"add_on_state_callback",
|
||||
forwarder=automation.TriggerOnTrueForwarder,
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_TURN_OFF,
|
||||
"add_on_state_callback",
|
||||
forwarder=automation.TriggerOnFalseForwarder,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.AUTOMATION)
|
||||
async def _build_switch_automations(var, config):
|
||||
for conf_key, args, forwarder in (
|
||||
(CONF_ON_STATE, [(bool, "x")], None),
|
||||
(CONF_ON_TURN_ON, [], automation.TriggerOnTrueForwarder),
|
||||
(CONF_ON_TURN_OFF, [], automation.TriggerOnFalseForwarder),
|
||||
):
|
||||
for conf in config.get(conf_key, []):
|
||||
await automation.build_callback_automation(
|
||||
var, "add_on_state_callback", args, conf, forwarder=forwarder
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
@setup_entity("switch")
|
||||
|
||||
@@ -184,16 +184,19 @@ async def build_filters(config):
|
||||
return await cg.build_registry_list(FILTER_REGISTRY, config)
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_VALUE, "add_on_state_callback", [(cg.std_string, "x")]
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_RAW_VALUE, "add_on_raw_state_callback", [(cg.std_string, "x")]
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.AUTOMATION)
|
||||
async def _build_text_sensor_automations(var, config):
|
||||
for conf_key, callback in (
|
||||
(CONF_ON_VALUE, "add_on_state_callback"),
|
||||
(CONF_ON_RAW_VALUE, "add_on_raw_state_callback"),
|
||||
):
|
||||
for conf in config.get(conf_key, []):
|
||||
await automation.build_callback_automation(
|
||||
var, callback, [(cg.std_string, "x")], conf
|
||||
)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
@setup_entity("text_sensor")
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
"""Tests for esphome.automation module."""
|
||||
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import AsyncMock, call, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome.automation import (
|
||||
CallbackAutomation,
|
||||
TriggerForwarder,
|
||||
TriggerOnFalseForwarder,
|
||||
TriggerOnTrueForwarder,
|
||||
build_callback_automations,
|
||||
has_non_synchronous_actions,
|
||||
)
|
||||
from esphome.cpp_generator import MockObj, RawExpression
|
||||
@@ -254,3 +256,222 @@ def test_trigger_forwarder_custom_type() -> None:
|
||||
custom = MockObj("MyForwarder", "")
|
||||
result = _build_forwarder("auto_1", [], forwarder=custom)
|
||||
assert result == "MyForwarder{auto_1}"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_build_callback() -> Generator[AsyncMock]:
|
||||
"""Patch build_callback_automation to capture calls."""
|
||||
with patch(
|
||||
"esphome.automation.build_callback_automation", new_callable=AsyncMock
|
||||
) as mock:
|
||||
yield mock
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_callback_automations_empty_entries(
|
||||
mock_build_callback: AsyncMock,
|
||||
) -> None:
|
||||
"""No entries means no calls."""
|
||||
parent = MockObj("var", "->")
|
||||
await build_callback_automations(parent, {}, ())
|
||||
mock_build_callback.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_callback_automations_missing_config_key(
|
||||
mock_build_callback: AsyncMock,
|
||||
) -> None:
|
||||
"""Entry present but config key missing -- no calls."""
|
||||
parent = MockObj("var", "->")
|
||||
await build_callback_automations(
|
||||
parent,
|
||||
{},
|
||||
(CallbackAutomation("on_state", "add_on_state_callback", [(bool, "x")]),),
|
||||
)
|
||||
mock_build_callback.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_callback_automations_single_entry(
|
||||
mock_build_callback: AsyncMock,
|
||||
) -> None:
|
||||
"""Single entry with one config triggers one call."""
|
||||
parent = MockObj("var", "->")
|
||||
conf: dict[str, object] = {"automation_id": "auto_1", "then": []}
|
||||
config: dict[str, list[dict[str, object]]] = {"on_state": [conf]}
|
||||
await build_callback_automations(
|
||||
parent,
|
||||
config,
|
||||
(CallbackAutomation("on_state", "add_on_state_callback", [(bool, "x")]),),
|
||||
)
|
||||
mock_build_callback.assert_called_once_with(
|
||||
parent, "add_on_state_callback", [(bool, "x")], conf, forwarder=None
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_callback_automations_multiple_configs(
|
||||
mock_build_callback: AsyncMock,
|
||||
) -> None:
|
||||
"""Single entry with multiple configs triggers multiple calls."""
|
||||
parent = MockObj("var", "->")
|
||||
conf1: dict[str, object] = {"automation_id": "auto_1", "then": []}
|
||||
conf2: dict[str, object] = {"automation_id": "auto_2", "then": []}
|
||||
config: dict[str, list[dict[str, object]]] = {"on_state": [conf1, conf2]}
|
||||
await build_callback_automations(
|
||||
parent,
|
||||
config,
|
||||
(CallbackAutomation("on_state", "add_on_state_callback", [(bool, "x")]),),
|
||||
)
|
||||
assert mock_build_callback.call_count == 2
|
||||
mock_build_callback.assert_any_call(
|
||||
parent, "add_on_state_callback", [(bool, "x")], conf1, forwarder=None
|
||||
)
|
||||
mock_build_callback.assert_any_call(
|
||||
parent, "add_on_state_callback", [(bool, "x")], conf2, forwarder=None
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_callback_automations_multiple_entries(
|
||||
mock_build_callback: AsyncMock,
|
||||
) -> None:
|
||||
"""Multiple entries each with one config."""
|
||||
parent = MockObj("var", "->")
|
||||
conf_a: dict[str, object] = {"automation_id": "auto_a", "then": []}
|
||||
conf_b: dict[str, object] = {"automation_id": "auto_b", "then": []}
|
||||
config: dict[str, list[dict[str, object]]] = {
|
||||
"on_value": [conf_a],
|
||||
"on_raw_value": [conf_b],
|
||||
}
|
||||
await build_callback_automations(
|
||||
parent,
|
||||
config,
|
||||
(
|
||||
CallbackAutomation("on_value", "add_on_value_callback", [(float, "x")]),
|
||||
CallbackAutomation(
|
||||
"on_raw_value", "add_on_raw_value_callback", [(float, "x")]
|
||||
),
|
||||
),
|
||||
)
|
||||
assert mock_build_callback.call_count == 2
|
||||
assert mock_build_callback.call_args_list == [
|
||||
call(parent, "add_on_value_callback", [(float, "x")], conf_a, forwarder=None),
|
||||
call(
|
||||
parent, "add_on_raw_value_callback", [(float, "x")], conf_b, forwarder=None
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_callback_automations_with_forwarder(
|
||||
mock_build_callback: AsyncMock,
|
||||
) -> None:
|
||||
"""Entry with forwarder passes it through."""
|
||||
parent = MockObj("var", "->")
|
||||
conf: dict[str, object] = {"automation_id": "auto_1", "then": []}
|
||||
config: dict[str, list[dict[str, object]]] = {"on_press": [conf]}
|
||||
await build_callback_automations(
|
||||
parent,
|
||||
config,
|
||||
(
|
||||
CallbackAutomation(
|
||||
"on_press", "add_on_state_callback", forwarder=TriggerOnTrueForwarder
|
||||
),
|
||||
),
|
||||
)
|
||||
mock_build_callback.assert_called_once_with(
|
||||
parent, "add_on_state_callback", [], conf, forwarder=TriggerOnTrueForwarder
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_callback_automations_mixed_entries(
|
||||
mock_build_callback: AsyncMock,
|
||||
) -> None:
|
||||
"""Mix of entries with args, forwarders, and defaults."""
|
||||
parent = MockObj("var", "->")
|
||||
conf_state: dict[str, object] = {"automation_id": "auto_1", "then": []}
|
||||
conf_press: dict[str, object] = {"automation_id": "auto_2", "then": []}
|
||||
conf_release: dict[str, object] = {"automation_id": "auto_3", "then": []}
|
||||
config: dict[str, list[dict[str, object]]] = {
|
||||
"on_state": [conf_state],
|
||||
"on_press": [conf_press],
|
||||
"on_release": [conf_release],
|
||||
}
|
||||
await build_callback_automations(
|
||||
parent,
|
||||
config,
|
||||
(
|
||||
CallbackAutomation("on_state", "add_on_state_callback", [(bool, "x")]),
|
||||
CallbackAutomation(
|
||||
"on_press", "add_on_state_callback", forwarder=TriggerOnTrueForwarder
|
||||
),
|
||||
CallbackAutomation(
|
||||
"on_release", "add_on_state_callback", forwarder=TriggerOnFalseForwarder
|
||||
),
|
||||
),
|
||||
)
|
||||
assert mock_build_callback.call_count == 3
|
||||
assert mock_build_callback.call_args_list == [
|
||||
call(
|
||||
parent, "add_on_state_callback", [(bool, "x")], conf_state, forwarder=None
|
||||
),
|
||||
call(
|
||||
parent,
|
||||
"add_on_state_callback",
|
||||
[],
|
||||
conf_press,
|
||||
forwarder=TriggerOnTrueForwarder,
|
||||
),
|
||||
call(
|
||||
parent,
|
||||
"add_on_state_callback",
|
||||
[],
|
||||
conf_release,
|
||||
forwarder=TriggerOnFalseForwarder,
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_callback_automations_skips_missing_keys(
|
||||
mock_build_callback: AsyncMock,
|
||||
) -> None:
|
||||
"""Entries whose config keys are absent are silently skipped."""
|
||||
parent = MockObj("var", "->")
|
||||
conf: dict[str, object] = {"automation_id": "auto_1", "then": []}
|
||||
config: dict[str, list[dict[str, object]]] = {"on_press": [conf]}
|
||||
await build_callback_automations(
|
||||
parent,
|
||||
config,
|
||||
(
|
||||
CallbackAutomation(
|
||||
"on_press", "add_on_state_callback", forwarder=TriggerOnTrueForwarder
|
||||
),
|
||||
CallbackAutomation(
|
||||
"on_release", "add_on_state_callback", forwarder=TriggerOnFalseForwarder
|
||||
),
|
||||
),
|
||||
)
|
||||
mock_build_callback.assert_called_once_with(
|
||||
parent, "add_on_state_callback", [], conf, forwarder=TriggerOnTrueForwarder
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_callback_automations_defaults(
|
||||
mock_build_callback: AsyncMock,
|
||||
) -> None:
|
||||
"""Verify CallbackAutomation with only required fields defaults args=[] and forwarder=None."""
|
||||
parent = MockObj("var", "->")
|
||||
conf: dict[str, object] = {"automation_id": "auto_1", "then": []}
|
||||
config: dict[str, list[dict[str, object]]] = {"on_press": [conf]}
|
||||
await build_callback_automations(
|
||||
parent,
|
||||
config,
|
||||
(CallbackAutomation("on_press", "add_on_press_callback"),),
|
||||
)
|
||||
mock_build_callback.assert_called_once_with(
|
||||
parent, "add_on_press_callback", [], conf, forwarder=None
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user