mirror of
https://github.com/esphome/esphome.git
synced 2026-10-22 22:06:12 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
937b73c8f1 |
@@ -737,9 +737,7 @@ file does, and it is the authority when they disagree. The most useful starting
|
||||
|
||||
6. **Avoid `std::deque`:** It allocates in 512-byte blocks regardless of element size, guaranteeing at least 512 bytes of RAM usage immediately. This is a major source of crashes on memory-constrained devices.
|
||||
|
||||
7. **Never use `new (std::nothrow)`:** On ESP-IDF exceptions are disabled, so a failed nothrow allocation aborts instead of returning `nullptr`. Use `RAMAllocator` from `esphome/core/helpers.h`; CI rejects `std::nothrow`.
|
||||
|
||||
8. **Detection:** Look for these patterns in compiler output:
|
||||
7. **Detection:** Look for these patterns in compiler output:
|
||||
- Large code sections with STL symbols (vector, map, set)
|
||||
- `alloc`, `realloc`, `dealloc` in symbol names
|
||||
- `_M_realloc_insert`, `_M_default_append` (vector reallocation)
|
||||
|
||||
@@ -762,7 +762,6 @@ def _wrap_to_code(name, comp, yaml_util):
|
||||
|
||||
@functools.wraps(comp.to_code)
|
||||
async def wrapped(conf):
|
||||
cg.add(cg.ComponentMarker(name))
|
||||
cg.add(cg.LineComment(f"{name}:"))
|
||||
if comp.config_schema is not None:
|
||||
# sort_keys: voluptuous fills defaults in set order, so an
|
||||
@@ -1344,12 +1343,8 @@ def _upload_via_native_api(
|
||||
# fall back to a plaintext upload
|
||||
noise_psk = None
|
||||
plaintext_fallback = False
|
||||
allow_plaintext_upload = False
|
||||
if (encryption_conf := ota_conf.get(CONF_ENCRYPTION)) is not None:
|
||||
noise_psk = encryption_conf.get(CONF_KEY)
|
||||
allow_plaintext_upload = bool(
|
||||
encryption_conf.get(espota2.CONF_ALLOW_PLAINTEXT_UPLOAD)
|
||||
)
|
||||
if not noise_psk:
|
||||
raise EsphomeError(
|
||||
"OTA encryption is configured but no key was resolved; "
|
||||
@@ -1400,7 +1395,6 @@ def _upload_via_native_api(
|
||||
ota_type,
|
||||
noise_psk,
|
||||
plaintext_fallback=plaintext_fallback,
|
||||
allow_plaintext_upload=allow_plaintext_upload,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ from __future__ import annotations
|
||||
from collections import defaultdict
|
||||
from collections.abc import Callable
|
||||
import heapq
|
||||
import json
|
||||
from operator import itemgetter
|
||||
from pathlib import Path
|
||||
import sys
|
||||
@@ -43,7 +42,7 @@ class MemoryAnalyzerCLI(MemoryAnalyzer):
|
||||
|
||||
# Symbol size threshold for detailed analysis
|
||||
SYMBOL_SIZE_THRESHOLD: int = (
|
||||
10 # Show symbols larger than this in detailed analysis
|
||||
100 # Show symbols larger than this in detailed analysis
|
||||
)
|
||||
# Lower threshold for RAM symbols (RAM is more constrained)
|
||||
RAM_SYMBOL_SIZE_THRESHOLD: int = 24
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
# pylint: disable=unused-import
|
||||
from esphome.cpp_generator import ( # noqa: F401
|
||||
ArrayInitializer,
|
||||
ComponentMarker,
|
||||
Expression,
|
||||
FlashStringLiteral,
|
||||
LineComment,
|
||||
|
||||
@@ -41,6 +41,10 @@ StateAnyForwarder = alarm_control_panel_ns.class_("StateAnyForwarder")
|
||||
StateEnterForwarder = alarm_control_panel_ns.class_("StateEnterForwarder")
|
||||
AlarmControlPanelState = alarm_control_panel_ns.enum("AlarmControlPanelState")
|
||||
|
||||
PendingAction = alarm_control_panel_ns.class_("PendingAction", automation.Action)
|
||||
TriggeredAction = alarm_control_panel_ns.class_("TriggeredAction", automation.Action)
|
||||
ChimeAction = alarm_control_panel_ns.class_("ChimeAction", automation.Action)
|
||||
ReadyAction = alarm_control_panel_ns.class_("ReadyAction", automation.Action)
|
||||
|
||||
AlarmControlPanelCondition = alarm_control_panel_ns.class_(
|
||||
"AlarmControlPanelCondition", automation.Condition
|
||||
@@ -204,30 +208,65 @@ for _name, _arm in (
|
||||
)
|
||||
|
||||
|
||||
for _name, _call in (
|
||||
("alarm_control_panel.pending", "pending()"),
|
||||
("alarm_control_panel.triggered", "triggered()"),
|
||||
):
|
||||
automation.register_apply_action(
|
||||
_name,
|
||||
ALARM_CONTROL_PANEL_ACTION_SCHEMA,
|
||||
automation.ApplyCall(_call),
|
||||
call="make_call",
|
||||
)
|
||||
@automation.register_action(
|
||||
"alarm_control_panel.pending",
|
||||
PendingAction,
|
||||
ALARM_CONTROL_PANEL_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def alarm_action_pending_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
automation.register_simple_condition(
|
||||
@automation.register_action(
|
||||
"alarm_control_panel.triggered",
|
||||
TriggeredAction,
|
||||
ALARM_CONTROL_PANEL_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def alarm_action_trigger_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"alarm_control_panel.chime",
|
||||
ChimeAction,
|
||||
ALARM_CONTROL_PANEL_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def alarm_action_chime_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"alarm_control_panel.ready",
|
||||
ReadyAction,
|
||||
ALARM_CONTROL_PANEL_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
@automation.register_condition(
|
||||
"alarm_control_panel.ready",
|
||||
AlarmControlPanelCondition,
|
||||
ALARM_CONTROL_PANEL_CONDITION_SCHEMA,
|
||||
)
|
||||
async def alarm_action_ready_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
automation.register_simple_condition(
|
||||
@automation.register_condition(
|
||||
"alarm_control_panel.is_armed",
|
||||
AlarmControlPanelCondition,
|
||||
ALARM_CONTROL_PANEL_CONDITION_SCHEMA,
|
||||
)
|
||||
async def alarm_control_panel_is_armed_to_code(
|
||||
config, condition_id, template_arg, args
|
||||
):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(condition_id, template_arg, paren)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.CORE)
|
||||
|
||||
@@ -27,6 +27,26 @@ static_assert(std::is_trivially_copyable_v<StateAnyForwarder>);
|
||||
static_assert(sizeof(StateEnterForwarder<ACP_STATE_TRIGGERED>) <= sizeof(void *));
|
||||
static_assert(std::is_trivially_copyable_v<StateEnterForwarder<ACP_STATE_TRIGGERED>>);
|
||||
|
||||
template<typename... Ts> class PendingAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit PendingAction(AlarmControlPanel *alarm_control_panel) : alarm_control_panel_(alarm_control_panel) {}
|
||||
|
||||
void play(const Ts &...x) override { this->alarm_control_panel_->make_call().pending().perform(); }
|
||||
|
||||
protected:
|
||||
AlarmControlPanel *alarm_control_panel_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class TriggeredAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit TriggeredAction(AlarmControlPanel *alarm_control_panel) : alarm_control_panel_(alarm_control_panel) {}
|
||||
|
||||
void play(const Ts &...x) override { this->alarm_control_panel_->make_call().triggered().perform(); }
|
||||
|
||||
protected:
|
||||
AlarmControlPanel *alarm_control_panel_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class AlarmControlPanelCondition final : public Condition<Ts...> {
|
||||
public:
|
||||
AlarmControlPanelCondition(AlarmControlPanel *parent) : parent_(parent) {}
|
||||
|
||||
@@ -655,7 +655,7 @@ async def to_code(config):
|
||||
cg.add_global(binary_sensor_ns.using)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"binary_sensor.invalidate_state",
|
||||
BinarySensorInvalidateAction,
|
||||
cv.maybe_simple_value(
|
||||
@@ -666,6 +666,9 @@ automation.register_simple_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def binary_sensor_invalidate_state_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
# automation.cpp only implements the click/double_click/multi_click triggers
|
||||
|
||||
@@ -32,6 +32,8 @@ from esphome.const import (
|
||||
UNIT_VOLT,
|
||||
UNIT_WATT,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
# Import ICONS not included in esphome's const.py, from the local components const.py
|
||||
@@ -136,7 +138,7 @@ FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"bl0906.reset_energy",
|
||||
ResetEnergyAction,
|
||||
maybe_simple_id(
|
||||
@@ -146,6 +148,15 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def reset_energy_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
|
||||
@@ -207,20 +207,26 @@ BLE_REMOVE_BOND_ACTION_SCHEMA = cv.Schema(
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"ble_client.disconnect",
|
||||
BLEDisconnectAction,
|
||||
BLE_CONNECT_ACTION_SCHEMA,
|
||||
synchronous=False,
|
||||
)
|
||||
async def ble_disconnect_to_code(config, action_id, template_arg, args):
|
||||
parent = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, parent)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"ble_client.connect",
|
||||
BLEConnectAction,
|
||||
BLE_CONNECT_ACTION_SCHEMA,
|
||||
synchronous=False,
|
||||
)
|
||||
async def ble_connect_to_code(config, action_id, template_arg, args):
|
||||
parent = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, parent)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
@@ -322,12 +328,15 @@ async def passkey_reply_to_code(config, action_id, template_arg, args):
|
||||
return var
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"ble_client.remove_bond",
|
||||
BLERemoveBondAction,
|
||||
BLE_REMOVE_BOND_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def remove_bond_to_code(config, action_id, template_arg, args):
|
||||
parent = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, parent)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
|
||||
@@ -28,7 +28,7 @@ CONFIG_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"bm8563.write_time",
|
||||
WriteAction,
|
||||
automation.maybe_simple_id(
|
||||
@@ -38,6 +38,15 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def bm8563_write_time_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
@@ -64,7 +73,7 @@ async def bm8563_start_timer_to_code(
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"bm8563.read_time",
|
||||
ReadAction,
|
||||
automation.maybe_simple_id(
|
||||
@@ -74,6 +83,15 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def bm8563_read_time_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
|
||||
@@ -16,14 +16,14 @@ from esphome.const import (
|
||||
DEVICE_CLASS_RESTART,
|
||||
DEVICE_CLASS_UPDATE,
|
||||
)
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_device_class,
|
||||
setup_entity,
|
||||
)
|
||||
from esphome.cpp_generator import MockObj, MockObjClass
|
||||
from esphome.cpp_generator import MockObj, MockObjClass, TemplateArgsType
|
||||
from esphome.types import ConfigType, SafeExpType
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
@@ -40,6 +40,8 @@ button_ns = cg.esphome_ns.namespace("button")
|
||||
Button = button_ns.class_("Button", cg.EntityBase)
|
||||
ButtonPtr = Button.operator("ptr")
|
||||
|
||||
PressAction = button_ns.class_("PressAction", automation.Action)
|
||||
|
||||
validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_")
|
||||
|
||||
|
||||
@@ -121,9 +123,17 @@ BUTTON_PRESS_SCHEMA = maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
automation.register_apply_action(
|
||||
"button.press", BUTTON_PRESS_SCHEMA, automation.ApplyCall("press()")
|
||||
@automation.register_action(
|
||||
"button.press", PressAction, BUTTON_PRESS_SCHEMA, synchronous=True
|
||||
)
|
||||
async def button_press_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.CORE)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/button/button.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/component.h"
|
||||
|
||||
namespace esphome::button {
|
||||
|
||||
template<typename... Ts> class PressAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit PressAction(Button *button) : button_(button) {}
|
||||
|
||||
void play(const Ts &...x) override { this->button_->press(); }
|
||||
|
||||
protected:
|
||||
Button *button_;
|
||||
};
|
||||
|
||||
} // namespace esphome::button
|
||||
@@ -364,36 +364,22 @@ CC1101_ACTION_SCHEMA = cv.Schema(
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
"cc1101.begin_tx",
|
||||
BeginTxAction,
|
||||
CC1101_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"cc1101.begin_tx", BeginTxAction, CC1101_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
"cc1101.begin_rx",
|
||||
BeginRxAction,
|
||||
CC1101_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"cc1101.begin_rx", BeginRxAction, CC1101_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
"cc1101.reset",
|
||||
ResetAction,
|
||||
CC1101_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"cc1101.reset", ResetAction, CC1101_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
"cc1101.set_idle",
|
||||
SetIdleAction,
|
||||
CC1101_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"cc1101.set_idle", SetIdleAction, CC1101_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
async def cc1101_action_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
def validate_raw_data(value):
|
||||
|
||||
@@ -13,6 +13,8 @@ from esphome.const import (
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_PARTS_PER_MILLION,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
DEPENDENCIES = ["uart"]
|
||||
@@ -70,9 +72,18 @@ CALIBRATION_ACTION_SCHEMA = maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"cm1106.calibrate_zero",
|
||||
CM1106CalibrateZeroAction,
|
||||
CALIBRATION_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def cm1106_calibration_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
"""Service code generation entry point."""
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
@@ -17,6 +17,8 @@ from esphome.const import (
|
||||
UNIT_VOLT,
|
||||
UNIT_WATT,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@balrog-kun"]
|
||||
@@ -129,7 +131,7 @@ async def to_code(config: ConfigType) -> None:
|
||||
cg.add(var.set_power_sensor(sens))
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"cs5460a.restart",
|
||||
CS5460ARestartAction,
|
||||
maybe_simple_id(
|
||||
@@ -139,3 +141,11 @@ automation.register_simple_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def restart_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
@@ -214,6 +214,16 @@ def _validate_sleep_duration(value: core.TimePeriod) -> core.TimePeriod:
|
||||
deep_sleep_ns = cg.esphome_ns.namespace("deep_sleep")
|
||||
DeepSleepComponent = deep_sleep_ns.class_("DeepSleepComponent", cg.Component)
|
||||
EnterDeepSleepAction = deep_sleep_ns.class_("EnterDeepSleepAction", automation.Action)
|
||||
PreventDeepSleepAction = deep_sleep_ns.class_(
|
||||
"PreventDeepSleepAction",
|
||||
automation.Action,
|
||||
cg.Parented.template(DeepSleepComponent),
|
||||
)
|
||||
AllowDeepSleepAction = deep_sleep_ns.class_(
|
||||
"AllowDeepSleepAction",
|
||||
automation.Action,
|
||||
cg.Parented.template(DeepSleepComponent),
|
||||
)
|
||||
|
||||
WakeupPinMode = deep_sleep_ns.enum("WakeupPinMode")
|
||||
WAKEUP_PIN_MODES = {
|
||||
@@ -480,15 +490,27 @@ async def deep_sleep_enter_to_code(
|
||||
return var
|
||||
|
||||
|
||||
for _name, _call in (
|
||||
("deep_sleep.prevent", "prevent_deep_sleep()"),
|
||||
("deep_sleep.allow", "allow_deep_sleep()"),
|
||||
):
|
||||
automation.register_apply_action(
|
||||
_name,
|
||||
automation.maybe_simple_id(DEEP_SLEEP_ACTION_SCHEMA),
|
||||
automation.ApplyCall(_call),
|
||||
)
|
||||
@automation.register_action(
|
||||
"deep_sleep.prevent",
|
||||
PreventDeepSleepAction,
|
||||
automation.maybe_simple_id(DEEP_SLEEP_ACTION_SCHEMA),
|
||||
synchronous=True,
|
||||
)
|
||||
@automation.register_action(
|
||||
"deep_sleep.allow",
|
||||
AllowDeepSleepAction,
|
||||
automation.maybe_simple_id(DEEP_SLEEP_ACTION_SCHEMA),
|
||||
synchronous=True,
|
||||
)
|
||||
async def deep_sleep_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
FILTER_SOURCE_FILES = filter_source_files_from_platform(
|
||||
|
||||
@@ -121,6 +121,8 @@ class Ext1WakeTrigger : public Trigger<>, public Component {
|
||||
|
||||
template<typename... Ts> class EnterDeepSleepAction;
|
||||
|
||||
template<typename... Ts> class PreventDeepSleepAction;
|
||||
|
||||
/** This component allows setting up the node to go into deep sleep mode to conserve battery.
|
||||
*
|
||||
* To set this component up, first set *when* the deep sleep should trigger using set_run_cycles
|
||||
@@ -296,4 +298,15 @@ template<typename... Ts> class EnterDeepSleepAction final : public Action<Ts...>
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename... Ts>
|
||||
class PreventDeepSleepAction final : public Action<Ts...>, public Parented<DeepSleepComponent> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->prevent_deep_sleep(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class AllowDeepSleepAction final : public Action<Ts...>, public Parented<DeepSleepComponent> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->allow_deep_sleep(); }
|
||||
};
|
||||
|
||||
} // namespace esphome::deep_sleep
|
||||
|
||||
@@ -199,7 +199,7 @@ automation.register_apply_action(
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_condition(
|
||||
@automation.register_condition(
|
||||
"dfplayer.is_playing",
|
||||
DFPlayerIsPlayingCondition,
|
||||
cv.Schema(
|
||||
@@ -208,3 +208,7 @@ automation.register_parented_condition(
|
||||
}
|
||||
),
|
||||
)
|
||||
async def dfplayer_is_playing_to_code(config, condition_id, template_arg, args):
|
||||
var = cg.new_Pvariable(condition_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
@@ -49,7 +49,7 @@ async def to_code(config: ConfigType) -> None:
|
||||
await uart.register_uart_device(var, config)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"dfrobot_sen0395.reset",
|
||||
DfrobotSen0395ResetAction,
|
||||
maybe_simple_id(
|
||||
@@ -59,6 +59,16 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def dfrobot_sen0395_reset_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
|
||||
return var
|
||||
|
||||
|
||||
def range_segment_list(input: Any) -> list:
|
||||
|
||||
@@ -55,6 +55,18 @@ MenuItemSwitch = display_menu_base_ns.class_("MenuItemSwitch")
|
||||
MenuItemCommand = display_menu_base_ns.class_("MenuItemCommand")
|
||||
MenuItemCustom = display_menu_base_ns.class_("MenuItemCustom")
|
||||
|
||||
UpAction = display_menu_base_ns.class_("UpAction", automation.Action)
|
||||
DownAction = display_menu_base_ns.class_("DownAction", automation.Action)
|
||||
LeftAction = display_menu_base_ns.class_("LeftAction", automation.Action)
|
||||
RightAction = display_menu_base_ns.class_("RightAction", automation.Action)
|
||||
EnterAction = display_menu_base_ns.class_("EnterAction", automation.Action)
|
||||
ShowAction = display_menu_base_ns.class_("ShowAction", automation.Action)
|
||||
HideAction = display_menu_base_ns.class_("HideAction", automation.Action)
|
||||
ShowMainAction = display_menu_base_ns.class_("ShowMainAction", automation.Action)
|
||||
|
||||
IsActiveCondition = display_menu_base_ns.class_(
|
||||
"IsActiveCondition", automation.Condition
|
||||
)
|
||||
|
||||
MenuItemType = display_menu_base_ns.enum("MenuItemType")
|
||||
|
||||
@@ -282,23 +294,85 @@ MENU_ACTION_SCHEMA = maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
for _name, _call in (
|
||||
("display_menu.up", "up()"),
|
||||
("display_menu.down", "down()"),
|
||||
("display_menu.left", "left()"),
|
||||
("display_menu.right", "right()"),
|
||||
("display_menu.enter", "enter()"),
|
||||
("display_menu.show", "show()"),
|
||||
("display_menu.hide", "hide()"),
|
||||
("display_menu.show_main", "show_main()"),
|
||||
):
|
||||
automation.register_apply_action(
|
||||
_name, MENU_ACTION_SCHEMA, automation.ApplyCall(_call)
|
||||
)
|
||||
|
||||
automation.register_apply_condition(
|
||||
"display_menu.is_active", MENU_ACTION_SCHEMA, "is_active()"
|
||||
@automation.register_action(
|
||||
"display_menu.up", UpAction, MENU_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
async def menu_up_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"display_menu.down", DownAction, MENU_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
async def menu_down_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"display_menu.left", LeftAction, MENU_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
async def menu_left_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"display_menu.right", RightAction, MENU_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
async def menu_right_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"display_menu.enter", EnterAction, MENU_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
async def menu_enter_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"display_menu.show", ShowAction, MENU_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
async def menu_show_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"display_menu.hide", HideAction, MENU_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
async def menu_hide_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"display_menu.show_main",
|
||||
ShowMainAction,
|
||||
MENU_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def menu_show_main_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_condition(
|
||||
"display_menu.is_active",
|
||||
IsActiveCondition,
|
||||
automation.maybe_simple_id(
|
||||
{
|
||||
cv.GenerateID(CONF_ID): cv.use_id(DisplayMenuComponent),
|
||||
}
|
||||
),
|
||||
)
|
||||
async def display_menu_is_active_to_code(config, condition_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(condition_id, template_arg, paren)
|
||||
|
||||
|
||||
async def menu_item_to_code(menu, config, parent):
|
||||
|
||||
@@ -5,6 +5,94 @@
|
||||
|
||||
namespace esphome::display_menu_base {
|
||||
|
||||
template<typename... Ts> class UpAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit UpAction(DisplayMenuComponent *menu) : menu_(menu) {}
|
||||
|
||||
void play(const Ts &...x) override { this->menu_->up(); }
|
||||
|
||||
protected:
|
||||
DisplayMenuComponent *menu_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class DownAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit DownAction(DisplayMenuComponent *menu) : menu_(menu) {}
|
||||
|
||||
void play(const Ts &...x) override { this->menu_->down(); }
|
||||
|
||||
protected:
|
||||
DisplayMenuComponent *menu_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class LeftAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit LeftAction(DisplayMenuComponent *menu) : menu_(menu) {}
|
||||
|
||||
void play(const Ts &...x) override { this->menu_->left(); }
|
||||
|
||||
protected:
|
||||
DisplayMenuComponent *menu_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class RightAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit RightAction(DisplayMenuComponent *menu) : menu_(menu) {}
|
||||
|
||||
void play(const Ts &...x) override { this->menu_->right(); }
|
||||
|
||||
protected:
|
||||
DisplayMenuComponent *menu_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class EnterAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit EnterAction(DisplayMenuComponent *menu) : menu_(menu) {}
|
||||
|
||||
void play(const Ts &...x) override { this->menu_->enter(); }
|
||||
|
||||
protected:
|
||||
DisplayMenuComponent *menu_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class ShowAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit ShowAction(DisplayMenuComponent *menu) : menu_(menu) {}
|
||||
|
||||
void play(const Ts &...x) override { this->menu_->show(); }
|
||||
|
||||
protected:
|
||||
DisplayMenuComponent *menu_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class HideAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit HideAction(DisplayMenuComponent *menu) : menu_(menu) {}
|
||||
|
||||
void play(const Ts &...x) override { this->menu_->hide(); }
|
||||
|
||||
protected:
|
||||
DisplayMenuComponent *menu_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class ShowMainAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit ShowMainAction(DisplayMenuComponent *menu) : menu_(menu) {}
|
||||
|
||||
void play(const Ts &...x) override { this->menu_->show_main(); }
|
||||
|
||||
protected:
|
||||
DisplayMenuComponent *menu_;
|
||||
};
|
||||
template<typename... Ts> class IsActiveCondition final : public Condition<Ts...> {
|
||||
public:
|
||||
explicit IsActiveCondition(DisplayMenuComponent *menu) : menu_(menu) {}
|
||||
bool check(const Ts &...x) override { return this->menu_->is_active(); }
|
||||
|
||||
protected:
|
||||
DisplayMenuComponent *menu_;
|
||||
};
|
||||
|
||||
class DisplayMenuOnEnterTrigger final : public Trigger<const MenuItem *> {
|
||||
public:
|
||||
explicit DisplayMenuOnEnterTrigger(MenuItem *parent) : parent_(parent) {
|
||||
|
||||
@@ -3,6 +3,8 @@ import esphome.codegen as cg
|
||||
from esphome.components import i2c, time
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@badbadc0ffee"]
|
||||
@@ -20,7 +22,7 @@ CONFIG_SCHEMA = time.TIME_SCHEMA.extend(
|
||||
).extend(i2c.i2c_device_schema(0x68))
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"ds1307.write_time",
|
||||
WriteAction,
|
||||
cv.Schema(
|
||||
@@ -30,9 +32,18 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def ds1307_write_time_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"ds1307.read_time",
|
||||
ReadAction,
|
||||
automation.maybe_simple_id(
|
||||
@@ -42,6 +53,15 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def ds1307_read_time_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
from esphome import automation
|
||||
from esphome.automation import (
|
||||
Action,
|
||||
Condition,
|
||||
maybe_simple_id,
|
||||
register_action,
|
||||
register_condition,
|
||||
)
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import binary_sensor, sensor
|
||||
import esphome.config_validation as cv
|
||||
@@ -23,13 +29,13 @@ duty_time_sensor_ns = cg.esphome_ns.namespace("duty_time_sensor")
|
||||
DutyTimeSensor = duty_time_sensor_ns.class_(
|
||||
"DutyTimeSensor", sensor.Sensor, cg.PollingComponent
|
||||
)
|
||||
BaseAction = duty_time_sensor_ns.class_("BaseAction", automation.Action, cg.Parented)
|
||||
BaseAction = duty_time_sensor_ns.class_("BaseAction", Action, cg.Parented)
|
||||
StartAction = duty_time_sensor_ns.class_("StartAction", BaseAction)
|
||||
StopAction = duty_time_sensor_ns.class_("StopAction", BaseAction)
|
||||
ResetAction = duty_time_sensor_ns.class_("ResetAction", BaseAction)
|
||||
SetAction = duty_time_sensor_ns.class_("SetAction", BaseAction)
|
||||
RunningCondition = duty_time_sensor_ns.class_(
|
||||
"RunningCondition", automation.Condition, cg.Parented
|
||||
"RunningCondition", Condition, cg.Parented
|
||||
)
|
||||
|
||||
|
||||
@@ -80,38 +86,56 @@ async def to_code(config: ConfigType) -> None:
|
||||
|
||||
# AUTOMATIONS
|
||||
|
||||
DUTY_TIME_ID_SCHEMA = automation.maybe_simple_id(
|
||||
DUTY_TIME_ID_SCHEMA = maybe_simple_id(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.use_id(DutyTimeSensor),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
"sensor.duty_time.start",
|
||||
StartAction,
|
||||
DUTY_TIME_ID_SCHEMA,
|
||||
synchronous=True,
|
||||
@register_action(
|
||||
"sensor.duty_time.start", StartAction, DUTY_TIME_ID_SCHEMA, synchronous=True
|
||||
)
|
||||
async def sensor_runtime_start_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
"sensor.duty_time.stop",
|
||||
StopAction,
|
||||
DUTY_TIME_ID_SCHEMA,
|
||||
synchronous=True,
|
||||
@register_action(
|
||||
"sensor.duty_time.stop", StopAction, DUTY_TIME_ID_SCHEMA, synchronous=True
|
||||
)
|
||||
async def sensor_runtime_stop_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
"sensor.duty_time.reset",
|
||||
ResetAction,
|
||||
DUTY_TIME_ID_SCHEMA,
|
||||
synchronous=True,
|
||||
@register_action(
|
||||
"sensor.duty_time.reset", ResetAction, DUTY_TIME_ID_SCHEMA, synchronous=True
|
||||
)
|
||||
async def sensor_runtime_reset_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
@automation.register_condition(
|
||||
@register_condition(
|
||||
"sensor.duty_time.is_running", RunningCondition, DUTY_TIME_ID_SCHEMA
|
||||
)
|
||||
async def duty_time_is_running_to_code(
|
||||
@@ -124,7 +148,7 @@ async def duty_time_is_running_to_code(
|
||||
return cg.new_Pvariable(condition_id, template_arg, paren, True)
|
||||
|
||||
|
||||
@automation.register_condition(
|
||||
@register_condition(
|
||||
"sensor.duty_time.is_not_running", RunningCondition, DUTY_TIME_ID_SCHEMA
|
||||
)
|
||||
async def duty_time_is_not_running_to_code(
|
||||
|
||||
@@ -11,10 +11,7 @@ from typing import Any
|
||||
|
||||
from esphome import yaml_util
|
||||
import esphome.codegen as cg
|
||||
from esphome.components.const import (
|
||||
CONF_ENABLE_OTA_DOWNGRADE_PROTECTION,
|
||||
CONF_IGNORE_NOT_FOUND,
|
||||
)
|
||||
from esphome.components.const import CONF_ENABLE_OTA_DOWNGRADE_PROTECTION
|
||||
from esphome.config_helpers import filter_source_files_from_defines
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
@@ -114,7 +111,6 @@ CONF_ENGINEERING_SAMPLE = "engineering_sample"
|
||||
CONF_INCLUDE_BUILTIN_IDF_COMPONENTS = "include_builtin_idf_components"
|
||||
CONF_ENABLE_LWIP_ASSERT = "enable_lwip_assert"
|
||||
CONF_EXECUTE_FROM_PSRAM = "execute_from_psram"
|
||||
CONF_NVS_CACHE_IN_PSRAM = "nvs_cache_in_psram"
|
||||
CONF_FLASH_CHIP = "flash_chip"
|
||||
CONF_KEY_ID = "key_id"
|
||||
CONF_MINIMUM_CHIP_REVISION = "minimum_chip_revision"
|
||||
@@ -1599,29 +1595,6 @@ def final_validate(config) -> None:
|
||||
path=[CONF_FRAMEWORK, CONF_ADVANCED, CONF_EXECUTE_FROM_PSRAM],
|
||||
)
|
||||
)
|
||||
if advanced.get(CONF_NVS_CACHE_IN_PSRAM):
|
||||
psram_conf = full_config.get(PSRAM_DOMAIN)
|
||||
if (
|
||||
psram_conf is None
|
||||
or psram_conf[CONF_DISABLED]
|
||||
or psram_conf[CONF_IGNORE_NOT_FOUND]
|
||||
):
|
||||
errs.append(
|
||||
cv.Invalid(
|
||||
f"'{CONF_NVS_CACHE_IN_PSRAM}' requires PSRAM with 'ignore_not_found: false'",
|
||||
path=[CONF_FRAMEWORK, CONF_ADVANCED, CONF_NVS_CACHE_IN_PSRAM],
|
||||
)
|
||||
)
|
||||
if (
|
||||
advanced.get(CONF_NVS_ENCRYPTION) is not None
|
||||
or conf_fw[CONF_SDKCONFIG_OPTIONS].get("CONFIG_NVS_ENCRYPTION") == "y"
|
||||
):
|
||||
errs.append(
|
||||
cv.Invalid(
|
||||
f"'{CONF_NVS_CACHE_IN_PSRAM}' cannot be used with NVS encryption; the keys must stay in internal RAM",
|
||||
path=[CONF_FRAMEWORK, CONF_ADVANCED, CONF_NVS_CACHE_IN_PSRAM],
|
||||
)
|
||||
)
|
||||
|
||||
final_validate_pins(full_config)
|
||||
|
||||
@@ -2062,7 +2035,6 @@ FRAMEWORK_SCHEMA = cv.Schema(
|
||||
cv.Optional(CONF_RINGBUF_IN_IRAM, default=False): cv.boolean,
|
||||
cv.Optional(CONF_HEAP_IN_IRAM, default=False): cv.boolean,
|
||||
cv.Optional(CONF_EXECUTE_FROM_PSRAM, default=False): cv.boolean,
|
||||
cv.Optional(CONF_NVS_CACHE_IN_PSRAM): cv.boolean,
|
||||
cv.Optional(CONF_LOOP_TASK_STACK_SIZE, default=8192): cv.int_range(
|
||||
min=8192, max=32768
|
||||
),
|
||||
@@ -2389,20 +2361,6 @@ async def _set_libc_picolibc_newlib_compat() -> None:
|
||||
)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.FINAL)
|
||||
async def _apply_nvs_cache_in_psram(explicit: bool) -> None:
|
||||
"""Keep the NVS cache in PSRAM unless NVS encryption is on, however it was enabled."""
|
||||
# The encrypted partition object holds the derived keys, which must stay in internal RAM
|
||||
if is_idf_sdkconfig_option_enabled("CONFIG_NVS_ENCRYPTION"):
|
||||
if explicit:
|
||||
_LOGGER.warning(
|
||||
"%s ignored: NVS encryption keeps the NVS cache in internal RAM",
|
||||
CONF_NVS_CACHE_IN_PSRAM,
|
||||
)
|
||||
return
|
||||
set_idf_sdkconfig_default("CONFIG_NVS_ALLOCATE_CACHE_IN_SPIRAM", True)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.FINAL)
|
||||
async def _reconcile_certificate_bundle_sdkconfig() -> None:
|
||||
"""Enable the mbedTLS certificate bundle only when something asked for it.
|
||||
@@ -2955,17 +2913,6 @@ async def to_code(config):
|
||||
if advanced[CONF_EXECUTE_FROM_PSRAM]:
|
||||
add_idf_sdkconfig_option("CONFIG_SPIRAM_XIP_FROM_PSRAM", True)
|
||||
|
||||
# Imported here as psram imports this module
|
||||
from esphome.components.psram import is_guaranteed as psram_is_guaranteed
|
||||
|
||||
# Frees internal heap (the cache scales with the NVS partition) but slows NVS, so only
|
||||
# where PSRAM is known to be fitted. Decided at FINAL so every way of enabling NVS
|
||||
# encryption has been seen and a user's sdkconfig_options value wins.
|
||||
# Unset means on; only an explicit true is worth a warning when it has to be dropped.
|
||||
requested = advanced.get(CONF_NVS_CACHE_IN_PSRAM)
|
||||
if requested is not False and psram_is_guaranteed():
|
||||
CORE.add_job(_apply_nvs_cache_in_psram, requested is True)
|
||||
|
||||
# Apply LWIP core locking for better socket performance
|
||||
# This is already enabled by default in Arduino framework, where it provides
|
||||
# significant performance benefits. Our benchmarks show socket operations are
|
||||
|
||||
@@ -32,7 +32,8 @@ from esphome.const import (
|
||||
CONF_NAME,
|
||||
CONF_NAME_ADD_MAC_SUFFIX,
|
||||
)
|
||||
from esphome.core import CORE, TimePeriod
|
||||
from esphome.core import CORE, ID, TimePeriod
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
import esphome.final_validate as fv
|
||||
from esphome.types import ConfigType
|
||||
|
||||
@@ -605,27 +606,38 @@ async def to_code(config: ConfigType) -> None:
|
||||
cg.add_define("USE_ESP32_BLE_UUID")
|
||||
|
||||
|
||||
automation.register_bare_condition(
|
||||
"ble.enabled",
|
||||
BLEEnabledCondition,
|
||||
cv.Schema({}),
|
||||
@automation.register_condition("ble.enabled", BLEEnabledCondition, cv.Schema({}))
|
||||
async def ble_enabled_to_code(
|
||||
config: ConfigType,
|
||||
condition_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
return cg.new_Pvariable(condition_id, template_arg)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"ble.enable", BLEEnableAction, cv.Schema({}), synchronous=True
|
||||
)
|
||||
async def ble_enable_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
return cg.new_Pvariable(action_id, template_arg)
|
||||
|
||||
|
||||
automation.register_bare_action(
|
||||
"ble.enable",
|
||||
BLEEnableAction,
|
||||
cv.Schema({}),
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_bare_action(
|
||||
"ble.disable",
|
||||
BLEDisableAction,
|
||||
cv.Schema({}),
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"ble.disable", BLEDisableAction, cv.Schema({}), synchronous=True
|
||||
)
|
||||
async def ble_disable_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
return cg.new_Pvariable(action_id, template_arg)
|
||||
|
||||
|
||||
# ble_advertising.cpp is fully #ifdef'd on USE_ESP32_BLE_ADVERTISING, set
|
||||
|
||||
@@ -339,16 +339,7 @@ async def to_code(config: ConfigType) -> None:
|
||||
cg.add_platformio_option("platform", conf[CONF_PLATFORM_VERSION])
|
||||
cg.add_platformio_option(
|
||||
"platform_packages",
|
||||
[
|
||||
f"platformio/framework-arduinoespressif8266@{conf[CONF_SOURCE]}",
|
||||
# Override the ancient tool-esptoolpy ~1.30000.0 pinned by
|
||||
# platform-espressif8266 4.2.1 with the same 5.x build the
|
||||
# pioarduino ESP32 platform uses, so both platforms share the
|
||||
# same installed package and stop reinstalling on every switch.
|
||||
# The 0.0.1 path component is pioarduino's stable registry
|
||||
# release tag (not the tool version); the tool itself is 5.2.0.
|
||||
"pioarduino/tool-esptoolpy@https://github.com/pioarduino/registry/releases/download/0.0.1/esptoolpy-v5.2.0.zip",
|
||||
],
|
||||
[f"platformio/framework-arduinoespressif8266@{conf[CONF_SOURCE]}"],
|
||||
)
|
||||
|
||||
# Default for platformio is LWIP2_LOW_MEMORY with:
|
||||
|
||||
@@ -2,7 +2,7 @@ import logging
|
||||
|
||||
import esphome.codegen as cg
|
||||
from esphome.components.noise import (
|
||||
ENCRYPTION_SCHEMA,
|
||||
encryption_schema,
|
||||
new_psk_progmem,
|
||||
static_encryption_key,
|
||||
)
|
||||
@@ -27,7 +27,6 @@ from esphome.const import (
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.coroutine import CoroPriority
|
||||
from esphome.espota2 import CONF_ALLOW_PLAINTEXT_UPLOAD
|
||||
import esphome.final_validate as fv
|
||||
from esphome.types import ConfigType
|
||||
|
||||
@@ -232,38 +231,15 @@ def _resolve_encryption_key(encryption_conf: ConfigType, api_conf: ConfigType) -
|
||||
encryption_conf[CONF_KEY] = api_key
|
||||
|
||||
|
||||
# Uploader side options live only on the ota block; the api block keeps the
|
||||
# shared schema
|
||||
_ENCRYPTION_SCHEMA = ENCRYPTION_SCHEMA.extend(
|
||||
{
|
||||
cv.Optional(CONF_ALLOW_PLAINTEXT_UPLOAD): cv.boolean,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def _encryption_schema(config: ConfigType | None) -> ConfigType:
|
||||
# Only a bare `encryption:` block is keyless; `false` or a list must fail
|
||||
return _ENCRYPTION_SCHEMA({} if config is None else config)
|
||||
|
||||
|
||||
# Also called on merged same-port configs in final validate, where schemas
|
||||
# do not run
|
||||
def _validate_no_password_with_encryption(config: ConfigType) -> ConfigType:
|
||||
if (
|
||||
CONF_PASSWORD not in config
|
||||
or (encryption := config.get(CONF_ENCRYPTION)) is None
|
||||
):
|
||||
return config
|
||||
# The migration install may still have to answer the old firmware's
|
||||
# password prompt on the plaintext leg; the password is not built in
|
||||
if encryption.get(CONF_ALLOW_PLAINTEXT_UPLOAD):
|
||||
return config
|
||||
raise cv.Invalid(
|
||||
f"'{CONF_PASSWORD}' cannot be combined with '{CONF_ENCRYPTION}'; the "
|
||||
f"encryption key already authenticates the uploader, remove '{CONF_PASSWORD}' "
|
||||
f"(or set '{CONF_ALLOW_PLAINTEXT_UPLOAD}: true' for the one install that "
|
||||
f"migrates a device still asking for it)"
|
||||
)
|
||||
if CONF_PASSWORD in config and CONF_ENCRYPTION in config:
|
||||
raise cv.Invalid(
|
||||
f"'{CONF_PASSWORD}' cannot be combined with '{CONF_ENCRYPTION}'; the "
|
||||
f"encryption key already authenticates the uploader, remove '{CONF_PASSWORD}'"
|
||||
)
|
||||
return config
|
||||
|
||||
|
||||
def _consume_ota_sockets(config: ConfigType) -> ConfigType:
|
||||
@@ -293,7 +269,7 @@ CONFIG_SCHEMA = cv.All(
|
||||
): cv.port,
|
||||
cv.Optional(CONF_ALLOW_PARTITION_ACCESS, default=False): cv.boolean,
|
||||
cv.Optional(CONF_PASSWORD): cv.sensitive(),
|
||||
cv.Optional(CONF_ENCRYPTION): _encryption_schema,
|
||||
cv.Optional(CONF_ENCRYPTION): encryption_schema,
|
||||
cv.Optional(CONF_NUM_ATTEMPTS): cv.invalid(
|
||||
f"'{CONF_SAFE_MODE}' (and its related configuration variables) has moved from 'ota' to its own component. See https://esphome.io/components/safe_mode"
|
||||
),
|
||||
@@ -328,10 +304,7 @@ async def to_code(config: ConfigType) -> None:
|
||||
# An empty password opts in to the auth code path so set_auth_password() can be
|
||||
# called at runtime (e.g. to rotate the password from a lambda). When `password:`
|
||||
# is omitted entirely, the auth path is excluded to save flash on small devices.
|
||||
# A password is never built in next to encryption: validation only lets
|
||||
# the two coexist for the migration install, where the password answers
|
||||
# the running firmware and the build is authenticated by the key
|
||||
if CONF_PASSWORD in config and CONF_ENCRYPTION not in config:
|
||||
if CONF_PASSWORD in config:
|
||||
cg.add_define("USE_OTA_PASSWORD")
|
||||
if config[CONF_PASSWORD]:
|
||||
cg.add(var.set_auth_password(config[CONF_PASSWORD]))
|
||||
|
||||
@@ -53,10 +53,12 @@ from esphome.const import (
|
||||
)
|
||||
from esphome.core import (
|
||||
CORE,
|
||||
ID,
|
||||
CoroPriority,
|
||||
TimePeriodMilliseconds,
|
||||
coroutine_with_priority,
|
||||
)
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
import esphome.final_validate as fv
|
||||
from esphome.types import ConfigType
|
||||
|
||||
@@ -239,8 +241,6 @@ EthernetComponent = ethernet_ns.class_("EthernetComponent", cg.Component)
|
||||
ManualIP = ethernet_ns.struct("ManualIP")
|
||||
EthernetConnectedCondition = ethernet_ns.class_("EthernetConnectedCondition", Condition)
|
||||
EthernetEnabledCondition = ethernet_ns.class_("EthernetEnabledCondition", Condition)
|
||||
EthernetEnableAction = ethernet_ns.class_("EthernetEnableAction", automation.Action)
|
||||
EthernetDisableAction = ethernet_ns.class_("EthernetDisableAction", automation.Action)
|
||||
|
||||
|
||||
def _is_framework_spi_polling_mode_supported() -> bool:
|
||||
@@ -922,15 +922,27 @@ def _filter_source_files() -> list[str]:
|
||||
FILTER_SOURCE_FILES = _filter_source_files
|
||||
|
||||
|
||||
automation.register_bare_condition(
|
||||
"ethernet.connected", EthernetConnectedCondition, cv.Schema({})
|
||||
)
|
||||
automation.register_bare_condition(
|
||||
"ethernet.enabled", EthernetEnabledCondition, cv.Schema({})
|
||||
)
|
||||
automation.register_bare_action(
|
||||
"ethernet.enable", EthernetEnableAction, cv.Schema({}), synchronous=True
|
||||
)
|
||||
automation.register_bare_action(
|
||||
"ethernet.disable", EthernetDisableAction, cv.Schema({}), synchronous=True
|
||||
)
|
||||
async def _new_pvariable_to_code(
|
||||
config: ConfigType,
|
||||
id_: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
return cg.new_Pvariable(id_, template_arg)
|
||||
|
||||
|
||||
for _name, _cls in (
|
||||
("ethernet.connected", EthernetConnectedCondition),
|
||||
("ethernet.enabled", EthernetEnabledCondition),
|
||||
):
|
||||
automation.register_condition(_name, _cls, cv.Schema({}))(_new_pvariable_to_code)
|
||||
|
||||
ETHERNET_ACTION_SCHEMA = cv.Schema({cv.GenerateID(): cv.use_id(EthernetComponent)})
|
||||
|
||||
for _name, _method in (
|
||||
("ethernet.enable", "enable()"),
|
||||
("ethernet.disable", "disable()"),
|
||||
):
|
||||
automation.register_apply_action(
|
||||
_name, ETHERNET_ACTION_SCHEMA, automation.ApplyCall(_method)
|
||||
)
|
||||
|
||||
@@ -16,15 +16,5 @@ template<typename... Ts> class EthernetEnabledCondition final : public Condition
|
||||
bool check(const Ts &...x) override { return global_eth_component->is_enabled(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class EthernetEnableAction final : public Action<Ts...> {
|
||||
public:
|
||||
void play(const Ts &...x) override { global_eth_component->enable(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class EthernetDisableAction final : public Action<Ts...> {
|
||||
public:
|
||||
void play(const Ts &...x) override { global_eth_component->disable(); }
|
||||
};
|
||||
|
||||
} // namespace esphome::ethernet
|
||||
#endif
|
||||
|
||||
@@ -80,52 +80,72 @@ EzoPMPArbitraryCommandAction = ezo_pmp_ns.class_(
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"ezo_pmp.find",
|
||||
EzoPMPFindAction,
|
||||
EZO_PMP_NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def ezo_pmp_find_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"ezo_pmp.dose_continuously",
|
||||
EzoPMPDoseContinuouslyAction,
|
||||
EZO_PMP_NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def ezo_pmp_dose_continuously_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"ezo_pmp.clear_total_volume_dosed",
|
||||
EzoPMPClearTotalVolumeDispensedAction,
|
||||
EZO_PMP_NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def ezo_pmp_clear_total_volume_dosed_to_code(
|
||||
config, action_id, template_arg, args
|
||||
):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"ezo_pmp.clear_calibration",
|
||||
EzoPMPClearCalibrationAction,
|
||||
EZO_PMP_NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def ezo_pmp_clear_calibration_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"ezo_pmp.pause_dosing",
|
||||
EzoPMPPauseDosingAction,
|
||||
EZO_PMP_NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def ezo_pmp_pause_dosing_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"ezo_pmp.stop_dosing",
|
||||
EzoPMPStopDosingAction,
|
||||
EZO_PMP_NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def ezo_pmp_stop_dosing_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
# Actions that require Multiple Args
|
||||
|
||||
@@ -61,6 +61,8 @@ RESTORE_MODES = {
|
||||
}
|
||||
|
||||
# Actions
|
||||
TurnOffAction = fan_ns.class_("TurnOffAction", automation.Action)
|
||||
ToggleAction = fan_ns.class_("ToggleAction", automation.Action)
|
||||
CycleSpeedAction = fan_ns.class_("CycleSpeedAction", automation.Action)
|
||||
|
||||
FanStateTrigger = fan_ns.class_(
|
||||
@@ -308,8 +310,21 @@ FAN_ACTION_SCHEMA = maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
automation.register_apply_action("fan.toggle", FAN_ACTION_SCHEMA, call="toggle")
|
||||
automation.register_apply_action("fan.turn_off", FAN_ACTION_SCHEMA, call="turn_off")
|
||||
@automation.register_action(
|
||||
"fan.toggle", ToggleAction, FAN_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
async def fan_toggle_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"fan.turn_off", TurnOffAction, FAN_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
async def fan_turn_off_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
automation.register_apply_action(
|
||||
"fan.turn_on",
|
||||
|
||||
@@ -6,6 +6,24 @@
|
||||
|
||||
namespace esphome::fan {
|
||||
|
||||
template<typename... Ts> class TurnOffAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit TurnOffAction(Fan *state) : state_(state) {}
|
||||
|
||||
void play(const Ts &...x) override { this->state_->turn_off().perform(); }
|
||||
|
||||
Fan *state_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class ToggleAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit ToggleAction(Fan *state) : state_(state) {}
|
||||
|
||||
void play(const Ts &...x) override { this->state_->toggle().perform(); }
|
||||
|
||||
Fan *state_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class CycleSpeedAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit CycleSpeedAction(Fan *state) : state_(state) {}
|
||||
|
||||
@@ -83,7 +83,7 @@ void FanCall::validate_() {
|
||||
auto traits = this->parent_.get_traits();
|
||||
|
||||
if (this->speed_.has_value()) {
|
||||
this->speed_ = clamp(*this->speed_, 1, static_cast<int>(traits.supported_speed_count()));
|
||||
this->speed_ = clamp(*this->speed_, 1, traits.supported_speed_count());
|
||||
|
||||
// https://developers.home-assistant.io/docs/core/entity/fan/#preset-modes
|
||||
// "Manually setting a speed must disable any set preset mode"
|
||||
|
||||
@@ -14,7 +14,7 @@ class FanTraits {
|
||||
|
||||
public:
|
||||
FanTraits() = default;
|
||||
FanTraits(bool oscillation, bool speed, bool direction, uint8_t speed_count)
|
||||
FanTraits(bool oscillation, bool speed, bool direction, int speed_count)
|
||||
: oscillation_(oscillation), speed_(speed), direction_(direction), speed_count_(speed_count) {}
|
||||
|
||||
/// Return if this fan supports oscillation.
|
||||
@@ -26,9 +26,9 @@ class FanTraits {
|
||||
/// Set whether this fan supports speed levels.
|
||||
void set_speed(bool speed) { this->speed_ = speed; }
|
||||
/// Return how many speed levels the fan has
|
||||
uint8_t supported_speed_count() const { return this->speed_count_; }
|
||||
int supported_speed_count() const { return this->speed_count_; }
|
||||
/// Set how many speed levels this fan has.
|
||||
void set_supported_speed_count(uint8_t speed_count) { this->speed_count_ = speed_count; }
|
||||
void set_supported_speed_count(int speed_count) { this->speed_count_ = speed_count; }
|
||||
/// Return if this fan supports changing direction
|
||||
bool supports_direction() const { return this->direction_; }
|
||||
/// Set whether this fan supports changing direction
|
||||
|
||||
@@ -206,7 +206,7 @@ async def fingerprint_grow_enroll_to_code(config, action_id, template_arg, args)
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"fingerprint_grow.cancel_enroll",
|
||||
CancelEnrollmentAction,
|
||||
cv.Schema(
|
||||
@@ -216,6 +216,10 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def fingerprint_grow_cancel_enroll_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
@@ -239,7 +243,7 @@ async def fingerprint_grow_delete_to_code(config, action_id, template_arg, args)
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"fingerprint_grow.delete_all",
|
||||
DeleteAllAction,
|
||||
cv.Schema(
|
||||
@@ -249,6 +253,10 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def fingerprint_grow_delete_all_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
FINGERPRINT_GROW_LED_CONTROL_ACTION_SCHEMA = cv.maybe_simple_value(
|
||||
|
||||
@@ -126,7 +126,7 @@ async def grove_tb6612fng_stop_to_code(config, action_id, template_arg, args):
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"grove_tb6612fng.standby",
|
||||
GROVETB6612FNGMotorStandbyAction,
|
||||
cv.Schema(
|
||||
@@ -136,9 +136,14 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def grove_tb6612fng_standby_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"grove_tb6612fng.no_standby",
|
||||
GROVETB6612FNGMotorNoStandbyAction,
|
||||
cv.Schema(
|
||||
@@ -148,6 +153,11 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def grove_tb6612fng_no_standby_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
|
||||
return var
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
#include "haier_base.h"
|
||||
#include "hon_climate.h"
|
||||
|
||||
namespace esphome::haier {
|
||||
|
||||
template<typename... Ts> class DisplayOnAction final : public Action<Ts...> {
|
||||
public:
|
||||
DisplayOnAction(HaierClimateBase *parent) : parent_(parent) {}
|
||||
void play(const Ts &...x) { this->parent_->set_display_state(true); }
|
||||
|
||||
protected:
|
||||
HaierClimateBase *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class DisplayOffAction final : public Action<Ts...> {
|
||||
public:
|
||||
DisplayOffAction(HaierClimateBase *parent) : parent_(parent) {}
|
||||
void play(const Ts &...x) { this->parent_->set_display_state(false); }
|
||||
|
||||
protected:
|
||||
HaierClimateBase *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class BeeperOnAction final : public Action<Ts...> {
|
||||
public:
|
||||
BeeperOnAction(HonClimate *parent) : parent_(parent) {}
|
||||
void play(const Ts &...x) { this->parent_->set_beeper_state(true); }
|
||||
|
||||
protected:
|
||||
HonClimate *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class BeeperOffAction final : public Action<Ts...> {
|
||||
public:
|
||||
BeeperOffAction(HonClimate *parent) : parent_(parent) {}
|
||||
void play(const Ts &...x) { this->parent_->set_beeper_state(false); }
|
||||
|
||||
protected:
|
||||
HonClimate *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class VerticalAirflowAction final : public Action<Ts...> {
|
||||
public:
|
||||
VerticalAirflowAction(HonClimate *parent) : parent_(parent) {}
|
||||
TEMPLATABLE_VALUE(hon_protocol::VerticalSwingMode, direction)
|
||||
void play(const Ts &...x) { this->parent_->set_vertical_airflow(this->direction_.value(x...)); }
|
||||
|
||||
protected:
|
||||
HonClimate *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class HorizontalAirflowAction final : public Action<Ts...> {
|
||||
public:
|
||||
HorizontalAirflowAction(HonClimate *parent) : parent_(parent) {}
|
||||
TEMPLATABLE_VALUE(hon_protocol::HorizontalSwingMode, direction)
|
||||
void play(const Ts &...x) { this->parent_->set_horizontal_airflow(this->direction_.value(x...)); }
|
||||
|
||||
protected:
|
||||
HonClimate *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class HealthOnAction final : public Action<Ts...> {
|
||||
public:
|
||||
HealthOnAction(HaierClimateBase *parent) : parent_(parent) {}
|
||||
void play(const Ts &...x) { this->parent_->set_health_mode(true); }
|
||||
|
||||
protected:
|
||||
HaierClimateBase *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class HealthOffAction final : public Action<Ts...> {
|
||||
public:
|
||||
HealthOffAction(HaierClimateBase *parent) : parent_(parent) {}
|
||||
void play(const Ts &...x) { this->parent_->set_health_mode(false); }
|
||||
|
||||
protected:
|
||||
HaierClimateBase *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class StartSelfCleaningAction final : public Action<Ts...> {
|
||||
public:
|
||||
StartSelfCleaningAction(HonClimate *parent) : parent_(parent) {}
|
||||
void play(const Ts &...x) { this->parent_->start_self_cleaning(); }
|
||||
|
||||
protected:
|
||||
HonClimate *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class StartSteriCleaningAction final : public Action<Ts...> {
|
||||
public:
|
||||
StartSteriCleaningAction(HonClimate *parent) : parent_(parent) {}
|
||||
void play(const Ts &...x) { this->parent_->start_steri_cleaning(); }
|
||||
|
||||
protected:
|
||||
HonClimate *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class PowerOnAction final : public Action<Ts...> {
|
||||
public:
|
||||
PowerOnAction(HaierClimateBase *parent) : parent_(parent) {}
|
||||
void play(const Ts &...x) { this->parent_->send_power_on_command(); }
|
||||
|
||||
protected:
|
||||
HaierClimateBase *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class PowerOffAction final : public Action<Ts...> {
|
||||
public:
|
||||
PowerOffAction(HaierClimateBase *parent) : parent_(parent) {}
|
||||
void play(const Ts &...x) { this->parent_->send_power_off_command(); }
|
||||
|
||||
protected:
|
||||
HaierClimateBase *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class PowerToggleAction final : public Action<Ts...> {
|
||||
public:
|
||||
PowerToggleAction(HaierClimateBase *parent) : parent_(parent) {}
|
||||
void play(const Ts &...x) { this->parent_->toggle_power(); }
|
||||
|
||||
protected:
|
||||
HaierClimateBase *parent_;
|
||||
};
|
||||
|
||||
} // namespace esphome::haier
|
||||
@@ -9,6 +9,7 @@ from esphome.const import (
|
||||
CONF_BEEPER,
|
||||
CONF_CURRENT_TEMPERATURE,
|
||||
CONF_DISPLAY,
|
||||
CONF_ID,
|
||||
CONF_LEVEL,
|
||||
CONF_LOGGER,
|
||||
CONF_LOGS,
|
||||
@@ -253,6 +254,23 @@ CONFIG_SCHEMA = cv.All(
|
||||
)
|
||||
|
||||
|
||||
# Actions
|
||||
DisplayOnAction = haier_ns.class_("DisplayOnAction", automation.Action)
|
||||
DisplayOffAction = haier_ns.class_("DisplayOffAction", automation.Action)
|
||||
BeeperOnAction = haier_ns.class_("BeeperOnAction", automation.Action)
|
||||
BeeperOffAction = haier_ns.class_("BeeperOffAction", automation.Action)
|
||||
StartSelfCleaningAction = haier_ns.class_("StartSelfCleaningAction", automation.Action)
|
||||
StartSteriCleaningAction = haier_ns.class_(
|
||||
"StartSteriCleaningAction", automation.Action
|
||||
)
|
||||
VerticalAirflowAction = haier_ns.class_("VerticalAirflowAction", automation.Action)
|
||||
HorizontalAirflowAction = haier_ns.class_("HorizontalAirflowAction", automation.Action)
|
||||
HealthOnAction = haier_ns.class_("HealthOnAction", automation.Action)
|
||||
HealthOffAction = haier_ns.class_("HealthOffAction", automation.Action)
|
||||
PowerOnAction = haier_ns.class_("PowerOnAction", automation.Action)
|
||||
PowerOffAction = haier_ns.class_("PowerOffAction", automation.Action)
|
||||
PowerToggleAction = haier_ns.class_("PowerToggleAction", automation.Action)
|
||||
|
||||
HAIER_BASE_ACTION_SCHEMA = automation.maybe_simple_id(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(HaierClimateBase),
|
||||
@@ -266,35 +284,62 @@ HAIER_HON_BASE_ACTION_SCHEMA = automation.maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
for _name, _schema, _call in (
|
||||
("climate.haier.display_on", HAIER_BASE_ACTION_SCHEMA, "set_display_state(true)"),
|
||||
("climate.haier.display_off", HAIER_BASE_ACTION_SCHEMA, "set_display_state(false)"),
|
||||
("climate.haier.beeper_on", HAIER_HON_BASE_ACTION_SCHEMA, "set_beeper_state(true)"),
|
||||
(
|
||||
"climate.haier.beeper_off",
|
||||
HAIER_HON_BASE_ACTION_SCHEMA,
|
||||
"set_beeper_state(false)",
|
||||
),
|
||||
(
|
||||
"climate.haier.start_self_cleaning",
|
||||
HAIER_HON_BASE_ACTION_SCHEMA,
|
||||
"start_self_cleaning()",
|
||||
),
|
||||
(
|
||||
"climate.haier.start_steri_cleaning",
|
||||
HAIER_HON_BASE_ACTION_SCHEMA,
|
||||
"start_steri_cleaning()",
|
||||
),
|
||||
("climate.haier.health_on", HAIER_BASE_ACTION_SCHEMA, "set_health_mode(true)"),
|
||||
("climate.haier.health_off", HAIER_BASE_ACTION_SCHEMA, "set_health_mode(false)"),
|
||||
("climate.haier.power_on", HAIER_BASE_ACTION_SCHEMA, "send_power_on_command()"),
|
||||
("climate.haier.power_off", HAIER_BASE_ACTION_SCHEMA, "send_power_off_command()"),
|
||||
("climate.haier.power_toggle", HAIER_BASE_ACTION_SCHEMA, "toggle_power()"),
|
||||
):
|
||||
automation.register_apply_action(_name, _schema, automation.ApplyCall(_call))
|
||||
@automation.register_action(
|
||||
"climate.haier.display_on",
|
||||
DisplayOnAction,
|
||||
HAIER_BASE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
@automation.register_action(
|
||||
"climate.haier.display_off",
|
||||
DisplayOffAction,
|
||||
HAIER_BASE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def display_action_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
automation.register_apply_action(
|
||||
|
||||
@automation.register_action(
|
||||
"climate.haier.beeper_on",
|
||||
BeeperOnAction,
|
||||
HAIER_HON_BASE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
@automation.register_action(
|
||||
"climate.haier.beeper_off",
|
||||
BeeperOffAction,
|
||||
HAIER_HON_BASE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def beeper_action_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
# Start self cleaning or steri-cleaning action action
|
||||
@automation.register_action(
|
||||
"climate.haier.start_self_cleaning",
|
||||
StartSelfCleaningAction,
|
||||
HAIER_HON_BASE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
@automation.register_action(
|
||||
"climate.haier.start_steri_cleaning",
|
||||
StartSteriCleaningAction,
|
||||
HAIER_HON_BASE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def start_cleaning_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
# Set vertical airflow direction action
|
||||
@automation.register_action(
|
||||
"climate.haier.set_vertical_airflow",
|
||||
VerticalAirflowAction,
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(HonClimate),
|
||||
@@ -303,13 +348,22 @@ automation.register_apply_action(
|
||||
),
|
||||
}
|
||||
),
|
||||
automation.ApplyField(
|
||||
CONF_VERTICAL_AIRFLOW, "set_vertical_airflow", AirflowVerticalDirection
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def haier_set_vertical_airflow_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
var = cg.new_Pvariable(action_id, template_arg, paren)
|
||||
template_ = await cg.templatable(
|
||||
config[CONF_VERTICAL_AIRFLOW], args, AirflowVerticalDirection
|
||||
)
|
||||
cg.add(var.set_direction(template_))
|
||||
return var
|
||||
|
||||
automation.register_apply_action(
|
||||
|
||||
# Set horizontal airflow direction action
|
||||
@automation.register_action(
|
||||
"climate.haier.set_horizontal_airflow",
|
||||
HorizontalAirflowAction,
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(HonClimate),
|
||||
@@ -318,10 +372,56 @@ automation.register_apply_action(
|
||||
),
|
||||
}
|
||||
),
|
||||
automation.ApplyField(
|
||||
CONF_HORIZONTAL_AIRFLOW, "set_horizontal_airflow", AirflowHorizontalDirection
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def haier_set_horizontal_airflow_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
var = cg.new_Pvariable(action_id, template_arg, paren)
|
||||
template_ = await cg.templatable(
|
||||
config[CONF_HORIZONTAL_AIRFLOW], args, AirflowHorizontalDirection
|
||||
)
|
||||
cg.add(var.set_direction(template_))
|
||||
return var
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"climate.haier.health_on",
|
||||
HealthOnAction,
|
||||
HAIER_BASE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
@automation.register_action(
|
||||
"climate.haier.health_off",
|
||||
HealthOffAction,
|
||||
HAIER_BASE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def health_action_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"climate.haier.power_on",
|
||||
PowerOnAction,
|
||||
HAIER_BASE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
@automation.register_action(
|
||||
"climate.haier.power_off",
|
||||
PowerOffAction,
|
||||
HAIER_BASE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
@automation.register_action(
|
||||
"climate.haier.power_toggle",
|
||||
PowerToggleAction,
|
||||
HAIER_BASE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def power_action_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
def _final_validate(config) -> None:
|
||||
|
||||
@@ -7,11 +7,14 @@ import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_DECAY_MODE,
|
||||
CONF_ENABLE_PIN,
|
||||
CONF_ID,
|
||||
CONF_PIN_A,
|
||||
CONF_PIN_B,
|
||||
CONF_PRESET_MODES,
|
||||
CONF_SPEED_COUNT,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
from .. import hbridge_ns
|
||||
@@ -39,7 +42,7 @@ CONFIG_SCHEMA = (
|
||||
cv.Optional(CONF_DECAY_MODE, default="SLOW"): cv.enum(
|
||||
DECAY_MODE_OPTIONS, upper=True
|
||||
),
|
||||
cv.Optional(CONF_SPEED_COUNT, default=100): cv.int_range(min=1, max=255),
|
||||
cv.Optional(CONF_SPEED_COUNT, default=100): cv.int_range(min=1),
|
||||
cv.Optional(CONF_ENABLE_PIN): cv.use_id(output.FloatOutput),
|
||||
cv.Optional(CONF_PRESET_MODES): validate_preset_modes,
|
||||
}
|
||||
@@ -48,12 +51,20 @@ CONFIG_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"fan.hbridge.brake",
|
||||
BrakeAction,
|
||||
maybe_simple_id({cv.GenerateID(): cv.use_id(HBridgeFan)}),
|
||||
synchronous=True,
|
||||
)
|
||||
async def fan_hbridge_brake_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
|
||||
@@ -14,7 +14,7 @@ enum DecayMode {
|
||||
|
||||
class HBridgeFan final : public Component, public fan::Fan {
|
||||
public:
|
||||
HBridgeFan(uint8_t speed_count, DecayMode decay_mode) : speed_count_(speed_count), decay_mode_(decay_mode) {}
|
||||
HBridgeFan(int speed_count, DecayMode decay_mode) : speed_count_(speed_count), decay_mode_(decay_mode) {}
|
||||
|
||||
void set_pin_a(output::FloatOutput *pin_a) { pin_a_ = pin_a; }
|
||||
void set_pin_b(output::FloatOutput *pin_b) { pin_b_ = pin_b; }
|
||||
@@ -35,7 +35,7 @@ class HBridgeFan final : public Component, public fan::Fan {
|
||||
output::FloatOutput *pin_b_;
|
||||
output::FloatOutput *enable_{nullptr};
|
||||
output::BinaryOutput *oscillating_{nullptr};
|
||||
uint8_t speed_count_{};
|
||||
int speed_count_{};
|
||||
DecayMode decay_mode_{DECAY_MODE_SLOW};
|
||||
fan::FanTraits traits_;
|
||||
|
||||
|
||||
@@ -139,9 +139,18 @@ async def hdc302x_heater_on_to_code(
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"hdc302x.heater_off",
|
||||
HeaterOffAction,
|
||||
HDC302X_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def hdc302x_heater_off_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
@@ -187,7 +187,7 @@ void HeatpumpIRClimate::transmit_state() {
|
||||
swing_h_cmd = HDIR_SWING;
|
||||
}
|
||||
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) {
|
||||
switch (this->fan_mode.value_or(climate::CLIMATE_FAN_AUTO)) {
|
||||
case climate::CLIMATE_FAN_LOW:
|
||||
fan_speed_cmd = FAN_2;
|
||||
break;
|
||||
|
||||
@@ -118,7 +118,7 @@ void IDFI2CBus::dump_config() {
|
||||
if (s.second) {
|
||||
ESP_LOGCONFIG(TAG, "Found device at address 0x%02X", s.first);
|
||||
} else {
|
||||
ESP_LOGCONFIG(TAG, "Unknown error at address 0x%02X", s.first);
|
||||
ESP_LOGE(TAG, "Unknown error at address 0x%02X", s.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,4 +71,16 @@ class IntegrationSensor final : public sensor::Sensor, public Component {
|
||||
float last_value_{0.0f};
|
||||
};
|
||||
|
||||
template<typename... Ts> class ResetAction final : public Action<Ts...>, public Parented<IntegrationSensor> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->reset(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class SetValueAction final : public Action<Ts...>, public Parented<IntegrationSensor> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(float, value)
|
||||
|
||||
void play(const Ts &...x) override { this->parent_->set_value(this->value_.value(x...)); }
|
||||
};
|
||||
|
||||
} // namespace esphome::integration
|
||||
|
||||
@@ -11,13 +11,17 @@ from esphome.const import (
|
||||
CONF_UNIT_OF_MEASUREMENT,
|
||||
CONF_VALUE,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.core.entity_helpers import inherit_property_from
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
integration_ns = cg.esphome_ns.namespace("integration")
|
||||
IntegrationSensor = integration_ns.class_(
|
||||
"IntegrationSensor", sensor.Sensor, cg.Component
|
||||
)
|
||||
ResetAction = integration_ns.class_("ResetAction", automation.Action)
|
||||
SetValueAction = integration_ns.class_("SetValueAction", automation.Action)
|
||||
|
||||
IntegrationSensorTime = integration_ns.enum("IntegrationSensorTime")
|
||||
INTEGRATION_TIMES = {
|
||||
@@ -102,23 +106,46 @@ async def to_code(config: ConfigType) -> None:
|
||||
cg.add(var.set_restore(config[CONF_RESTORE]))
|
||||
|
||||
|
||||
automation.register_apply_action(
|
||||
@automation.register_action(
|
||||
"sensor.integration.reset",
|
||||
ResetAction,
|
||||
automation.maybe_simple_id(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.use_id(IntegrationSensor),
|
||||
}
|
||||
),
|
||||
automation.ApplyCall("reset()"),
|
||||
synchronous=True,
|
||||
)
|
||||
async def sensor_integration_reset_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
automation.register_apply_action(
|
||||
|
||||
@automation.register_action(
|
||||
"sensor.integration.set_value",
|
||||
SetValueAction,
|
||||
cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.use_id(IntegrationSensor),
|
||||
cv.Required(CONF_VALUE): cv.templatable(cv.float_),
|
||||
}
|
||||
),
|
||||
automation.ApplyField(CONF_VALUE, "set_value", cg.float_),
|
||||
synchronous=True,
|
||||
)
|
||||
async def sensor_integration_set_value_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
template_ = await cg.templatable(config[CONF_VALUE], args, cg.float_)
|
||||
cg.add(var.set_value(template_))
|
||||
return var
|
||||
|
||||
@@ -15,6 +15,7 @@ from esphome.const import (
|
||||
CONF_TIMEOUT,
|
||||
CONF_TRIGGER_ID,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, literal
|
||||
from esphome.types import ConfigType, TemplateArgsType
|
||||
|
||||
@@ -134,7 +135,7 @@ async def to_code(config: ConfigType) -> None:
|
||||
cg.add(var.set_enabled(config[CONF_ENABLE_ON_BOOT]))
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"key_collector.enable",
|
||||
EnableAction,
|
||||
automation.maybe_simple_id(
|
||||
@@ -144,9 +145,18 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def enable_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"key_collector.disable",
|
||||
DisableAction,
|
||||
automation.maybe_simple_id(
|
||||
@@ -156,3 +166,12 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def disable_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
@@ -31,9 +31,6 @@
|
||||
|
||||
namespace esphome::ld24xx {
|
||||
|
||||
/// Parse a little-endian 16-bit unsigned value from two bytes.
|
||||
static constexpr uint16_t two_byte_to_uint16(uint8_t low, uint8_t high) { return ((uint16_t) high << 8) | low; }
|
||||
|
||||
// Helper to find index of value in constexpr array
|
||||
template<size_t N> optional<size_t> find_index(const uint32_t (&arr)[N], uint32_t value) {
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
|
||||
@@ -12,13 +12,13 @@ from esphome.const import (
|
||||
CONF_ON_UNLOCK,
|
||||
CONF_WEB_SERVER,
|
||||
)
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import (
|
||||
entity_duplicate_validator,
|
||||
queue_entity_register,
|
||||
setup_entity,
|
||||
)
|
||||
from esphome.cpp_generator import MockObj, MockObjClass
|
||||
from esphome.cpp_generator import MockObj, MockObjClass, TemplateArgsType
|
||||
from esphome.types import ConfigType, SafeExpType
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
@@ -29,6 +29,9 @@ Lock = lock_ns.class_("Lock", cg.EntityBase)
|
||||
LockPtr = Lock.operator("ptr")
|
||||
LockCall = lock_ns.class_("LockCall")
|
||||
|
||||
UnlockAction = lock_ns.class_("UnlockAction", automation.Action)
|
||||
LockAction = lock_ns.class_("LockAction", automation.Action)
|
||||
OpenAction = lock_ns.class_("OpenAction", automation.Action)
|
||||
LockPublishAction = lock_ns.class_("LockPublishAction", automation.Action)
|
||||
|
||||
LockStateForwarder = lock_ns.class_("LockStateForwarder")
|
||||
@@ -131,14 +134,23 @@ LOCK_ACTION_SCHEMA = maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
for _name, _call in (
|
||||
("lock.unlock", "unlock()"),
|
||||
("lock.lock", "lock()"),
|
||||
("lock.open", "open()"),
|
||||
):
|
||||
automation.register_apply_action(
|
||||
_name, LOCK_ACTION_SCHEMA, automation.ApplyCall(_call)
|
||||
)
|
||||
@automation.register_action(
|
||||
"lock.unlock", UnlockAction, LOCK_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
@automation.register_action(
|
||||
"lock.lock", LockAction, LOCK_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
@automation.register_action(
|
||||
"lock.open", OpenAction, LOCK_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
async def lock_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
automation.register_apply_condition(
|
||||
|
||||
@@ -6,6 +6,36 @@
|
||||
|
||||
namespace esphome::lock {
|
||||
|
||||
template<typename... Ts> class LockAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit LockAction(Lock *a_lock) : lock_(a_lock) {}
|
||||
|
||||
void play(const Ts &...x) override { this->lock_->lock(); }
|
||||
|
||||
protected:
|
||||
Lock *lock_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class UnlockAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit UnlockAction(Lock *a_lock) : lock_(a_lock) {}
|
||||
|
||||
void play(const Ts &...x) override { this->lock_->unlock(); }
|
||||
|
||||
protected:
|
||||
Lock *lock_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class OpenAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit OpenAction(Lock *a_lock) : lock_(a_lock) {}
|
||||
|
||||
void play(const Ts &...x) override { this->lock_->open(); }
|
||||
|
||||
protected:
|
||||
Lock *lock_;
|
||||
};
|
||||
|
||||
/// Callback forwarder that triggers an Automation<> only when a specific lock state is entered.
|
||||
/// Pointer-sized (single Automation* field) to fit inline in Callback::ctx_.
|
||||
template<LockState State> struct LockStateForwarder {
|
||||
|
||||
@@ -14,6 +14,8 @@ from esphome.const import (
|
||||
UNIT_PERCENT,
|
||||
UNIT_VOLT,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
DEPENDENCIES = ["i2c"]
|
||||
@@ -72,9 +74,14 @@ MAX17043_ACTION_SCHEMA = maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
"max17043.sleep_mode",
|
||||
SleepAction,
|
||||
MAX17043_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"max17043.sleep_mode", SleepAction, MAX17043_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
async def max17043_sleep_mode_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
@@ -144,28 +144,36 @@ TERMINAL_ACTION_SCHEMA = cv.Schema(
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
"mcp4461.wiper.increase",
|
||||
WiperIncreaseAction,
|
||||
WIPER_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"mcp4461.wiper.increase", WiperIncreaseAction, WIPER_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
"mcp4461.wiper.decrease",
|
||||
WiperDecreaseAction,
|
||||
WIPER_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"mcp4461.wiper.decrease", WiperDecreaseAction, WIPER_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
async def mcp4461_wiper_step_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
wiper = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, wiper)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"mcp4461.wiper.store_nonvolatile",
|
||||
WiperStoreNonvolatileAction,
|
||||
WIPER_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def mcp4461_wiper_store_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
wiper = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, wiper)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
|
||||
@@ -122,28 +122,33 @@ NO_ARGS_ACTION_SCHEMA = maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"mhz19.calibrate_zero",
|
||||
MHZ19CalibrateZeroAction,
|
||||
NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"mhz19.abc_enable",
|
||||
MHZ19ABCEnableAction,
|
||||
NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"mhz19.abc_disable",
|
||||
MHZ19ABCDisableAction,
|
||||
NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def mhz19_no_args_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
RANGE_ACTION_SCHEMA = maybe_simple_id(
|
||||
|
||||
@@ -6,6 +6,7 @@ import re
|
||||
from urllib.parse import urljoin
|
||||
|
||||
from esphome import automation, external_files, git
|
||||
from esphome.automation import register_action, register_condition
|
||||
from esphome.bundle import add_bundle_file
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import esp32, microphone, ota, psram
|
||||
@@ -57,6 +58,17 @@ micro_wake_word_ns = cg.esphome_ns.namespace("micro_wake_word")
|
||||
|
||||
MicroWakeWord = micro_wake_word_ns.class_("MicroWakeWord", cg.Component)
|
||||
|
||||
DisableModelAction = micro_wake_word_ns.class_("DisableModelAction", automation.Action)
|
||||
EnableModelAction = micro_wake_word_ns.class_("EnableModelAction", automation.Action)
|
||||
StartAction = micro_wake_word_ns.class_("StartAction", automation.Action)
|
||||
StopAction = micro_wake_word_ns.class_("StopAction", automation.Action)
|
||||
|
||||
ModelIsEnabledCondition = micro_wake_word_ns.class_(
|
||||
"ModelIsEnabledCondition", automation.Condition
|
||||
)
|
||||
IsRunningCondition = micro_wake_word_ns.class_(
|
||||
"IsRunningCondition", automation.Condition
|
||||
)
|
||||
|
||||
WakeWordModel = micro_wake_word_ns.class_("WakeWordModel")
|
||||
|
||||
@@ -607,19 +619,23 @@ async def to_code(config):
|
||||
|
||||
MICRO_WAKE_WORD_ACTION_SCHEMA = cv.Schema({cv.GenerateID(): cv.use_id(MicroWakeWord)})
|
||||
|
||||
automation.register_apply_action(
|
||||
|
||||
@register_action(
|
||||
"micro_wake_word.start",
|
||||
StartAction,
|
||||
MICRO_WAKE_WORD_ACTION_SCHEMA,
|
||||
automation.ApplyCall("start()"),
|
||||
synchronous=True,
|
||||
)
|
||||
automation.register_apply_action(
|
||||
"micro_wake_word.stop",
|
||||
MICRO_WAKE_WORD_ACTION_SCHEMA,
|
||||
automation.ApplyCall("stop()"),
|
||||
@register_action(
|
||||
"micro_wake_word.stop", StopAction, MICRO_WAKE_WORD_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
automation.register_apply_condition(
|
||||
"micro_wake_word.is_running", MICRO_WAKE_WORD_ACTION_SCHEMA, "is_running()"
|
||||
@register_condition(
|
||||
"micro_wake_word.is_running", IsRunningCondition, MICRO_WAKE_WORD_ACTION_SCHEMA
|
||||
)
|
||||
async def micro_wake_word_action_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
MICRO_WAKE_WORLD_MODEL_ACTION_SCHEMA = automation.maybe_simple_id(
|
||||
@@ -628,18 +644,24 @@ MICRO_WAKE_WORLD_MODEL_ACTION_SCHEMA = automation.maybe_simple_id(
|
||||
}
|
||||
)
|
||||
|
||||
automation.register_apply_action(
|
||||
|
||||
@register_action(
|
||||
"micro_wake_word.enable_model",
|
||||
EnableModelAction,
|
||||
MICRO_WAKE_WORLD_MODEL_ACTION_SCHEMA,
|
||||
automation.ApplyCall("enable()"),
|
||||
synchronous=True,
|
||||
)
|
||||
automation.register_apply_action(
|
||||
@register_action(
|
||||
"micro_wake_word.disable_model",
|
||||
DisableModelAction,
|
||||
MICRO_WAKE_WORLD_MODEL_ACTION_SCHEMA,
|
||||
automation.ApplyCall("disable()"),
|
||||
synchronous=True,
|
||||
)
|
||||
automation.register_apply_condition(
|
||||
@register_condition(
|
||||
"micro_wake_word.model_is_enabled",
|
||||
ModelIsEnabledCondition,
|
||||
MICRO_WAKE_WORLD_MODEL_ACTION_SCHEMA,
|
||||
"is_enabled()",
|
||||
)
|
||||
async def model_action(config, action_id, template_arg, args):
|
||||
parent = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, parent)
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "micro_wake_word.h"
|
||||
#include "streaming_model.h"
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
namespace esphome::micro_wake_word {
|
||||
|
||||
template<typename... Ts> class StartAction final : public Action<Ts...>, public Parented<MicroWakeWord> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->start(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class StopAction final : public Action<Ts...>, public Parented<MicroWakeWord> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->stop(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class IsRunningCondition final : public Condition<Ts...>, public Parented<MicroWakeWord> {
|
||||
public:
|
||||
bool check(const Ts &...x) override { return this->parent_->is_running(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class EnableModelAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit EnableModelAction(WakeWordModel *wake_word_model) : wake_word_model_(wake_word_model) {}
|
||||
void play(const Ts &...x) override { this->wake_word_model_->enable(); }
|
||||
|
||||
protected:
|
||||
WakeWordModel *wake_word_model_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class DisableModelAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit DisableModelAction(WakeWordModel *wake_word_model) : wake_word_model_(wake_word_model) {}
|
||||
void play(const Ts &...x) override { this->wake_word_model_->disable(); }
|
||||
|
||||
protected:
|
||||
WakeWordModel *wake_word_model_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class ModelIsEnabledCondition final : public Condition<Ts...> {
|
||||
public:
|
||||
explicit ModelIsEnabledCondition(WakeWordModel *wake_word_model) : wake_word_model_(wake_word_model) {}
|
||||
bool check(const Ts &...x) override { return this->wake_word_model_->is_enabled(); }
|
||||
|
||||
protected:
|
||||
WakeWordModel *wake_word_model_;
|
||||
};
|
||||
|
||||
} // namespace esphome::micro_wake_word
|
||||
|
||||
#endif
|
||||
@@ -14,9 +14,9 @@ from esphome.const import (
|
||||
CONF_ON_DATA,
|
||||
CONF_TRIGGER_ID,
|
||||
)
|
||||
from esphome.core import CORE
|
||||
from esphome.core import CORE, ID
|
||||
from esphome.coroutine import CoroPriority, coroutine_with_priority
|
||||
from esphome.cpp_generator import MockObj
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
AUTO_LOAD = ["audio"]
|
||||
@@ -29,11 +29,30 @@ microphone_ns = cg.esphome_ns.namespace("microphone")
|
||||
Microphone = microphone_ns.class_("Microphone")
|
||||
MicrophoneSource = microphone_ns.class_("MicrophoneSource")
|
||||
|
||||
CaptureAction = microphone_ns.class_(
|
||||
"CaptureAction", automation.Action, cg.Parented.template(Microphone)
|
||||
)
|
||||
StopCaptureAction = microphone_ns.class_(
|
||||
"StopCaptureAction", automation.Action, cg.Parented.template(Microphone)
|
||||
)
|
||||
MuteAction = microphone_ns.class_(
|
||||
"MuteAction", automation.Action, cg.Parented.template(Microphone)
|
||||
)
|
||||
UnmuteAction = microphone_ns.class_(
|
||||
"UnmuteAction", automation.Action, cg.Parented.template(Microphone)
|
||||
)
|
||||
|
||||
|
||||
DataTrigger = microphone_ns.class_(
|
||||
"DataTrigger",
|
||||
automation.Trigger.template(cg.std_vector.template(cg.uint8).operator("ref")),
|
||||
)
|
||||
|
||||
IsCapturingCondition = microphone_ns.class_(
|
||||
"IsCapturingCondition", automation.Condition
|
||||
)
|
||||
IsMutedCondition = microphone_ns.class_("IsMutedCondition", automation.Condition)
|
||||
|
||||
|
||||
async def setup_microphone_core_(var: MockObj, config: ConfigType) -> None:
|
||||
for conf in config.get(CONF_ON_DATA, []):
|
||||
@@ -170,22 +189,44 @@ async def microphone_source_to_code(
|
||||
return mic_source
|
||||
|
||||
|
||||
for _name, _call in (
|
||||
("microphone.capture", "start()"),
|
||||
("microphone.stop_capture", "stop()"),
|
||||
("microphone.mute", "set_mute_state(true)"),
|
||||
("microphone.unmute", "set_mute_state(false)"),
|
||||
):
|
||||
automation.register_apply_action(
|
||||
_name, MICROPHONE_ACTION_SCHEMA, automation.ApplyCall(_call)
|
||||
)
|
||||
async def microphone_action(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
automation.register_apply_condition(
|
||||
"microphone.is_capturing", MICROPHONE_ACTION_SCHEMA, "is_running()"
|
||||
)
|
||||
automation.register_apply_condition(
|
||||
"microphone.is_muted", MICROPHONE_ACTION_SCHEMA, "get_mute_state()"
|
||||
)
|
||||
|
||||
automation.register_action(
|
||||
"microphone.capture",
|
||||
CaptureAction,
|
||||
MICROPHONE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)(microphone_action)
|
||||
|
||||
automation.register_action(
|
||||
"microphone.stop_capture",
|
||||
StopCaptureAction,
|
||||
MICROPHONE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)(microphone_action)
|
||||
|
||||
automation.register_action(
|
||||
"microphone.mute", MuteAction, MICROPHONE_ACTION_SCHEMA, synchronous=True
|
||||
)(microphone_action)
|
||||
automation.register_action(
|
||||
"microphone.unmute", UnmuteAction, MICROPHONE_ACTION_SCHEMA, synchronous=True
|
||||
)(microphone_action)
|
||||
|
||||
automation.register_condition(
|
||||
"microphone.is_capturing", IsCapturingCondition, MICROPHONE_ACTION_SCHEMA
|
||||
)(microphone_action)
|
||||
automation.register_condition(
|
||||
"microphone.is_muted", IsMutedCondition, MICROPHONE_ACTION_SCHEMA
|
||||
)(microphone_action)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.CORE)
|
||||
|
||||
@@ -7,6 +7,21 @@
|
||||
|
||||
namespace esphome::microphone {
|
||||
|
||||
template<typename... Ts> class CaptureAction final : public Action<Ts...>, public Parented<Microphone> {
|
||||
void play(const Ts &...x) override { this->parent_->start(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class StopCaptureAction final : public Action<Ts...>, public Parented<Microphone> {
|
||||
void play(const Ts &...x) override { this->parent_->stop(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class MuteAction final : public Action<Ts...>, public Parented<Microphone> {
|
||||
void play(const Ts &...x) override { this->parent_->set_mute_state(true); }
|
||||
};
|
||||
template<typename... Ts> class UnmuteAction final : public Action<Ts...>, public Parented<Microphone> {
|
||||
void play(const Ts &...x) override { this->parent_->set_mute_state(false); }
|
||||
};
|
||||
|
||||
class DataTrigger final : public Trigger<const std::vector<uint8_t> &> {
|
||||
public:
|
||||
explicit DataTrigger(Microphone *mic) {
|
||||
@@ -14,4 +29,14 @@ class DataTrigger final : public Trigger<const std::vector<uint8_t> &> {
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Ts> class IsCapturingCondition final : public Condition<Ts...>, public Parented<Microphone> {
|
||||
public:
|
||||
bool check(const Ts &...x) override { return this->parent_->is_running(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class IsMutedCondition final : public Condition<Ts...>, public Parented<Microphone> {
|
||||
public:
|
||||
bool check(const Ts &...x) override { return this->parent_->get_mute_state(); }
|
||||
};
|
||||
|
||||
} // namespace esphome::microphone
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#if (defined(USE_ARDUINO) && !defined(USE_RP2) && !defined(USE_LIBRETINY)) || defined(USE_ESP_IDF)
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
#include "air_conditioner.h"
|
||||
|
||||
namespace esphome::midea::ac {
|
||||
|
||||
template<typename... Ts> class MideaActionBase : public Action<Ts...> {
|
||||
public:
|
||||
void set_parent(AirConditioner *parent) { this->parent_ = parent; }
|
||||
|
||||
protected:
|
||||
AirConditioner *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class FollowMeAction : public MideaActionBase<Ts...> {
|
||||
TEMPLATABLE_VALUE(float, temperature)
|
||||
TEMPLATABLE_VALUE(bool, use_fahrenheit)
|
||||
TEMPLATABLE_VALUE(bool, beeper)
|
||||
|
||||
void play(const Ts &...x) override {
|
||||
this->parent_->do_follow_me(this->temperature_.value(x...), this->use_fahrenheit_.value(x...),
|
||||
this->beeper_.value(x...));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Ts> class SwingStepAction : public MideaActionBase<Ts...> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->do_swing_step(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class DisplayToggleAction : public MideaActionBase<Ts...> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->do_display_toggle(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class BeeperOnAction : public MideaActionBase<Ts...> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->do_beeper_on(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class BeeperOffAction : public MideaActionBase<Ts...> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->do_beeper_off(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class PowerOnAction : public MideaActionBase<Ts...> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->do_power_on(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class PowerOffAction : public MideaActionBase<Ts...> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->do_power_off(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class PowerToggleAction : public MideaActionBase<Ts...> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->do_power_toggle(); }
|
||||
};
|
||||
|
||||
} // namespace esphome::midea::ac
|
||||
|
||||
#endif // USE_ARDUINO || USE_ESP_IDF
|
||||
@@ -32,7 +32,7 @@ from esphome.const import (
|
||||
UNIT_PERCENT,
|
||||
UNIT_WATT,
|
||||
)
|
||||
from esphome.core import CORE
|
||||
from esphome.core import CORE, coroutine
|
||||
|
||||
CODEOWNERS = ["@dudanov"]
|
||||
DEPENDENCIES = ["climate", "uart"]
|
||||
@@ -53,6 +53,25 @@ def templatize(value):
|
||||
return cv.Schema(ret)
|
||||
|
||||
|
||||
def register_action(name, type_, schema):
|
||||
validator = templatize(schema).extend(MIDEA_ACTION_BASE_SCHEMA)
|
||||
registerer = automation.register_action(
|
||||
f"midea_ac.{name}", type_, validator, synchronous=True
|
||||
)
|
||||
|
||||
def decorator(func):
|
||||
async def new_func(config, action_id, template_arg, args):
|
||||
ac_ = await cg.get_variable(config[CONF_ID])
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
cg.add(var.set_parent(ac_))
|
||||
await coroutine(func)(var, config, args)
|
||||
return var
|
||||
|
||||
return registerer(new_func)
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
ALLOWED_CLIMATE_MODES = {
|
||||
"HEAT_COOL": ClimateMode.CLIMATE_MODE_HEAT_COOL,
|
||||
"COOL": ClimateMode.CLIMATE_MODE_COOL,
|
||||
@@ -142,6 +161,16 @@ CONFIG_SCHEMA = cv.All(
|
||||
),
|
||||
)
|
||||
|
||||
# Actions
|
||||
FollowMeAction = midea_ac_ns.class_("FollowMeAction", automation.Action)
|
||||
DisplayToggleAction = midea_ac_ns.class_("DisplayToggleAction", automation.Action)
|
||||
SwingStepAction = midea_ac_ns.class_("SwingStepAction", automation.Action)
|
||||
BeeperOnAction = midea_ac_ns.class_("BeeperOnAction", automation.Action)
|
||||
BeeperOffAction = midea_ac_ns.class_("BeeperOffAction", automation.Action)
|
||||
PowerOnAction = midea_ac_ns.class_("PowerOnAction", automation.Action)
|
||||
PowerOffAction = midea_ac_ns.class_("PowerOffAction", automation.Action)
|
||||
PowerToggleAction = midea_ac_ns.class_("PowerToggleAction", automation.Action)
|
||||
|
||||
MIDEA_ACTION_BASE_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_ID): cv.use_id(AirConditioner),
|
||||
@@ -158,31 +187,84 @@ MIDEA_FOLLOW_ME_SCHEMA = cv.Schema(
|
||||
)
|
||||
|
||||
|
||||
automation.register_apply_action(
|
||||
"midea_ac.follow_me",
|
||||
templatize(MIDEA_FOLLOW_ME_SCHEMA).extend(MIDEA_ACTION_BASE_SCHEMA),
|
||||
automation.ApplyCall(
|
||||
"do_follow_me({}, {}, {})",
|
||||
(
|
||||
(CONF_TEMPERATURE, cg.float_),
|
||||
(CONF_USE_FAHRENHEIT, cg.bool_),
|
||||
(CONF_BEEPER, cg.bool_),
|
||||
),
|
||||
),
|
||||
)
|
||||
@register_action("follow_me", FollowMeAction, MIDEA_FOLLOW_ME_SCHEMA)
|
||||
async def follow_me_to_code(var, config, args):
|
||||
template_ = await cg.templatable(config[CONF_BEEPER], args, cg.bool_)
|
||||
cg.add(var.set_beeper(template_))
|
||||
template_ = await cg.templatable(config[CONF_USE_FAHRENHEIT], args, cg.bool_)
|
||||
cg.add(var.set_use_fahrenheit(template_))
|
||||
template_ = await cg.templatable(config[CONF_TEMPERATURE], args, cg.float_)
|
||||
cg.add(var.set_temperature(template_))
|
||||
|
||||
for _name, _call in (
|
||||
("midea_ac.display_toggle", "do_display_toggle()"),
|
||||
("midea_ac.swing_step", "do_swing_step()"),
|
||||
("midea_ac.beeper_on", "do_beeper_on()"),
|
||||
("midea_ac.beeper_off", "do_beeper_off()"),
|
||||
("midea_ac.power_on", "do_power_on()"),
|
||||
("midea_ac.power_off", "do_power_off()"),
|
||||
("midea_ac.power_toggle", "do_power_toggle()"),
|
||||
):
|
||||
automation.register_apply_action(
|
||||
_name, MIDEA_ACTION_BASE_SCHEMA, automation.ApplyCall(_call)
|
||||
)
|
||||
|
||||
# Toggle Display action
|
||||
@register_action(
|
||||
"display_toggle",
|
||||
DisplayToggleAction,
|
||||
cv.Schema({}),
|
||||
)
|
||||
async def display_toggle_to_code(var, config, args):
|
||||
pass
|
||||
|
||||
|
||||
# Swing Step action
|
||||
@register_action(
|
||||
"swing_step",
|
||||
SwingStepAction,
|
||||
cv.Schema({}),
|
||||
)
|
||||
async def swing_step_to_code(var, config, args):
|
||||
pass
|
||||
|
||||
|
||||
# Beeper On action
|
||||
@register_action(
|
||||
"beeper_on",
|
||||
BeeperOnAction,
|
||||
cv.Schema({}),
|
||||
)
|
||||
async def beeper_on_to_code(var, config, args):
|
||||
pass
|
||||
|
||||
|
||||
# Beeper Off action
|
||||
@register_action(
|
||||
"beeper_off",
|
||||
BeeperOffAction,
|
||||
cv.Schema({}),
|
||||
)
|
||||
async def beeper_off_to_code(var, config, args):
|
||||
pass
|
||||
|
||||
|
||||
# Power On action
|
||||
@register_action(
|
||||
"power_on",
|
||||
PowerOnAction,
|
||||
cv.Schema({}),
|
||||
)
|
||||
async def power_on_to_code(var, config, args):
|
||||
pass
|
||||
|
||||
|
||||
# Power Off action
|
||||
@register_action(
|
||||
"power_off",
|
||||
PowerOffAction,
|
||||
cv.Schema({}),
|
||||
)
|
||||
async def power_off_to_code(var, config, args):
|
||||
pass
|
||||
|
||||
|
||||
# Power Toggle action
|
||||
@register_action(
|
||||
"power_toggle",
|
||||
PowerToggleAction,
|
||||
cv.Schema({}),
|
||||
)
|
||||
async def power_inv_to_code(var, config, args):
|
||||
pass
|
||||
|
||||
|
||||
FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
|
||||
|
||||
@@ -155,7 +155,7 @@ void MideaIR::transmit_state() {
|
||||
data.set_fahrenheit(this->fahrenheit_);
|
||||
data.set_temp(this->target_temperature);
|
||||
data.set_mode(this->mode);
|
||||
data.set_fan_mode(this->fan_mode.value_or(ClimateFanMode::CLIMATE_FAN_ON));
|
||||
data.set_fan_mode(this->fan_mode.value_or(ClimateFanMode::CLIMATE_FAN_AUTO));
|
||||
data.set_sleep_preset(this->preset == climate::CLIMATE_PRESET_SLEEP);
|
||||
data.fix();
|
||||
this->transmit_(data);
|
||||
|
||||
@@ -162,12 +162,21 @@ async def remote_temperature_action_to_code(
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
f"{DOMAIN}.clear_remote_temperature",
|
||||
ClearRemoteTemperatureAction,
|
||||
CLEAR_REMOTE_TEMPERATURE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def clear_temperature_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
VANE_CONTROL_ACTION_SCHEMA = cv.Schema(
|
||||
|
||||
@@ -117,7 +117,10 @@ mqtt_ns = cg.esphome_ns.namespace("mqtt")
|
||||
MQTTMessage = mqtt_ns.struct("MQTTMessage")
|
||||
MQTTClientDisconnectReason = mqtt_ns.enum("MQTTClientDisconnectReason")
|
||||
MQTTClientComponent = mqtt_ns.class_("MQTTClientComponent", cg.Component)
|
||||
MQTTPublishAction = mqtt_ns.class_("MQTTPublishAction", automation.Action)
|
||||
MQTTPublishJsonAction = mqtt_ns.class_("MQTTPublishJsonAction", automation.Action)
|
||||
MQTTEnableAction = mqtt_ns.class_("MQTTEnableAction", automation.Action)
|
||||
MQTTDisableAction = mqtt_ns.class_("MQTTDisableAction", automation.Action)
|
||||
MQTTMessageTrigger = mqtt_ns.class_(
|
||||
"MQTTMessageTrigger", automation.Trigger.template(cg.std_string), cg.Component
|
||||
)
|
||||
@@ -500,26 +503,22 @@ MQTT_PUBLISH_ACTION_SCHEMA = cv.Schema(
|
||||
)
|
||||
|
||||
|
||||
# A bare literal is ambiguous between the std::string and (const char *, size_t) publish
|
||||
# overloads, so constants and inlined `return "...";` lambdas are both spelled as std::string.
|
||||
def _std_string(config: ConfigType, value: str) -> str:
|
||||
rendered = automation.flash_string(config, value)
|
||||
return rendered if CORE.is_esp8266 else f"std::string({rendered})"
|
||||
|
||||
|
||||
automation.register_apply_action(
|
||||
"mqtt.publish",
|
||||
MQTT_PUBLISH_ACTION_SCHEMA,
|
||||
automation.ApplyCall(
|
||||
"publish({}, {}, {}, {})",
|
||||
(
|
||||
(CONF_TOPIC, "std::string", _std_string),
|
||||
(CONF_PAYLOAD, "std::string", _std_string),
|
||||
(CONF_QOS, cg.uint8),
|
||||
(CONF_RETAIN, cg.bool_),
|
||||
),
|
||||
),
|
||||
@automation.register_action(
|
||||
"mqtt.publish", MQTTPublishAction, MQTT_PUBLISH_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
async def mqtt_publish_action_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
var = cg.new_Pvariable(action_id, template_arg, paren)
|
||||
template_ = await cg.templatable(config[CONF_TOPIC], args, cg.std_string)
|
||||
cg.add(var.set_topic(template_))
|
||||
|
||||
template_ = await cg.templatable(config[CONF_PAYLOAD], args, cg.std_string)
|
||||
cg.add(var.set_payload(template_))
|
||||
template_ = await cg.templatable(config[CONF_QOS], args, cg.uint8)
|
||||
cg.add(var.set_qos(template_))
|
||||
template_ = await cg.templatable(config[CONF_RETAIN], args, cg.bool_)
|
||||
cg.add(var.set_retain(template_))
|
||||
return var
|
||||
|
||||
|
||||
MQTT_PUBLISH_JSON_ACTION_SCHEMA = cv.Schema(
|
||||
@@ -609,16 +608,34 @@ automation.register_apply_condition(
|
||||
)
|
||||
|
||||
|
||||
for _name, _call in (("mqtt.enable", "enable()"), ("mqtt.disable", "disable()")):
|
||||
automation.register_apply_action(
|
||||
_name,
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(MQTTClientComponent),
|
||||
}
|
||||
),
|
||||
automation.ApplyCall(_call),
|
||||
)
|
||||
@automation.register_action(
|
||||
"mqtt.enable",
|
||||
MQTTEnableAction,
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(MQTTClientComponent),
|
||||
}
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def mqtt_enable_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"mqtt.disable",
|
||||
MQTTDisableAction,
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(MQTTClientComponent),
|
||||
}
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def mqtt_disable_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
_platform_filter = filter_source_files_from_platform(
|
||||
|
||||
@@ -378,6 +378,23 @@ class MQTTDisconnectTrigger final : public Trigger<MQTTClientDisconnectReason> {
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Ts> class MQTTPublishAction final : public Action<Ts...> {
|
||||
public:
|
||||
MQTTPublishAction(MQTTClientComponent *parent) : parent_(parent) {}
|
||||
TEMPLATABLE_VALUE(std::string, topic)
|
||||
TEMPLATABLE_VALUE(std::string, payload)
|
||||
TEMPLATABLE_VALUE(uint8_t, qos)
|
||||
TEMPLATABLE_VALUE(bool, retain)
|
||||
|
||||
void play(const Ts &...x) override {
|
||||
this->parent_->publish(this->topic_.value(x...), this->payload_.value(x...), this->qos_.value(x...),
|
||||
this->retain_.value(x...));
|
||||
}
|
||||
|
||||
protected:
|
||||
MQTTClientComponent *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class MQTTPublishJsonAction final : public Action<Ts...> {
|
||||
public:
|
||||
MQTTPublishJsonAction(MQTTClientComponent *parent) : parent_(parent) {}
|
||||
@@ -400,6 +417,26 @@ template<typename... Ts> class MQTTPublishJsonAction final : public Action<Ts...
|
||||
MQTTClientComponent *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class MQTTEnableAction final : public Action<Ts...> {
|
||||
public:
|
||||
MQTTEnableAction(MQTTClientComponent *parent) : parent_(parent) {}
|
||||
|
||||
void play(const Ts &...x) override { this->parent_->enable(); }
|
||||
|
||||
protected:
|
||||
MQTTClientComponent *parent_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class MQTTDisableAction final : public Action<Ts...> {
|
||||
public:
|
||||
MQTTDisableAction(MQTTClientComponent *parent) : parent_(parent) {}
|
||||
|
||||
void play(const Ts &...x) override { this->parent_->disable(); }
|
||||
|
||||
protected:
|
||||
MQTTClientComponent *parent_;
|
||||
};
|
||||
|
||||
} // namespace esphome::mqtt
|
||||
|
||||
#endif // USE_MQTT
|
||||
|
||||
@@ -4,6 +4,8 @@ import esphome.codegen as cg
|
||||
from esphome.components import i2c, sensor
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_GAIN, CONF_ID, ICON_SCALE, STATE_CLASS_MEASUREMENT
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@cujomalainey"]
|
||||
@@ -114,25 +116,30 @@ NAU7802_CALIBRATE_SCHEMA = maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"nau7802.calibrate_internal_offset",
|
||||
NAU7802CalbrateInternalOffsetAction,
|
||||
NAU7802_CALIBRATE_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"nau7802.calibrate_external_offset",
|
||||
NAU7802CalbrateExternalOffsetAction,
|
||||
NAU7802_CALIBRATE_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"nau7802.calibrate_gain",
|
||||
NAU7802CalbrateGainAction,
|
||||
NAU7802_CALIBRATE_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def nau7802_calibrate_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
@@ -28,7 +28,6 @@ void DeviceFirmwareUpdate::setup() {
|
||||
this->reset_pin_->digital_write(true);
|
||||
} else {
|
||||
NRF_POWER->GPREGRET = DFU_MAGIC_UF2_RESET;
|
||||
arch_feed_wdt();
|
||||
App.reboot();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ import esphome.codegen as cg
|
||||
from esphome.components import i2c, time
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@brogon"]
|
||||
@@ -22,7 +24,7 @@ CONFIG_SCHEMA = time.TIME_SCHEMA.extend(
|
||||
).extend(i2c.i2c_device_schema(0x51))
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"pcf85063.write_time",
|
||||
WriteAction,
|
||||
cv.Schema(
|
||||
@@ -32,9 +34,18 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def pcf85063_write_time_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"pcf85063.read_time",
|
||||
ReadAction,
|
||||
automation.maybe_simple_id(
|
||||
@@ -44,6 +55,15 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def pcf85063_read_time_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
|
||||
@@ -3,6 +3,8 @@ import esphome.codegen as cg
|
||||
from esphome.components import i2c, time
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@KoenBreeman"]
|
||||
@@ -25,7 +27,7 @@ CONFIG_SCHEMA = time.TIME_SCHEMA.extend(
|
||||
).extend(i2c.i2c_device_schema(0x51))
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"pcf8563.write_time",
|
||||
WriteAction,
|
||||
automation.maybe_simple_id(
|
||||
@@ -35,9 +37,18 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def pcf8563_write_time_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"pcf8563.read_time",
|
||||
ReadAction,
|
||||
automation.maybe_simple_id(
|
||||
@@ -47,6 +58,15 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def pcf8563_read_time_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
|
||||
@@ -105,20 +105,26 @@ PMWCS3_CALIBRATION_SCHEMA = cv.Schema(
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"pmwcs3.air_calibration",
|
||||
PMWCS3AirCalibrationAction,
|
||||
PMWCS3_CALIBRATION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"pmwcs3.water_calibration",
|
||||
PMWCS3WaterCalibrationAction,
|
||||
PMWCS3_CALIBRATION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def pmwcs3_calibration_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
parent = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, parent)
|
||||
|
||||
|
||||
PMWCS3_NEW_I2C_ADDRESS_SCHEMA = cv.maybe_simple_value(
|
||||
|
||||
@@ -3,12 +3,14 @@ import esphome.codegen as cg
|
||||
from esphome.components import nfc
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_ON_FINISHED_WRITE,
|
||||
CONF_ON_TAG,
|
||||
CONF_ON_TAG_REMOVED,
|
||||
CONF_TRIGGER_ID,
|
||||
)
|
||||
from esphome.cpp_generator import MockObj
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@OttoWinter", "@jesserockz"]
|
||||
@@ -77,7 +79,7 @@ async def setup_pn532(var: MockObj, config: ConfigType) -> None:
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
automation.register_parented_condition(
|
||||
@automation.register_condition(
|
||||
"pn532.is_writing",
|
||||
PN532IsWritingCondition,
|
||||
cv.Schema(
|
||||
@@ -86,3 +88,12 @@ automation.register_parented_condition(
|
||||
}
|
||||
),
|
||||
)
|
||||
async def pn532_is_writing_to_code(
|
||||
config: ConfigType,
|
||||
condition_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(condition_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
@@ -127,68 +127,54 @@ async def pn7150_set_message_to_code(
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"tag.emulation_off",
|
||||
EmulationOffAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
"tag.emulation_on",
|
||||
EmulationOnAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"tag.emulation_on", EmulationOnAction, SIMPLE_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
"tag.polling_off",
|
||||
PollingOffAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"tag.polling_off", PollingOffAction, SIMPLE_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
"tag.polling_on",
|
||||
PollingOnAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"tag.polling_on", PollingOnAction, SIMPLE_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"tag.set_clean_mode",
|
||||
SetCleanModeAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"tag.set_format_mode",
|
||||
SetFormatModeAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"tag.set_read_mode",
|
||||
SetReadModeAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"tag.set_write_mode",
|
||||
SetWriteModeAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def pn7150_simple_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
@@ -234,7 +220,7 @@ async def setup_pn7150(var: MockObj, config: ConfigType) -> None:
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
automation.register_parented_condition(
|
||||
@automation.register_condition(
|
||||
"pn7150.is_writing",
|
||||
PN7150IsWritingCondition,
|
||||
cv.Schema(
|
||||
@@ -243,3 +229,12 @@ automation.register_parented_condition(
|
||||
}
|
||||
),
|
||||
)
|
||||
async def pn7150_is_writing_to_code(
|
||||
config: ConfigType,
|
||||
condition_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(condition_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
@@ -131,68 +131,54 @@ async def pn7160_set_message_to_code(
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"tag.emulation_off",
|
||||
EmulationOffAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
"tag.emulation_on",
|
||||
EmulationOnAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"tag.emulation_on", EmulationOnAction, SIMPLE_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
"tag.polling_off",
|
||||
PollingOffAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"tag.polling_off", PollingOffAction, SIMPLE_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
"tag.polling_on",
|
||||
PollingOnAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"tag.polling_on", PollingOnAction, SIMPLE_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"tag.set_clean_mode",
|
||||
SetCleanModeAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"tag.set_format_mode",
|
||||
SetFormatModeAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"tag.set_read_mode",
|
||||
SetReadModeAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"tag.set_write_mode",
|
||||
SetWriteModeAction,
|
||||
SIMPLE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def pn7160_simple_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
@@ -246,7 +232,7 @@ async def setup_pn7160(var: MockObj, config: ConfigType) -> None:
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
automation.register_parented_condition(
|
||||
@automation.register_condition(
|
||||
"pn7160.is_writing",
|
||||
PN7160IsWritingCondition,
|
||||
cv.Schema(
|
||||
@@ -255,3 +241,12 @@ automation.register_parented_condition(
|
||||
}
|
||||
),
|
||||
)
|
||||
async def pn7160_is_writing_to_code(
|
||||
config: ConfigType,
|
||||
condition_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(condition_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
@@ -26,6 +26,8 @@ from esphome.const import (
|
||||
UNIT_WATT,
|
||||
UNIT_WATT_HOURS,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
AUTO_LOAD = ["modbus"]
|
||||
@@ -83,7 +85,7 @@ CONFIG_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"pzemac.reset_energy",
|
||||
ResetEnergyAction,
|
||||
maybe_simple_id(
|
||||
@@ -93,6 +95,14 @@ automation.register_simple_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def reset_energy_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
def _final_validate(config: ConfigType) -> None:
|
||||
|
||||
@@ -20,6 +20,8 @@ from esphome.const import (
|
||||
UNIT_VOLT,
|
||||
UNIT_WATT,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
AUTO_LOAD = ["modbus"]
|
||||
@@ -65,7 +67,7 @@ CONFIG_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"pzemdc.reset_energy",
|
||||
ResetEnergyAction,
|
||||
maybe_simple_id(
|
||||
@@ -75,6 +77,14 @@ automation.register_simple_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def reset_energy_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
def _final_validate(config: ConfigType) -> None:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import esphome.codegen as cg
|
||||
|
||||
CONF_ENABLE_FULL_PRINTF = "enable_full_printf"
|
||||
KEY_BOARD = "board"
|
||||
KEY_LWIP_OPTS = "lwip_opts"
|
||||
KEY_RP2 = "rp2"
|
||||
|
||||
@@ -81,19 +81,6 @@ void RuntimeStatsCollector::log_stats_() {
|
||||
ESP_LOGI(TAG, " main_loop_overhead_section: before=%.1fms, tail=%.1fms, inter_component=%.1fms",
|
||||
static_cast<double>(before) / 1000.0, static_cast<double>(tail) / 1000.0,
|
||||
static_cast<double>(inter) / 1000.0);
|
||||
uint64_t sched = this->period_before_sched_time_us_;
|
||||
uint64_t wdt = this->period_before_wdt_time_us_;
|
||||
uint64_t before_residual = before > sched + wdt ? before - sched - wdt : 0;
|
||||
ESP_LOGI(TAG, " main_loop_before_breakdown: sched=%.1fms, wdt=%.1fms, residual=%.1fms",
|
||||
static_cast<double>(sched) / 1000.0, static_cast<double>(wdt) / 1000.0,
|
||||
static_cast<double>(before_residual) / 1000.0);
|
||||
uint32_t wdt_slow_hits = App.wdt_slow_count_;
|
||||
App.wdt_slow_count_ = 0;
|
||||
ESP_LOGI(TAG, " wdt_slow_path: hits=%" PRIu32 " (%.1f%% of iters, avg=%.2fus/hit)", wdt_slow_hits,
|
||||
this->period_active_count_ > 0
|
||||
? 100.0 * static_cast<double>(wdt_slow_hits) / static_cast<double>(this->period_active_count_)
|
||||
: 0.0,
|
||||
wdt_slow_hits > 0 ? static_cast<double>(wdt) / static_cast<double>(wdt_slow_hits) : 0.0);
|
||||
}
|
||||
|
||||
// Log total stats since boot (only for active components - idle ones haven't changed)
|
||||
@@ -129,12 +116,6 @@ void RuntimeStatsCollector::log_stats_() {
|
||||
ESP_LOGI(TAG, " main_loop_overhead_section: before=%.1fms, tail=%.1fms, inter_component=%.1fms",
|
||||
static_cast<double>(before) / 1000.0, static_cast<double>(tail) / 1000.0,
|
||||
static_cast<double>(inter) / 1000.0);
|
||||
uint64_t sched = this->total_before_sched_time_us_;
|
||||
uint64_t wdt = this->total_before_wdt_time_us_;
|
||||
uint64_t before_residual = before > sched + wdt ? before - sched - wdt : 0;
|
||||
ESP_LOGI(TAG, " main_loop_before_breakdown: sched=%.1fms, wdt=%.1fms, residual=%.1fms",
|
||||
static_cast<double>(sched) / 1000.0, static_cast<double>(wdt) / 1000.0,
|
||||
static_cast<double>(before_residual) / 1000.0);
|
||||
}
|
||||
|
||||
// Reset period stats
|
||||
@@ -145,8 +126,6 @@ void RuntimeStatsCollector::log_stats_() {
|
||||
this->period_active_time_us_ = 0;
|
||||
this->period_active_max_us_ = 0;
|
||||
this->period_before_time_us_ = 0;
|
||||
this->period_before_sched_time_us_ = 0;
|
||||
this->period_before_wdt_time_us_ = 0;
|
||||
this->period_tail_time_us_ = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,8 +49,7 @@ class RuntimeStatsCollector final {
|
||||
// which captures per-iteration inter-component bookkeeping (set_current_component,
|
||||
// LoopBlockingGuard construction/destruction, feed_wdt_with_time calls,
|
||||
// the for-loop itself).
|
||||
void record_loop_active(uint32_t active_us, uint32_t before_us, uint32_t sched_us, uint32_t wdt_us,
|
||||
uint32_t tail_us) {
|
||||
void record_loop_active(uint32_t active_us, uint32_t before_us, uint32_t tail_us) {
|
||||
this->period_active_count_++;
|
||||
this->period_active_time_us_ += active_us;
|
||||
if (active_us > this->period_active_max_us_)
|
||||
@@ -62,10 +61,6 @@ class RuntimeStatsCollector final {
|
||||
|
||||
this->period_before_time_us_ += before_us;
|
||||
this->total_before_time_us_ += before_us;
|
||||
this->period_before_sched_time_us_ += sched_us;
|
||||
this->total_before_sched_time_us_ += sched_us;
|
||||
this->period_before_wdt_time_us_ += wdt_us;
|
||||
this->total_before_wdt_time_us_ += wdt_us;
|
||||
this->period_tail_time_us_ += tail_us;
|
||||
this->total_tail_time_us_ += tail_us;
|
||||
}
|
||||
@@ -93,11 +88,6 @@ class RuntimeStatsCollector final {
|
||||
// Split of overhead sections — accumulated per iteration.
|
||||
uint64_t period_before_time_us_{0};
|
||||
uint64_t total_before_time_us_{0};
|
||||
// Sub-split of `before` into scheduler_tick_ vs. post-scheduler feed_wdt_with_time.
|
||||
uint64_t period_before_sched_time_us_{0};
|
||||
uint64_t total_before_sched_time_us_{0};
|
||||
uint64_t period_before_wdt_time_us_{0};
|
||||
uint64_t total_before_wdt_time_us_{0};
|
||||
uint64_t period_tail_time_us_{0};
|
||||
uint64_t total_tail_time_us_{0};
|
||||
};
|
||||
|
||||
@@ -3,6 +3,8 @@ import esphome.codegen as cg
|
||||
from esphome.components import i2c, time
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@beormund"]
|
||||
@@ -20,7 +22,7 @@ CONFIG_SCHEMA = time.TIME_SCHEMA.extend(
|
||||
).extend(i2c.i2c_device_schema(0x32))
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"rx8130.write_time",
|
||||
WriteAction,
|
||||
cv.Schema(
|
||||
@@ -30,9 +32,18 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def rx8130_write_time_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"rx8130.read_time",
|
||||
ReadAction,
|
||||
automation.maybe_simple_id(
|
||||
@@ -42,6 +53,15 @@ automation.register_parented_action(
|
||||
),
|
||||
synchronous=True,
|
||||
)
|
||||
async def rx8130_read_time_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
|
||||
@@ -10,8 +10,8 @@ from esphome.const import (
|
||||
CONF_STORAGE,
|
||||
KEY_PAST_SAFE_MODE,
|
||||
)
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.cpp_generator import RawExpression
|
||||
from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority
|
||||
from esphome.cpp_generator import MockObj, RawExpression, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@paulmonigatti", "@jsuanet", "@kbx81"]
|
||||
@@ -22,6 +22,7 @@ CONF_ON_SAFE_MODE = "on_safe_mode"
|
||||
|
||||
safe_mode_ns = cg.esphome_ns.namespace("safe_mode")
|
||||
SafeModeComponent = safe_mode_ns.class_("SafeModeComponent", cg.Component)
|
||||
MarkSuccessfulAction = safe_mode_ns.class_("MarkSuccessfulAction", automation.Action)
|
||||
|
||||
|
||||
def _remove_id_if_disabled(value: ConfigType) -> ConfigType:
|
||||
@@ -52,15 +53,26 @@ CONFIG_SCHEMA = cv.All(
|
||||
)
|
||||
|
||||
|
||||
automation.register_apply_action(
|
||||
@automation.register_action(
|
||||
"safe_mode.mark_successful",
|
||||
MarkSuccessfulAction,
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(SafeModeComponent),
|
||||
}
|
||||
),
|
||||
automation.ApplyCall("mark_successful()"),
|
||||
synchronous=True,
|
||||
)
|
||||
async def safe_mode_mark_successful_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
parent = await cg.get_variable(config[CONF_ID])
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
cg.add(var.set_parent(parent))
|
||||
return var
|
||||
|
||||
|
||||
_CALLBACK_AUTOMATIONS = (
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "esphome/core/automation.h"
|
||||
#include "safe_mode.h"
|
||||
|
||||
namespace esphome::safe_mode {
|
||||
|
||||
template<typename... Ts> class MarkSuccessfulAction final : public Action<Ts...>, public Parented<SafeModeComponent> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->mark_successful(); }
|
||||
};
|
||||
|
||||
} // namespace esphome::safe_mode
|
||||
@@ -166,9 +166,18 @@ SCD4X_RESET_ACTION_SCHEMA = maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"scd4x.factory_reset",
|
||||
FactoryResetAction,
|
||||
SCD4X_RESET_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def scd4x_reset_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
@@ -9,6 +9,7 @@ CODEOWNERS = ["@esphome/core"]
|
||||
script_ns = cg.esphome_ns.namespace("script")
|
||||
Script = script_ns.class_("Script", automation.Trigger.template())
|
||||
ScriptExecuteAction = script_ns.class_("ScriptExecuteAction", automation.Action)
|
||||
ScriptStopAction = script_ns.class_("ScriptStopAction", automation.Action)
|
||||
ScriptWaitAction = script_ns.class_("ScriptWaitAction", automation.Action, cg.Component)
|
||||
SingleScript = script_ns.class_("SingleScript", Script)
|
||||
RestartScript = script_ns.class_("RestartScript", Script)
|
||||
@@ -205,11 +206,16 @@ async def script_execute_action_to_code(config, action_id, template_arg, args):
|
||||
return var
|
||||
|
||||
|
||||
automation.register_apply_action(
|
||||
@automation.register_action(
|
||||
"script.stop",
|
||||
ScriptStopAction,
|
||||
maybe_simple_id({cv.Required(CONF_ID): cv.use_id(Script)}),
|
||||
automation.ApplyCall("stop()"),
|
||||
synchronous=True,
|
||||
)
|
||||
async def script_stop_action_to_code(config, action_id, template_arg, args):
|
||||
full_id, paren = await cg.get_variable_with_full_id(config[CONF_ID])
|
||||
template_arg = cg.TemplateArguments(full_id.type, *template_arg)
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
|
||||
@@ -257,6 +257,16 @@ template<class... As, typename... Ts> class ScriptExecuteAction<Script<As...>, T
|
||||
Args args_;
|
||||
};
|
||||
|
||||
template<class C, typename... Ts> class ScriptStopAction final : public Action<Ts...> {
|
||||
public:
|
||||
ScriptStopAction(C *script) : script_(script) {}
|
||||
|
||||
void play(const Ts &...x) override { this->script_->stop(); }
|
||||
|
||||
protected:
|
||||
C *script_;
|
||||
};
|
||||
|
||||
/** Wait for a script to finish before continuing.
|
||||
*
|
||||
* Uses queue-based storage to safely handle concurrent executions.
|
||||
|
||||
@@ -43,6 +43,8 @@ from esphome.const import (
|
||||
UNIT_MICROGRAMS_PER_CUBIC_METER,
|
||||
UNIT_PERCENT,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@martgras"]
|
||||
@@ -280,9 +282,17 @@ SEN5X_ACTION_SCHEMA = maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"sen5x.start_fan_autoclean",
|
||||
StartFanAction,
|
||||
SEN5X_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def sen54_fan_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
@@ -21,8 +21,8 @@ from esphome.const import (
|
||||
CONF_VERSION,
|
||||
CONF_WIDTH,
|
||||
)
|
||||
from esphome.core import CORE
|
||||
from esphome.cpp_generator import MockObj
|
||||
from esphome.core import CORE, ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
# mdns for autodiscovery
|
||||
@@ -109,6 +109,13 @@ SendspinHub = sendspin_ns.class_(
|
||||
)
|
||||
|
||||
|
||||
SendspinSwitchCommandAction = sendspin_ns.class_(
|
||||
"SendspinSwitchCommandAction",
|
||||
automation.Action,
|
||||
cg.Parented.template(SendspinHub),
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class SendspinConfiguration:
|
||||
artwork_support: bool = False
|
||||
@@ -233,11 +240,21 @@ SENDSPIN_SIMPLE_ACTION_SCHEMA = cv.All(
|
||||
)
|
||||
|
||||
|
||||
automation.register_apply_action(
|
||||
@automation.register_action(
|
||||
"sendspin.switch",
|
||||
SendspinSwitchCommandAction,
|
||||
SENDSPIN_SIMPLE_ACTION_SCHEMA,
|
||||
automation.ApplyCall("switch_client()"),
|
||||
synchronous=True,
|
||||
)
|
||||
async def sendspin_switch_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/defines.h"
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
#include "sendspin_hub.h"
|
||||
|
||||
namespace esphome::sendspin_ {
|
||||
|
||||
#ifdef USE_SENDSPIN_CONTROLLER
|
||||
template<typename... Ts> class SendspinSwitchCommandAction final : public Action<Ts...>, public Parented<SendspinHub> {
|
||||
public:
|
||||
void play(const Ts &...x) override {
|
||||
// Clear any EXTERNAL_SOURCE state so the switch command is followed
|
||||
this->parent_->update_state(sendspin::SendspinClientState::SYNCHRONIZED);
|
||||
this->parent_->send_client_command(sendspin::SendspinControllerCommand::SWITCH);
|
||||
}
|
||||
};
|
||||
#endif // USE_SENDSPIN_CONTROLLER
|
||||
|
||||
} // namespace esphome::sendspin_
|
||||
|
||||
#endif // USE_ESP32
|
||||
@@ -16,6 +16,7 @@ from esphome.const import (
|
||||
CONF_WIDTH,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
from .. import (
|
||||
@@ -197,8 +198,16 @@ async def to_code(config: ConfigType) -> None:
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
|
||||
automation.register_apply_action(
|
||||
SendspinImageTransitionFinishedAction = sendspin_ns.class_(
|
||||
"SendspinImageTransitionFinishedAction",
|
||||
automation.Action,
|
||||
cg.Parented.template(SendspinImageSlot),
|
||||
)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"sendspin.image.transition_finished",
|
||||
SendspinImageTransitionFinishedAction,
|
||||
automation.maybe_simple_id(
|
||||
cv.Schema(
|
||||
{
|
||||
@@ -206,5 +215,14 @@ automation.register_apply_action(
|
||||
}
|
||||
)
|
||||
),
|
||||
automation.ApplyCall("transition_finished()"),
|
||||
synchronous=True,
|
||||
)
|
||||
async def sendspin_image_transition_finished_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> cg.MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/defines.h"
|
||||
|
||||
#if defined(USE_ESP32) && defined(USE_SENDSPIN_ARTWORK)
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
#include "sendspin_image.h"
|
||||
|
||||
namespace esphome::sendspin_ {
|
||||
|
||||
template<typename... Ts>
|
||||
class SendspinImageTransitionFinishedAction final : public Action<Ts...>, public Parented<SendspinImageSlot> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->transition_finished(); }
|
||||
};
|
||||
|
||||
} // namespace esphome::sendspin_
|
||||
|
||||
#endif
|
||||
@@ -8,6 +8,8 @@ from esphome.const import (
|
||||
CONF_SAMPLE_RATE,
|
||||
CONF_TASK_STACK_IN_PSRAM,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
from .. import (
|
||||
@@ -39,6 +41,18 @@ SendspinMediaSource = sendspin_ns.class_(
|
||||
media_source.MediaSource,
|
||||
)
|
||||
|
||||
EnableStaticDelayAdjustmentAction = sendspin_ns.class_(
|
||||
"EnableStaticDelayAdjustmentAction",
|
||||
automation.Action,
|
||||
cg.Parented.template(SendspinMediaSource),
|
||||
)
|
||||
|
||||
DisableStaticDelayAdjustmentAction = sendspin_ns.class_(
|
||||
"DisableStaticDelayAdjustmentAction",
|
||||
automation.Action,
|
||||
cg.Parented.template(SendspinMediaSource),
|
||||
)
|
||||
|
||||
|
||||
def _resolve_codecs(config: ConfigType) -> ConfigType:
|
||||
"""Validate the codec preference list, filling in the default when it is not set."""
|
||||
@@ -130,16 +144,25 @@ SENDSPIN_MEDIA_SOURCE_ACTION_SCHEMA = automation.maybe_simple_id(
|
||||
)
|
||||
)
|
||||
|
||||
for _name, _call in (
|
||||
(
|
||||
"sendspin.media_source.enable_static_delay_adjustment",
|
||||
"set_static_delay_adjustable(true)",
|
||||
),
|
||||
(
|
||||
"sendspin.media_source.disable_static_delay_adjustment",
|
||||
"set_static_delay_adjustable(false)",
|
||||
),
|
||||
):
|
||||
automation.register_apply_action(
|
||||
_name, SENDSPIN_MEDIA_SOURCE_ACTION_SCHEMA, automation.ApplyCall(_call)
|
||||
)
|
||||
|
||||
@automation.register_action(
|
||||
"sendspin.media_source.enable_static_delay_adjustment",
|
||||
EnableStaticDelayAdjustmentAction,
|
||||
SENDSPIN_MEDIA_SOURCE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
@automation.register_action(
|
||||
"sendspin.media_source.disable_static_delay_adjustment",
|
||||
DisableStaticDelayAdjustmentAction,
|
||||
SENDSPIN_MEDIA_SOURCE_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def sendspin_static_delay_adjustment_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/defines.h"
|
||||
|
||||
#if defined(USE_ESP32) && defined(USE_SENDSPIN_PLAYER) && defined(USE_SENDSPIN_CONTROLLER)
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
#include "sendspin_media_source.h"
|
||||
|
||||
namespace esphome::sendspin_ {
|
||||
|
||||
template<typename... Ts>
|
||||
class EnableStaticDelayAdjustmentAction final : public Action<Ts...>, public Parented<SendspinMediaSource> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->set_static_delay_adjustable(true); }
|
||||
};
|
||||
|
||||
template<typename... Ts>
|
||||
class DisableStaticDelayAdjustmentAction final : public Action<Ts...>, public Parented<SendspinMediaSource> {
|
||||
public:
|
||||
void play(const Ts &...x) override { this->parent_->set_static_delay_adjustable(false); }
|
||||
};
|
||||
|
||||
} // namespace esphome::sendspin_
|
||||
|
||||
#endif
|
||||
@@ -284,13 +284,6 @@ void SendspinHub::send_client_command(sendspin::SendspinControllerCommand comman
|
||||
}
|
||||
}
|
||||
|
||||
// THREAD CONTEXT: Main loop (invoked from the sendspin.switch action)
|
||||
void SendspinHub::switch_client() {
|
||||
// Clear any EXTERNAL_SOURCE state so the switch command is followed
|
||||
this->update_state(sendspin::SendspinClientState::SYNCHRONIZED);
|
||||
this->send_client_command(sendspin::SendspinControllerCommand::SWITCH);
|
||||
}
|
||||
|
||||
// THREAD CONTEXT: Main loop (ControllerRoleListener override, fired from client_->loop())
|
||||
void SendspinHub::on_controller_state(const sendspin::ServerStateControllerObject &state) {
|
||||
this->controller_state_callbacks_.call(state);
|
||||
|
||||
@@ -181,9 +181,6 @@ class SendspinHub final : public Component,
|
||||
void send_client_command(sendspin::SendspinControllerCommand command, std::optional<uint8_t> volume = std::nullopt,
|
||||
std::optional<bool> mute = std::nullopt);
|
||||
|
||||
/// @brief Sends the SWITCH controller command; exposed as the sendspin.switch action.
|
||||
void switch_client();
|
||||
|
||||
template<typename F> void add_controller_state_callback(F &&callback) {
|
||||
this->controller_state_callbacks_.add(std::forward<F>(callback));
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ from esphome.const import (
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_PARTS_PER_MILLION,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
DEPENDENCIES = ["uart"]
|
||||
@@ -80,41 +82,41 @@ CALIBRATION_ACTION_SCHEMA = maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"senseair.background_calibration",
|
||||
SenseAirBackgroundCalibrationAction,
|
||||
CALIBRATION_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"senseair.background_calibration_result",
|
||||
SenseAirBackgroundCalibrationResultAction,
|
||||
CALIBRATION_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"senseair.abc_enable",
|
||||
SenseAirABCEnableAction,
|
||||
CALIBRATION_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"senseair.abc_disable",
|
||||
SenseAirABCDisableAction,
|
||||
CALIBRATION_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"senseair.abc_get_period",
|
||||
SenseAirABCGetPeriodAction,
|
||||
CALIBRATION_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def senseair_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
@@ -125,12 +125,15 @@ async def sim800l_dial_to_code(config, action_id, template_arg, args):
|
||||
return var
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"sim800l.connect",
|
||||
Sim800LConnectAction,
|
||||
cv.Schema({cv.GenerateID(): cv.use_id(Sim800LComponent)}),
|
||||
synchronous=True,
|
||||
)
|
||||
async def sim800l_connect_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
SIM800L_SEND_USSD_SCHEMA = cv.Schema(
|
||||
@@ -155,9 +158,12 @@ async def sim800l_send_ussd_to_code(config, action_id, template_arg, args):
|
||||
return var
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"sim800l.disconnect",
|
||||
Sim800LDisconnectAction,
|
||||
cv.Schema({cv.GenerateID(): cv.use_id(Sim800LComponent)}),
|
||||
synchronous=True,
|
||||
)
|
||||
async def sim800l_disconnect_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
@@ -11,6 +11,8 @@ from esphome.const import (
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_DECIBEL,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
AUTO_LOAD = ["audio"]
|
||||
@@ -90,17 +92,18 @@ SOUND_LEVEL_ACTION_SCHEMA = automation.maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
"sound_level.start",
|
||||
StartAction,
|
||||
SOUND_LEVEL_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"sound_level.start", StartAction, SOUND_LEVEL_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
"sound_level.stop",
|
||||
StopAction,
|
||||
SOUND_LEVEL_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
@automation.register_action(
|
||||
"sound_level.stop", StopAction, SOUND_LEVEL_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
async def sound_level_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
@@ -26,7 +26,7 @@ CONFIG_SCHEMA = (
|
||||
cv.Optional(CONF_SPEED): cv.invalid(
|
||||
"Configuring individual speeds is deprecated."
|
||||
),
|
||||
cv.Optional(CONF_SPEED_COUNT, default=100): cv.int_range(min=1, max=255),
|
||||
cv.Optional(CONF_SPEED_COUNT, default=100): cv.int_range(min=1),
|
||||
cv.Optional(CONF_PRESET_MODES): validate_preset_modes,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace esphome::speed {
|
||||
|
||||
class SpeedFan final : public Component, public fan::Fan {
|
||||
public:
|
||||
SpeedFan(uint8_t speed_count) : speed_count_(speed_count) {}
|
||||
SpeedFan(int speed_count) : speed_count_(speed_count) {}
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
void set_output(output::FloatOutput *output) { this->output_ = output; }
|
||||
@@ -28,7 +28,7 @@ class SpeedFan final : public Component, public fan::Fan {
|
||||
output::FloatOutput *output_;
|
||||
output::BinaryOutput *oscillating_{nullptr};
|
||||
output::BinaryOutput *direction_{nullptr};
|
||||
uint8_t speed_count_{};
|
||||
int speed_count_{};
|
||||
fan::FanTraits traits_;
|
||||
};
|
||||
|
||||
|
||||
@@ -66,10 +66,19 @@ SprinklerControllerSwitch = sprinkler_ns.class_(
|
||||
"SprinklerControllerSwitch", switch.Switch, cg.Component
|
||||
)
|
||||
|
||||
ClearQueuedValvesAction = sprinkler_ns.class_(
|
||||
"ClearQueuedValvesAction", automation.Action
|
||||
)
|
||||
StartFromQueueAction = sprinkler_ns.class_("StartFromQueueAction", automation.Action)
|
||||
StartFullCycleAction = sprinkler_ns.class_("StartFullCycleAction", automation.Action)
|
||||
StartSingleValveAction = sprinkler_ns.class_(
|
||||
"StartSingleValveAction", automation.Action
|
||||
)
|
||||
ShutdownAction = sprinkler_ns.class_("ShutdownAction", automation.Action)
|
||||
NextValveAction = sprinkler_ns.class_("NextValveAction", automation.Action)
|
||||
PreviousValveAction = sprinkler_ns.class_("PreviousValveAction", automation.Action)
|
||||
PauseAction = sprinkler_ns.class_("PauseAction", automation.Action)
|
||||
ResumeAction = sprinkler_ns.class_("ResumeAction", automation.Action)
|
||||
ResumeOrStartAction = sprinkler_ns.class_("ResumeOrStartAction", automation.Action)
|
||||
|
||||
|
||||
@@ -406,61 +415,57 @@ CONFIG_SCHEMA = cv.All(
|
||||
|
||||
_VALVE_AND_DURATION = ((CONF_VALVE_NUMBER, cg.size_t), (CONF_RUN_DURATION, cg.uint32))
|
||||
|
||||
for _name, _schema, _apply in (
|
||||
(
|
||||
"sprinkler.set_divider",
|
||||
SPRINKLER_ACTION_SET_DIVIDER_SCHEMA,
|
||||
automation.ApplyField(CONF_DIVIDER, "set_divider", cg.uint32),
|
||||
),
|
||||
(
|
||||
"sprinkler.set_multiplier",
|
||||
SPRINKLER_ACTION_SET_MULTIPLIER_SCHEMA,
|
||||
automation.ApplyField(CONF_MULTIPLIER, "set_multiplier", cg.float_),
|
||||
),
|
||||
(
|
||||
"sprinkler.queue_valve",
|
||||
SPRINKLER_ACTION_QUEUE_VALVE_SCHEMA,
|
||||
automation.ApplyCall("queue_valve({}, {})", _VALVE_AND_DURATION),
|
||||
),
|
||||
(
|
||||
"sprinkler.set_repeat",
|
||||
SPRINKLER_ACTION_REPEAT_SCHEMA,
|
||||
automation.ApplyField(CONF_REPEAT, "set_repeat", cg.uint32),
|
||||
),
|
||||
(
|
||||
"sprinkler.set_valve_run_duration",
|
||||
SPRINKLER_ACTION_SET_RUN_DURATION_SCHEMA,
|
||||
automation.ApplyCall("set_valve_run_duration({}, {})", _VALVE_AND_DURATION),
|
||||
),
|
||||
(
|
||||
"sprinkler.start_from_queue",
|
||||
SPRINKLER_ACTION_SCHEMA,
|
||||
automation.ApplyCall("start_from_queue()"),
|
||||
),
|
||||
(
|
||||
"sprinkler.start_full_cycle",
|
||||
SPRINKLER_ACTION_SCHEMA,
|
||||
automation.ApplyCall("start_full_cycle()"),
|
||||
),
|
||||
(
|
||||
"sprinkler.clear_queued_valves",
|
||||
SPRINKLER_ACTION_SCHEMA,
|
||||
automation.ApplyCall("clear_queued_valves()"),
|
||||
),
|
||||
(
|
||||
"sprinkler.next_valve",
|
||||
SPRINKLER_ACTION_SCHEMA,
|
||||
automation.ApplyCall("next_valve()"),
|
||||
),
|
||||
(
|
||||
"sprinkler.previous_valve",
|
||||
SPRINKLER_ACTION_SCHEMA,
|
||||
automation.ApplyCall("previous_valve()"),
|
||||
),
|
||||
("sprinkler.pause", SPRINKLER_ACTION_SCHEMA, automation.ApplyCall("pause()")),
|
||||
("sprinkler.resume", SPRINKLER_ACTION_SCHEMA, automation.ApplyCall("resume()")),
|
||||
):
|
||||
automation.register_apply_action(_name, _schema, _apply)
|
||||
automation.register_apply_action(
|
||||
"sprinkler.set_divider",
|
||||
SPRINKLER_ACTION_SET_DIVIDER_SCHEMA,
|
||||
automation.ApplyField(CONF_DIVIDER, "set_divider", cg.uint32),
|
||||
)
|
||||
|
||||
automation.register_apply_action(
|
||||
"sprinkler.set_multiplier",
|
||||
SPRINKLER_ACTION_SET_MULTIPLIER_SCHEMA,
|
||||
automation.ApplyField(CONF_MULTIPLIER, "set_multiplier", cg.float_),
|
||||
)
|
||||
|
||||
automation.register_apply_action(
|
||||
"sprinkler.queue_valve",
|
||||
SPRINKLER_ACTION_QUEUE_VALVE_SCHEMA,
|
||||
automation.ApplyCall("queue_valve({}, {})", _VALVE_AND_DURATION),
|
||||
)
|
||||
|
||||
automation.register_apply_action(
|
||||
"sprinkler.set_repeat",
|
||||
SPRINKLER_ACTION_REPEAT_SCHEMA,
|
||||
automation.ApplyField(CONF_REPEAT, "set_repeat", cg.uint32),
|
||||
)
|
||||
|
||||
automation.register_apply_action(
|
||||
"sprinkler.set_valve_run_duration",
|
||||
SPRINKLER_ACTION_SET_RUN_DURATION_SCHEMA,
|
||||
automation.ApplyCall("set_valve_run_duration({}, {})", _VALVE_AND_DURATION),
|
||||
)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"sprinkler.start_from_queue",
|
||||
StartFromQueueAction,
|
||||
SPRINKLER_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def sprinkler_start_from_queue_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"sprinkler.start_full_cycle",
|
||||
StartFullCycleAction,
|
||||
SPRINKLER_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def sprinkler_start_full_cycle_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
@@ -480,20 +485,45 @@ async def sprinkler_start_single_valve_to_code(config, action_id, template_arg,
|
||||
return var
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"sprinkler.clear_queued_valves",
|
||||
ClearQueuedValvesAction,
|
||||
SPRINKLER_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
@automation.register_action(
|
||||
"sprinkler.next_valve",
|
||||
NextValveAction,
|
||||
SPRINKLER_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
@automation.register_action(
|
||||
"sprinkler.previous_valve",
|
||||
PreviousValveAction,
|
||||
SPRINKLER_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
@automation.register_action(
|
||||
"sprinkler.pause", PauseAction, SPRINKLER_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
@automation.register_action(
|
||||
"sprinkler.resume", ResumeAction, SPRINKLER_ACTION_SCHEMA, synchronous=True
|
||||
)
|
||||
@automation.register_action(
|
||||
"sprinkler.resume_or_start_full_cycle",
|
||||
ResumeOrStartAction,
|
||||
SPRINKLER_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_simple_action(
|
||||
@automation.register_action(
|
||||
"sprinkler.shutdown",
|
||||
ShutdownAction,
|
||||
SPRINKLER_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def sprinkler_simple_action_to_code(config, action_id, template_arg, args):
|
||||
paren = await cg.get_variable(config[CONF_ID])
|
||||
return cg.new_Pvariable(action_id, template_arg, paren)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
|
||||
@@ -6,6 +6,36 @@
|
||||
|
||||
namespace esphome::sprinkler {
|
||||
|
||||
template<typename... Ts> class ClearQueuedValvesAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit ClearQueuedValvesAction(Sprinkler *a_sprinkler) : sprinkler_(a_sprinkler) {}
|
||||
|
||||
void play(const Ts &...x) override { this->sprinkler_->clear_queued_valves(); }
|
||||
|
||||
protected:
|
||||
Sprinkler *sprinkler_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class StartFromQueueAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit StartFromQueueAction(Sprinkler *a_sprinkler) : sprinkler_(a_sprinkler) {}
|
||||
|
||||
void play(const Ts &...x) override { this->sprinkler_->start_from_queue(); }
|
||||
|
||||
protected:
|
||||
Sprinkler *sprinkler_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class StartFullCycleAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit StartFullCycleAction(Sprinkler *a_sprinkler) : sprinkler_(a_sprinkler) {}
|
||||
|
||||
void play(const Ts &...x) override { this->sprinkler_->start_full_cycle(); }
|
||||
|
||||
protected:
|
||||
Sprinkler *sprinkler_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class StartSingleValveAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit StartSingleValveAction(Sprinkler *a_sprinkler) : sprinkler_(a_sprinkler) {}
|
||||
@@ -34,6 +64,46 @@ template<typename... Ts> class ShutdownAction final : public Action<Ts...> {
|
||||
Sprinkler *sprinkler_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class NextValveAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit NextValveAction(Sprinkler *a_sprinkler) : sprinkler_(a_sprinkler) {}
|
||||
|
||||
void play(const Ts &...x) override { this->sprinkler_->next_valve(); }
|
||||
|
||||
protected:
|
||||
Sprinkler *sprinkler_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class PreviousValveAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit PreviousValveAction(Sprinkler *a_sprinkler) : sprinkler_(a_sprinkler) {}
|
||||
|
||||
void play(const Ts &...x) override { this->sprinkler_->previous_valve(); }
|
||||
|
||||
protected:
|
||||
Sprinkler *sprinkler_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class PauseAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit PauseAction(Sprinkler *a_sprinkler) : sprinkler_(a_sprinkler) {}
|
||||
|
||||
void play(const Ts &...x) override { this->sprinkler_->pause(); }
|
||||
|
||||
protected:
|
||||
Sprinkler *sprinkler_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class ResumeAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit ResumeAction(Sprinkler *a_sprinkler) : sprinkler_(a_sprinkler) {}
|
||||
|
||||
void play(const Ts &...x) override { this->sprinkler_->resume(); }
|
||||
|
||||
protected:
|
||||
Sprinkler *sprinkler_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class ResumeOrStartAction final : public Action<Ts...> {
|
||||
public:
|
||||
explicit ResumeOrStartAction(Sprinkler *a_sprinkler) : sprinkler_(a_sprinkler) {}
|
||||
|
||||
@@ -26,6 +26,8 @@ from esphome.const import (
|
||||
UNIT_MICROGRAMS_PER_CUBIC_METER,
|
||||
UNIT_MICROMETER,
|
||||
)
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj, TemplateArgsType
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@martgras"]
|
||||
@@ -180,25 +182,30 @@ SPS30_ACTION_SCHEMA = maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"sps30.start_fan_autoclean",
|
||||
StartFanAction,
|
||||
SPS30_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"sps30.start_measurement",
|
||||
StartMeasurementAction,
|
||||
SPS30_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"sps30.stop_measurement",
|
||||
StopMeasurementAction,
|
||||
SPS30_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def sps30_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
@@ -302,36 +302,39 @@ NO_ARGS_ACTION_SCHEMA = automation.maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"sx126x.run_image_cal",
|
||||
RunImageCalAction,
|
||||
NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"sx126x.set_mode_tx",
|
||||
SetModeTxAction,
|
||||
NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"sx126x.set_mode_rx",
|
||||
SetModeRxAction,
|
||||
NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"sx126x.set_mode_standby",
|
||||
SetModeStandbyAction,
|
||||
NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def no_args_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
SET_MODE_SLEEP_ACTION_SCHEMA = automation.maybe_simple_id(
|
||||
|
||||
@@ -286,44 +286,45 @@ NO_ARGS_ACTION_SCHEMA = automation.maybe_simple_id(
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"sx127x.run_image_cal",
|
||||
RunImageCalAction,
|
||||
NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"sx127x.set_mode_tx",
|
||||
SetModeTxAction,
|
||||
NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"sx127x.set_mode_rx",
|
||||
SetModeRxAction,
|
||||
NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"sx127x.set_mode_sleep",
|
||||
SetModeSleepAction,
|
||||
NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
|
||||
|
||||
automation.register_parented_action(
|
||||
@automation.register_action(
|
||||
"sx127x.set_mode_standby",
|
||||
SetModeStandbyAction,
|
||||
NO_ARGS_ACTION_SCHEMA,
|
||||
synchronous=True,
|
||||
)
|
||||
async def no_args_action_to_code(
|
||||
config: ConfigType,
|
||||
action_id: ID,
|
||||
template_arg: cg.TemplateArguments,
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
SEND_PACKET_ACTION_SCHEMA = cv.maybe_simple_value(
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user