diff --git a/esphome/components/espnow/__init__.py b/esphome/components/espnow/__init__.py index 14d099ec06..c04cf1ed59 100644 --- a/esphome/components/espnow/__init__.py +++ b/esphome/components/espnow/__init__.py @@ -39,9 +39,6 @@ ESPNowRecvInfo = espnow_ns.class_("ESPNowRecvInfo") ESPNowRecvInfoConstRef = ESPNowRecvInfo.operator("const").operator("ref") SendAction = espnow_ns.class_("SendAction", automation.Action) -SetChannelAction = espnow_ns.class_("SetChannelAction", automation.Action) -AddPeerAction = espnow_ns.class_("AddPeerAction", automation.Action) -DeletePeerAction = espnow_ns.class_("DeletePeerAction", automation.Action) ESPNowHandlerTrigger = automation.Trigger.template( ESPNowRecvInfoConstRef, @@ -232,12 +229,16 @@ def _validate_raw_data(value: Any) -> str | list: ) +def _mac_bytes(address: core.MACAddress) -> list[HexInt]: + return [HexInt(p) for p in address.parts] + + async def register_peer( var: MockObj, config: ConfigType, args: TemplateArgsType ) -> None: peer = config[CONF_ADDRESS] if isinstance(peer, core.MACAddress): - peer = [HexInt(p) for p in peer.parts] + peer = _mac_bytes(peer) template_ = await cg.templatable(peer, args, peer_address_t, peer_address_t) cg.add(var.set_address(template_)) @@ -323,40 +324,28 @@ async def send_action( return var -@automation.register_action( - "espnow.peer.add", - AddPeerAction, - cv.maybe_simple_value( - PEER_SCHEMA, - key=CONF_ADDRESS, - ), - synchronous=True, -) -@automation.register_action( - "espnow.peer.delete", - DeletePeerAction, - cv.maybe_simple_value( - PEER_SCHEMA, - key=CONF_ADDRESS, - ), - synchronous=True, -) -async def peer_action( - config: ConfigType, - action_id: core.ID, - template_arg: cg.TemplateArguments, - args: list[tuple], -) -> MockObj: - var = cg.new_Pvariable(action_id, template_arg) - await cg.register_parented(var, config[CONF_ID]) - await register_peer(var, config, args) - - return var +def _peer_address(config: ConfigType, value: core.MACAddress) -> str: + return str(cg.safe_exp(_mac_bytes(value))) -@automation.register_action( +for _name, _method in ( + ("espnow.peer.add", "add_peer_from_action"), + ("espnow.peer.delete", "del_peer_from_action"), +): + automation.register_apply_action( + _name, + cv.maybe_simple_value( + PEER_SCHEMA, + key=CONF_ADDRESS, + ), + automation.ApplyField( + CONF_ADDRESS, _method, peer_address_t, const_fn=_peer_address + ), + ) + + +automation.register_apply_action( "espnow.set_channel", - SetChannelAction, cv.maybe_simple_value( { cv.GenerateID(): cv.use_id(ESPNowComponent), @@ -364,16 +353,5 @@ async def peer_action( }, key=CONF_CHANNEL, ), - synchronous=True, + automation.ApplyField(CONF_CHANNEL, "set_channel_from_action", cg.uint8), ) -async def channel_action( - config: ConfigType, - action_id: core.ID, - template_arg: cg.TemplateArguments, - args: list[tuple], -) -> MockObj: - var = cg.new_Pvariable(action_id, template_arg) - await cg.register_parented(var, config[CONF_ID]) - template_ = await cg.templatable(config[CONF_CHANNEL], args, cg.uint8) - cg.add(var.set_channel(template_)) - return var diff --git a/esphome/components/espnow/automation.h b/esphome/components/espnow/automation.h index e4d01bb1a8..3c9c6e8be9 100644 --- a/esphome/components/espnow/automation.h +++ b/esphome/components/espnow/automation.h @@ -86,39 +86,6 @@ template class SendAction final : public Action, public P } flags_{0}; }; -template class AddPeerAction final : public Action, public Parented { - TEMPLATABLE_VALUE(peer_address_t, address); - - protected: - void play(const Ts &...x) override { - peer_address_t address = this->address_.value(x...); - this->parent_->add_peer(address.data()); - } -}; - -template class DeletePeerAction final : public Action, public Parented { - TEMPLATABLE_VALUE(peer_address_t, address); - - protected: - void play(const Ts &...x) override { - peer_address_t address = this->address_.value(x...); - this->parent_->del_peer(address.data()); - } -}; - -template class SetChannelAction final : public Action, public Parented { - TEMPLATABLE_VALUE(uint8_t, channel) - - protected: - void play(const Ts &...x) override { - if (this->parent_->is_wifi_enabled()) { - return; - } - this->parent_->set_wifi_channel(this->channel_.value(x...)); - this->parent_->apply_wifi_channel(); - } -}; - class OnReceiveTrigger final : public Trigger, public ESPNowReceivedPacketHandler { public: diff --git a/esphome/components/espnow/espnow_component.h b/esphome/components/espnow/espnow_component.h index af693b47cf..375bd4faef 100644 --- a/esphome/components/espnow/espnow_component.h +++ b/esphome/components/espnow/espnow_component.h @@ -116,9 +116,18 @@ class ESPNowComponent final : public Component { esp_err_t add_peer(const uint8_t *peer); // Remove a peer with the esp_now api and remove from the internal list if exists esp_err_t del_peer(const uint8_t *peer); + // Action entry points; distinct names because add_peer(peer_address_t) only fills the boot-time list + esp_err_t add_peer_from_action(const peer_address_t &address) { return this->add_peer(address.data()); } + esp_err_t del_peer_from_action(const peer_address_t &address) { return this->del_peer(address.data()); } void set_wifi_channel(uint8_t channel) { this->wifi_channel_ = channel; } void apply_wifi_channel(); + void set_channel_from_action(uint8_t channel) { + if (this->is_wifi_enabled()) + return; + this->set_wifi_channel(channel); + this->apply_wifi_channel(); + } uint8_t get_wifi_channel(); void set_auto_add_peer(bool value) { this->auto_add_peer_ = value; } diff --git a/tests/components/espnow/common.yaml b/tests/components/espnow/common.yaml index 2f82e794c4..fec0dd9f3e 100644 --- a/tests/components/espnow/common.yaml +++ b/tests/components/espnow/common.yaml @@ -38,8 +38,15 @@ espnow: data: !lambda 'return {0x01, 0x02, 0x03, 0x04, 0x05};' - espnow.peer.add: address: 11:22:33:44:55:66 + - espnow.peer.add: + address: !lambda 'return {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};' - espnow.peer.delete: address: 11:22:33:44:55:66 + - espnow.peer.delete: + address: !lambda 'return {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};' + - espnow.set_channel: 6 + - espnow.set_channel: + channel: !lambda 'return 6;' on_broadcast: - logger.log: format: "Broadcast from: %s = '%s' RSSI: %d"