Compare commits

...
Author SHA1 Message Date
J. Nick Koston ca54b92204 Merge remote-tracking branch 'origin/dev' into apply-entities-switch 2026-10-19 07:52:32 -10:00
J. Nick Koston e21d3217bd Merge branch 'apply-entities' into apply-entities-switch 2026-10-16 14:07:10 -10:00
J. Nick Koston 754a960ed1 [core] Declare apply locals right before their first use
A local declared at the top ran option_at before a publish placed before
the statement, which changed the call order and grew ld2412 by 16 bytes.
2026-10-16 14:06:17 -10:00
J. Nick Koston 49337d8ad3 Merge branch 'apply-entities' into apply-entities-switch 2026-10-16 14:04:31 -10:00
J. Nick Koston f7a60f5859 [core] Give select apply statements an option local
Select apply statements can name the selected option text as option; the
local is declared only when a statement uses it.
2026-10-16 14:04:26 -10:00
J. Nick Koston 2edef5cfd9 [seeed_mr24hpc1] Use Apply switches 2026-10-16 13:46:00 -10:00
J. Nick Koston 825e71c74a [ld2450] Use Apply switches 2026-10-16 13:46:00 -10:00
J. Nick Koston 3275f6e4a8 [ld2412] Use Apply switches 2026-10-16 13:46:00 -10:00
J. Nick Koston 3e393631eb [ld2410] Use Apply switches 2026-10-16 13:45:59 -10:00
J. Nick Koston c6bfc403b5 [at581x] Use Apply switches 2026-10-16 13:45:59 -10:00
J. Nick Koston b8a0de91db [core] Simplify the Apply entity helpers
Fold the function cache into SubEntities, make each domain's APPLY_ENTITY public,
shorten the class and docstring comments and reuse the shared test hub.
2026-10-16 13:42:23 -10:00
J. Nick Koston 2937d81216 Mark the test recorders as intentional mutable globals 2026-10-16 12:20:50 -10:00
J. Nick Koston 05a4b256db Reject an unknown publish= value 2026-10-16 11:45:47 -10:00
J. Nick Koston d0427c36eb [core] Share the apply function naming with automations and check the Apply class at codegen 2026-10-16 11:04:36 -10:00
J. Nick Koston a990231342 [core] Add Apply button, switch, number and select entities for hub forwarders 2026-10-16 10:48:29 -10:00
21 changed files with 57 additions and 247 deletions
+6 -7
View File
@@ -4,14 +4,13 @@ import esphome.config_validation as cv
from esphome.const import DEVICE_CLASS_SWITCH, ICON_WIFI
from esphome.types import ConfigType
from .. import CONF_AT581X_ID, AT581XComponent, at581x_ns
from .. import CONF_AT581X_ID, AT581XComponent
DEPENDENCIES = ["at581x"]
RFSwitch = at581x_ns.class_("RFSwitch", switch.Switch)
CONFIG_SCHEMA = switch.switch_schema(
RFSwitch,
switch.ApplySwitch,
device_class=DEVICE_CLASS_SWITCH,
icon=ICON_WIFI,
).extend(
@@ -24,7 +23,7 @@ CONFIG_SCHEMA = switch.switch_schema(
async def to_code(config: ConfigType) -> None:
at581x_component = await cg.get_variable(config[CONF_AT581X_ID])
s = await switch.new_switch(config)
await cg.register_parented(s, config[CONF_AT581X_ID])
cg.add(at581x_component.set_rf_power_switch(s))
hub = await cg.get_variable(config[CONF_AT581X_ID])
await switch.sub_switches(config, parent=hub).create(
config, hub.set_rf_power_switch, apply="set_rf_mode(state)", publish="before"
)
@@ -1,10 +0,0 @@
#include "rf_switch.h"
namespace esphome::at581x {
void RFSwitch::write_state(bool state) {
this->publish_state(state);
this->parent_->set_rf_mode(state);
}
} // namespace esphome::at581x
@@ -1,13 +0,0 @@
#pragma once
#include "esphome/components/switch/switch.h"
#include "../at581x.h"
namespace esphome::at581x {
class RFSwitch final : public switch_::Switch, public Parented<AT581XComponent> {
protected:
void write_state(bool state) override;
};
} // namespace esphome::at581x
+15 -8
View File
@@ -11,10 +11,7 @@ from esphome.const import (
)
from esphome.types import ConfigType
from .. import CONF_LD2410_ID, LD2410Component, ld2410_ns
BluetoothSwitch = ld2410_ns.class_("BluetoothSwitch", switch.Switch)
EngineeringModeSwitch = ld2410_ns.class_("EngineeringModeSwitch", switch.Switch)
from .. import CONF_LD2410_ID, LD2410Component
CONF_ENGINEERING_MODE = "engineering_mode"
@@ -22,13 +19,13 @@ CONFIG_SCHEMA = {
cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase),
cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component),
cv.Optional(CONF_ENGINEERING_MODE): switch.switch_schema(
EngineeringModeSwitch,
switch.ApplySwitch,
device_class=DEVICE_CLASS_SWITCH,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_PULSE,
),
cv.Optional(CONF_BLUETOOTH): switch.switch_schema(
BluetoothSwitch,
switch.ApplySwitch,
device_class=DEVICE_CLASS_SWITCH,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_BLUETOOTH,
@@ -39,5 +36,15 @@ CONFIG_SCHEMA = {
async def to_code(config: ConfigType) -> None:
hub = await cg.get_variable(config[CONF_LD2410_ID])
switches = switch.sub_switches(config, parent=hub)
await switches(CONF_ENGINEERING_MODE, hub.set_engineering_mode_switch)
await switches(CONF_BLUETOOTH, hub.set_bluetooth_switch)
await switches(
CONF_ENGINEERING_MODE,
hub.set_engineering_mode_switch,
apply="set_engineering_mode(state)",
publish="before",
)
await switches(
CONF_BLUETOOTH,
hub.set_bluetooth_switch,
apply="set_bluetooth(state)",
publish="before",
)
@@ -1,10 +0,0 @@
#include "bluetooth_switch.h"
namespace esphome::ld2410 {
void BluetoothSwitch::write_state(bool state) {
this->publish_state(state);
this->parent_->set_bluetooth(state);
}
} // namespace esphome::ld2410
@@ -1,16 +0,0 @@
#pragma once
#include "esphome/components/switch/switch.h"
#include "../ld2410.h"
namespace esphome::ld2410 {
class BluetoothSwitch final : public switch_::Switch, public Parented<LD2410Component> {
public:
BluetoothSwitch() = default;
protected:
void write_state(bool state) override;
};
} // namespace esphome::ld2410
@@ -1,10 +0,0 @@
#include "engineering_mode_switch.h"
namespace esphome::ld2410 {
void EngineeringModeSwitch::write_state(bool state) {
this->publish_state(state);
this->parent_->set_engineering_mode(state);
}
} // namespace esphome::ld2410
@@ -1,16 +0,0 @@
#pragma once
#include "esphome/components/switch/switch.h"
#include "../ld2410.h"
namespace esphome::ld2410 {
class EngineeringModeSwitch final : public switch_::Switch, public Parented<LD2410Component> {
public:
EngineeringModeSwitch() = default;
protected:
void write_state(bool state) override;
};
} // namespace esphome::ld2410
+15 -8
View File
@@ -11,10 +11,7 @@ from esphome.const import (
)
from esphome.types import ConfigType
from .. import CONF_LD2412_ID, LD2412_ns, LD2412Component
BluetoothSwitch = LD2412_ns.class_("BluetoothSwitch", switch.Switch)
EngineeringModeSwitch = LD2412_ns.class_("EngineeringModeSwitch", switch.Switch)
from .. import CONF_LD2412_ID, LD2412Component
CONF_ENGINEERING_MODE = "engineering_mode"
@@ -22,13 +19,13 @@ CONFIG_SCHEMA = {
cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase),
cv.GenerateID(CONF_LD2412_ID): cv.use_id(LD2412Component),
cv.Optional(CONF_BLUETOOTH): switch.switch_schema(
BluetoothSwitch,
switch.ApplySwitch,
device_class=DEVICE_CLASS_SWITCH,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_BLUETOOTH,
),
cv.Optional(CONF_ENGINEERING_MODE): switch.switch_schema(
EngineeringModeSwitch,
switch.ApplySwitch,
device_class=DEVICE_CLASS_SWITCH,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_PULSE,
@@ -39,5 +36,15 @@ CONFIG_SCHEMA = {
async def to_code(config: ConfigType) -> None:
hub = await cg.get_variable(config[CONF_LD2412_ID])
switches = switch.sub_switches(config, parent=hub)
await switches(CONF_BLUETOOTH, hub.set_bluetooth_switch)
await switches(CONF_ENGINEERING_MODE, hub.set_engineering_mode_switch)
await switches(
CONF_BLUETOOTH,
hub.set_bluetooth_switch,
apply="set_bluetooth(state)",
publish="before",
)
await switches(
CONF_ENGINEERING_MODE,
hub.set_engineering_mode_switch,
apply="set_engineering_mode(state)",
publish="before",
)
@@ -1,10 +0,0 @@
#include "bluetooth_switch.h"
namespace esphome::ld2412 {
void BluetoothSwitch::write_state(bool state) {
this->publish_state(state);
this->parent_->set_bluetooth(state);
}
} // namespace esphome::ld2412
@@ -1,17 +0,0 @@
#pragma once
#include "esphome/components/switch/switch.h"
#include "../ld2412.h"
namespace esphome::ld2412 {
class BluetoothSwitch final : public switch_::Switch, public Parented<LD2412Component> {
public:
// User provided, not "= default": `new(p) BluetoothSwitch()` would zero-fill .bss that is already zero.
BluetoothSwitch() {}
protected:
void write_state(bool state) override;
};
} // namespace esphome::ld2412
@@ -1,10 +0,0 @@
#include "engineering_mode_switch.h"
namespace esphome::ld2412 {
void EngineeringModeSwitch::write_state(bool state) {
this->publish_state(state);
this->parent_->set_engineering_mode(state);
}
} // namespace esphome::ld2412
@@ -1,17 +0,0 @@
#pragma once
#include "esphome/components/switch/switch.h"
#include "../ld2412.h"
namespace esphome::ld2412 {
class EngineeringModeSwitch final : public switch_::Switch, public Parented<LD2412Component> {
public:
// User provided, not "= default": `new(p) EngineeringModeSwitch()` would zero-fill .bss that is already zero.
EngineeringModeSwitch() {}
protected:
void write_state(bool state) override;
};
} // namespace esphome::ld2412
+15 -8
View File
@@ -11,10 +11,7 @@ from esphome.const import (
)
from esphome.types import ConfigType
from .. import CONF_LD2450_ID, LD2450Component, ld2450_ns
BluetoothSwitch = ld2450_ns.class_("BluetoothSwitch", switch.Switch)
MultiTargetSwitch = ld2450_ns.class_("MultiTargetSwitch", switch.Switch)
from .. import CONF_LD2450_ID, LD2450Component
CONF_MULTI_TARGET = "multi_target"
@@ -22,13 +19,13 @@ CONFIG_SCHEMA = {
cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase),
cv.GenerateID(CONF_LD2450_ID): cv.use_id(LD2450Component),
cv.Optional(CONF_BLUETOOTH): switch.switch_schema(
BluetoothSwitch,
switch.ApplySwitch,
device_class=DEVICE_CLASS_SWITCH,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_BLUETOOTH,
),
cv.Optional(CONF_MULTI_TARGET): switch.switch_schema(
MultiTargetSwitch,
switch.ApplySwitch,
device_class=DEVICE_CLASS_SWITCH,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_PULSE,
@@ -39,5 +36,15 @@ CONFIG_SCHEMA = {
async def to_code(config: ConfigType) -> None:
hub = await cg.get_variable(config[CONF_LD2450_ID])
switches = switch.sub_switches(config, parent=hub)
await switches(CONF_BLUETOOTH, hub.set_bluetooth_switch)
await switches(CONF_MULTI_TARGET, hub.set_multi_target_switch)
await switches(
CONF_BLUETOOTH,
hub.set_bluetooth_switch,
apply="set_bluetooth(state)",
publish="before",
)
await switches(
CONF_MULTI_TARGET,
hub.set_multi_target_switch,
apply="set_multi_target(state)",
publish="before",
)
@@ -1,10 +0,0 @@
#include "bluetooth_switch.h"
namespace esphome::ld2450 {
void BluetoothSwitch::write_state(bool state) {
this->publish_state(state);
this->parent_->set_bluetooth(state);
}
} // namespace esphome::ld2450
@@ -1,17 +0,0 @@
#pragma once
#include "esphome/components/switch/switch.h"
#include "../ld2450.h"
namespace esphome::ld2450 {
class BluetoothSwitch : public switch_::Switch, public Parented<LD2450Component> {
public:
// User provided, not "= default": `new(p) BluetoothSwitch()` would zero-fill .bss that is already zero.
BluetoothSwitch() {}
protected:
void write_state(bool state) override;
};
} // namespace esphome::ld2450
@@ -1,10 +0,0 @@
#include "multi_target_switch.h"
namespace esphome::ld2450 {
void MultiTargetSwitch::write_state(bool state) {
this->publish_state(state);
this->parent_->set_multi_target(state);
}
} // namespace esphome::ld2450
@@ -1,17 +0,0 @@
#pragma once
#include "esphome/components/switch/switch.h"
#include "../ld2450.h"
namespace esphome::ld2450 {
class MultiTargetSwitch : public switch_::Switch, public Parented<LD2450Component> {
public:
// User provided, not "= default": `new(p) MultiTargetSwitch()` would zero-fill .bss that is already zero.
MultiTargetSwitch() {}
protected:
void write_state(bool state) override;
};
} // namespace esphome::ld2450
@@ -4,18 +4,14 @@ import esphome.config_validation as cv
from esphome.const import DEVICE_CLASS_SWITCH, ENTITY_CATEGORY_CONFIG
from esphome.types import ConfigType
from .. import CONF_MR24HPC1_ID, MR24HPC1Component, mr24hpc1_ns
UnderlyingOpenFuncSwitch = mr24hpc1_ns.class_(
"UnderlyOpenFunctionSwitch", switch.Switch
)
from .. import CONF_MR24HPC1_ID, MR24HPC1Component
CONF_UNDERLYING_OPEN_FUNCTION = "underlying_open_function"
CONFIG_SCHEMA = {
cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component),
cv.Optional(CONF_UNDERLYING_OPEN_FUNCTION): switch.switch_schema(
UnderlyingOpenFuncSwitch,
switch.ApplySwitch,
device_class=DEVICE_CLASS_SWITCH,
entity_category=ENTITY_CATEGORY_CONFIG,
icon="mdi:electric-switch",
@@ -27,5 +23,8 @@ async def to_code(config: ConfigType) -> None:
hub = await cg.get_variable(config[CONF_MR24HPC1_ID])
switches = switch.sub_switches(config, parent=hub)
await switches(
CONF_UNDERLYING_OPEN_FUNCTION, hub.set_underlying_open_function_switch
CONF_UNDERLYING_OPEN_FUNCTION,
hub.set_underlying_open_function_switch,
apply="set_underlying_open_function(state)",
publish="before",
)
@@ -1,10 +0,0 @@
#include "underlyFuc_switch.h"
namespace esphome::seeed_mr24hpc1 {
void UnderlyOpenFunctionSwitch::write_state(bool state) {
this->publish_state(state);
this->parent_->set_underlying_open_function(state);
}
} // namespace esphome::seeed_mr24hpc1
@@ -1,16 +0,0 @@
#pragma once
#include "esphome/components/switch/switch.h"
#include "../seeed_mr24hpc1.h"
namespace esphome::seeed_mr24hpc1 {
class UnderlyOpenFunctionSwitch final : public switch_::Switch, public Parented<MR24HPC1Component> {
public:
UnderlyOpenFunctionSwitch() = default;
protected:
void write_state(bool state) override;
};
} // namespace esphome::seeed_mr24hpc1