From 7931a307b47a8d033837bfc7c4522f2ecdc3acdd Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Sat, 5 Oct 2024 18:53:55 +0200 Subject: [PATCH] Add command filters to the triggers --- esphome/components/espnow/__init__.py | 23 +++++++++----- esphome/components/espnow/espnow.cpp | 5 +-- esphome/components/espnow/espnow.h | 45 ++++++++++++++++++++++----- 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/esphome/components/espnow/__init__.py b/esphome/components/espnow/__init__.py index 17fc02be82..f830eae648 100644 --- a/esphome/components/espnow/__init__.py +++ b/esphome/components/espnow/__init__.py @@ -1,7 +1,7 @@ from esphome import automation import esphome.codegen as cg import esphome.config_validation as cv -from esphome.const import CONF_DATA, CONF_ID, CONF_TRIGGER_ID +from esphome.const import CONF_COMMAND, CONF_DATA, CONF_ID, CONF_TRIGGER_ID from esphome.core import CORE CODEOWNERS = ["@nielsnl68", "@jesserockz"] @@ -66,16 +66,19 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional(CONF_ON_RECEIVE): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESPNowReceiveTrigger), + cv.Optional(CONF_COMMAND): cv.Range(min=16, max=255), } ), cv.Optional(CONF_ON_SENT): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESPNowSentTrigger), + cv.Optional(CONF_COMMAND): cv.Range(min=16, max=255), } ), cv.Optional(CONF_ON_NEW_PEER): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESPNowNewPeerTrigger), + cv.Optional(CONF_COMMAND): cv.Range(min=16, max=255), } ), cv.Optional(CONF_PEERS): cv.ensure_list(cv.mac_address), @@ -101,6 +104,8 @@ async def to_code(config): for conf in config.get(CONF_ON_SENT, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + if CONF_COMMAND in conf: + cg.add(trigger.set_command(conf[CONF_COMMAND])) await automation.build_automation( trigger, [(ESPNowPacketConst, "packet"), (bool, "status")], @@ -109,12 +114,16 @@ async def to_code(config): for conf in config.get(CONF_ON_RECEIVE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + if CONF_COMMAND in conf: + cg.add(trigger.set_command(conf[CONF_COMMAND])) await automation.build_automation( trigger, [(ESPNowPacketConst, "packet")], conf ) for conf in config.get(CONF_ON_NEW_PEER, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + if CONF_COMMAND in conf: + cg.add(trigger.set_command(conf[CONF_COMMAND])) await automation.build_automation( trigger, [(ESPNowPacketConst, "packet")], conf ) @@ -144,6 +153,7 @@ async def register_protocol(var, config): cv.GenerateID(): cv.use_id(ESPNowComponent), cv.Optional(CONF_PEER): cv.templatable(cv.mac_address), cv.Required(CONF_DATA): cv.templatable(validate_raw_data), + cv.Optional(CONF_COMMAND): cv.templatable(cv.Range(min=16, max=255)), }, key=CONF_DATA, ), @@ -155,6 +165,10 @@ async def send_action(config, action_id, template_arg, args): template_ = await cg.templatable(config[CONF_PEER].as_hex, args, cg.uint64) cg.add(var.set_mac(template_)) + if CONF_COMMAND in config: + template_ = await cg.templatable(config[CONF_COMMAND], args, cg.uint8) + cg.add(var.set_command(template_)) + data = config.get(CONF_DATA, []) if isinstance(data, bytes): data = list(data) @@ -178,13 +192,6 @@ async def send_action(config, action_id, template_arg, args): key=CONF_PEER, ), ) -async def new_peer_action(config, action_id, template_arg, args): - var = cg.new_Pvariable(action_id, template_arg) - template_ = await cg.templatable(config[CONF_PEER].as_hex, args, cg.uint64) - cg.add(var.set_mac(template_)) - return var - - @automation.register_action( "espnow.peer.del", DelPeerAction, diff --git a/esphome/components/espnow/espnow.cpp b/esphome/components/espnow/espnow.cpp index 7dc3ed63a5..55a7058784 100644 --- a/esphome/components/espnow/espnow.cpp +++ b/esphome/components/espnow/espnow.cpp @@ -344,9 +344,10 @@ void ESPNowComponent::on_data_sent(const uint8_t *mac_addr, esp_now_send_status_ /* ESPNowProtocol ********************************************************************** */ -bool ESPNowProtocol::send(uint64_t peer, const uint8_t *data, uint8_t len) { +bool ESPNowProtocol::send(uint64_t peer, const uint8_t *data, uint8_t len, uint8_t command = 0) { ESPNowPacket packet(peer, data, len, this->get_protocol_component_id()); // NOLINT - packet.set_sequents(this->get_next_sequents()); + packet.set_sequents(this->get_next_sequents(packet.peer, packet.protocol())); + packet.set_command(command); return this->parent_->send(packet); } diff --git a/esphome/components/espnow/espnow.h b/esphome/components/espnow/espnow.h index 5d79de1e5f..3c219165b8 100644 --- a/esphome/components/espnow/espnow.h +++ b/esphome/components/espnow/espnow.h @@ -23,7 +23,7 @@ static const uint64_t ESPNOW_BROADCAST_ADDR = 0xFFFFFFFFFFFF; static const uint8_t MAX_ESPNOW_DATA_SIZE = 241; -static const uint8_t TRANSPORT_HEADER[] = {'N', '0', 'w'}; +static const uint8_t TRANSPORT_HEADER[3] = {'N', '0', 'w'}; static const uint32_t ESPNOW_MAIN_PROTOCOL_ID = 0x447453; // = StD static const uint8_t ESPNOW_COMMAND_ACK = 0x06; @@ -129,7 +129,7 @@ class ESPNowProtocol : public Parented { virtual void on_new_peer(const ESPNowPacket &packet){}; virtual uint32_t get_protocol_component_id() = 0; - uint8_t get_next_sequents() { + uint8_t get_next_sequents(uint64_t peer = 0, uint32_t protocol = 0) { if (this->next_sequents_ == 255) { this->next_sequents_ = 0; } else { @@ -145,7 +145,7 @@ class ESPNowProtocol : public Parented { return valid; } - bool send(uint64_t peer, const uint8_t *data, uint8_t len); + bool send(uint64_t peer, const uint8_t *data, uint8_t len, uint8_t command = 0); protected: uint8_t next_sequents_{255}; @@ -260,6 +260,8 @@ class ESPNowComponent : public Component { template class SendAction : public Action, public Parented { public: template void set_mac(V mac) { this->mac_ = mac; } + template void set_command(V command) { this->command_ = command; } + void set_data_template(std::function func) { this->data_func_ = func; this->static_ = false; @@ -271,6 +273,10 @@ template class SendAction : public Action, public Parente void play(Ts... x) override { uint64_t mac = this->mac_.value(x...); + uint8_t command = 0; + if (this->command_.has_value()) { + command = this->mac_.value(x...); + } if (this->static_) { this->parent_->get_default_protocol()->send(mac, this->data_static_.data(), this->data_static_.size()); @@ -281,6 +287,7 @@ template class SendAction : public Action, public Parente } protected: + TemplatableValue command_{}; TemplatableValue mac_{}; bool static_{false}; std::function data_func_{}; @@ -314,24 +321,46 @@ template class DelPeerAction : public Action, public Pare class ESPNowSentTrigger : public Trigger { public: explicit ESPNowSentTrigger(ESPNowComponent *parent) { - parent->get_default_protocol()->add_on_sent_callback( - [this](const ESPNowPacket packet, bool status) { this->trigger(packet, status); }); + parent->get_default_protocol()->add_on_sent_callback([this](const ESPNowPacket packet, bool status) { + if ((this->command_ == 0) || this->command_ == packet.get_command()) { + this->trigger(packet, status); + } + }); } + void set_command(uint8_t command) { this->command_ = command; } + + protected: + uint8_t command_{0}; }; class ESPNowReceiveTrigger : public Trigger { public: explicit ESPNowReceiveTrigger(ESPNowComponent *parent) { - parent->get_default_protocol()->add_on_receive_callback( - [this](const ESPNowPacket packet) { this->trigger(packet); }); + parent->get_default_protocol()->add_on_receive_callback([this](const ESPNowPacket packet) { + if ((this->command_ == 0) || this->command_ == packet.get_command()) { + this->trigger(packet); + } + }); } + void set_command(uint8_t command) { this->command_ = command; } + + protected: + uint8_t command_{0}; }; class ESPNowNewPeerTrigger : public Trigger { public: explicit ESPNowNewPeerTrigger(ESPNowComponent *parent) { - parent->get_default_protocol()->add_on_peer_callback([this](const ESPNowPacket packet) { this->trigger(packet); }); + parent->get_default_protocol()->add_on_peer_callback([this](const ESPNowPacket packet) { + if ((this->command_ == 0) || this->command_ == packet.get_command()) { + this->trigger(packet); + } + }); } + void set_command(uint8_t command) { this->command_ = command; } + + protected: + uint8_t command_{0}; }; } // namespace espnow