From c35d7c0968c9462a59b18b9b346daafbcdc838b5 Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Sun, 29 Sep 2024 19:03:21 +0200 Subject: [PATCH] rework the component again. --- esphome/components/espnow/__init__.py | 12 +- esphome/components/espnow/espnow.cpp | 202 +++++++++++--------------- esphome/components/espnow/espnow.h | 138 +++++++++++------- esphome/components/espnow/test.yaml | 54 +++++++ tests/components/espnow/common.yaml | 2 +- 5 files changed, 233 insertions(+), 175 deletions(-) create mode 100644 esphome/components/espnow/test.yaml diff --git a/esphome/components/espnow/__init__.py b/esphome/components/espnow/__init__.py index 4b99a8c7c2..b6c1a80d84 100644 --- a/esphome/components/espnow/__init__.py +++ b/esphome/components/espnow/__init__.py @@ -11,7 +11,7 @@ ESPNowComponent = espnow_ns.class_("ESPNowComponent", cg.Component) ESPNowListener = espnow_ns.class_("ESPNowListener") ESPNowPacket = espnow_ns.class_("ESPNowPacket") -ESPNowPacketPtr = ESPNowPacket.operator("ptr") +ESPNowPacketConst = ESPNowPacket.operator("const") ESPNowInterface = espnow_ns.class_( @@ -94,17 +94,21 @@ async def to_code(config): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation( trigger, - [(ESPNowPacketPtr, "packet"), (bool, "status")], + [(ESPNowPacketConst, "packet"), (bool, "status")], conf, ) for conf in config.get(CONF_ON_RECEIVE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(ESPNowPacketPtr, "packet")], conf) + 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) - await automation.build_automation(trigger, [(ESPNowPacketPtr, "packet")], conf) + await automation.build_automation( + trigger, [(ESPNowPacketConst, "packet")], conf + ) for conf in config.get(CONF_PEERS, []): cg.add(var.add_peer(conf.as_hex)) diff --git a/esphome/components/espnow/espnow.cpp b/esphome/components/espnow/espnow.cpp index b59fc70993..cfe2731fa4 100644 --- a/esphome/components/espnow/espnow.cpp +++ b/esphome/components/espnow/espnow.cpp @@ -36,37 +36,6 @@ static void application_task(void *param) { ESPNowComponent *ESPNowComponent::static_{nullptr}; // NOLINT -/* ESPNowPacket ********************************************************************** */ - -ESPNowPacket::ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size, uint32_t protocol) { - assert(size <= MAX_ESPNOW_DATA_SIZE); - - this->set_peer(peer); - - this->is_broadcast = - (std::memcmp((const void *) this->peer_as_bytes(), (const void *) &ESPNOW_BROADCAST_ADDR, 6) == 0); - this->protocol(protocol); - this->size = size; - std::memcpy(this->payload_as_bytes(), data, size); - this->calc_crc(); -} - -ESPNowPacket::ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size) { - this->set_peer(peer); - std::memcpy(this->content_as_bytes(), data, size); - this->size = size - this->prefix_size(); -} - -bool ESPNowPacket::is_valid() { - uint16_t crc = this->crc(); - this->calc_crc(); - bool valid = (memcmp((const void *) &this->content, (const void *) &TRANSPORT_HEADER, 3) == 0); - valid &= (this->protocol() != 0); - valid &= (this->crc() == crc); - this->crc(crc); - return valid; -} - /* ESPNowComponent ********************************************************************** */ ESPNowComponent::ESPNowComponent() { ESPNowComponent::static_ = this; } // NOLINT @@ -76,16 +45,16 @@ void ESPNowComponent::dump_config() { ESP_LOGCONFIG(TAG, " MAC Address: 0x%12llx.", this->own_peer_address_); } -void ESPNowComponent::show_packet(const std::string &title, ESPNowPacket *packet) { +void ESPNowComponent::show_packet(std::string title, const ESPNowPacket &packet) { /* char buf[20]; sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); ESP_LOGVV(TAG, "%s packet: M:%s H:%cx%cx%c P:%c%c%c 0x%02x S:%02x C:ox%02x~0x%02x S:%02d V:%s", "test", - buf, packet->content_at(0), packet->content_at(1), - packet->content_at(2), packet->content_at(3), packet->content_at(4), packet->content_at(5), - packet->content_at(6), packet->content_at(7), packet->crc(), packet->calc_crc(), packet->content_size() - packet->is_valid() ? "Yes" : "No"); + buf, packet.content_at(0), packet.content_at(1), + packet.content_at(2), packet.content_at(3), packet.content_at(4), packet.content_at(5), + packet.content_at(6), packet.content_at(7), packet.crc(), packet.calc_crc(), packet.content_size() + packet.is_valid() ? "Yes" : "No"); */ } @@ -167,10 +136,13 @@ void ESPNowComponent::setup() { this->mark_failed(); return; } +} - xTaskCreate(application_task, "espnow_task", 8192, this, 2, &this->espnow_task_handle_); - - ESP_LOGI(TAG, "ESP-NOW setup complete"); +void ESPNowComponent::loop() { + if (!this->task_running_) { + xTaskCreate(application_task, "espnow_task", 8192, this, 2, &this->espnow_task_handle_); + this->task_running_ = true; + } } esp_err_t ESPNowComponent::add_peer(uint64_t addr) { @@ -214,24 +186,24 @@ ESPNowProtocol *ESPNowComponent::get_protocol_component_(uint32_t protocol) { return this->protocols_[protocol]; } -void ESPNowComponent::on_receive_(ESPNowPacket *packet) { - ESPNowProtocol *protocol = this->get_protocol_component_(packet->protocol()); +void ESPNowComponent::call_on_receive_(const ESPNowPacket packet) { + ESPNowProtocol *protocol = this->get_protocol_component_(packet.protocol()); if (protocol != nullptr) { - protocol->on_receive(packet); + this->defer([protocol, packet]() { protocol->on_receive(packet); }); } } -void ESPNowComponent::on_sent_(ESPNowPacket *packet, bool status) { - ESPNowProtocol *protocol = this->get_protocol_component_(packet->protocol()); +void ESPNowComponent::call_on_sent_(const ESPNowPacket packet, bool status) { + ESPNowProtocol *protocol = this->get_protocol_component_(packet.protocol()); if (protocol != nullptr) { - protocol->on_sent(packet, packet); + this->defer([protocol, packet, status]() { protocol->on_sent(packet, status); }); } } -void ESPNowComponent::on_new_peer_(ESPNowPacket *packet) { - ESPNowProtocol *protocol = this->get_protocol_component_(packet->protocol()); +void ESPNowComponent::call_on_new_peer_(const ESPNowPacket packet) { + ESPNowProtocol *protocol = this->get_protocol_component_(packet.protocol()); if (protocol != nullptr) { - protocol->on_new_peer(packet); + this->defer([protocol, packet]() { protocol->on_new_peer(packet); }); } } @@ -258,46 +230,46 @@ void ESPNowComponent::on_data_received(const uint8_t *addr, const uint8_t *data, (wifi_promiscuous_pkt_t *) (data - sizeof(wifi_pkt_rx_ctrl_t) - 39); // = sizeof (espnow_frame_format_t) rx_ctrl = &promiscuous_pkt->rx_ctrl; #endif - ESPNowPacket *packet = new ESPNowPacket((uint64_t) *addr, data, (uint8_t) size); // NOLINT - packet->is_broadcast = broadcast; + ESPNowPacket packet((uint64_t) *addr, data, (uint8_t) size); // NOLINT + packet.is_broadcast = broadcast; if (rx_ctrl != nullptr) { - packet->rssi = rx_ctrl->rssi; - packet->timestamp = rx_ctrl->timestamp; + packet.rssi = rx_ctrl->rssi; + packet.timestamp = rx_ctrl->timestamp; } else { - packet->timestamp = millis(); + packet.timestamp = millis(); } /// this->show_packet("Receive", *packet); - if (packet->is_valid()) { - xQueueSendToBack(ESPNowComponent::static_->receive_queue_, (void *) packet, 10); + if (packet.is_valid()) { + xQueueSendToBack(ESPNowComponent::static_->receive_queue_, (void *) &packet, 10); } else { ESP_LOGE(TAG, "Invalid ESP-NOW packet received (CRC)"); } } -bool ESPNowComponent::write(ESPNowPacket *packet) { - uint8_t *mac = packet->peer_as_bytes(); - // this->show_packet("Write", *packet); +bool ESPNowComponent::send(ESPNowPacket packet) { + uint8_t *mac = packet.peer_as_bytes(); + + // this->show_packet("Write", packet); if (this->is_failed()) { ESP_LOGE(TAG, "Cannot send espnow packet, espnow failed to setup"); } else if (this->send_queue_full()) { ESP_LOGE(TAG, "Send Buffer Out of Memory."); } else if (!esp_now_is_peer_exist(mac)) { - ESP_LOGW(TAG, "Peer not registered: 0x%12llx.", packet->peer); - } else if (!packet->is_valid()) { + ESP_LOGW(TAG, "Peer not registered: 0x%12llx.", packet.peer); + } else if (!packet.is_valid()) { ESP_LOGW(TAG, "Packet is invalid. maybe you need to ::calc_crc(). the packat before writing."); } else if (this->use_sent_check_) { - xQueueSendToBack(this->send_queue_, (void *) packet, 10); - ESP_LOGVV(TAG, "Send to 0x%12llx (%d.%d): Buffer Used: %d", packet->peer, packet->sequents(), packet->attempts, - this->send_queue_used()); - + ESP_LOGD(TAG, "Place 0x%12llx (%d.%d) into send buffer. Used: %d of %d", packet.peer, packet.sequents(), + packet.attempts, this->send_queue_used(), SEND_BUFFER_SIZE); + xQueueSendToBack(this->send_queue_, (void *) &packet, 10); return true; } else { - esp_err_t err = esp_now_send((uint8_t *) &mac, packet->content_as_bytes(), packet->content_size()); - ESP_LOGVV(TAG, "S: 0x%04x.%d B: %d%s.", packet->sequents(), packet->attempts, this->send_queue_used(), - (err == ESP_OK) ? "" : " FAILED"); + esp_err_t err = esp_now_send((uint8_t *) &mac, packet.content_as_bytes(), packet.content_size()); + ESP_LOGD(TAG, "Sended 0x%12llx (%d.%d) directly%s.", packet.peer, packet.sequents(), packet.attempts, + (err == ESP_OK) ? "" : " FAILED"); - this->defer([this, packet, err]() { this->on_sent_(packet, err == ESP_OK); }); + this->call_on_sent_(packet, err == ESP_OK); return true; } @@ -305,50 +277,49 @@ bool ESPNowComponent::write(ESPNowPacket *packet) { } void ESPNowComponent::runner() { - ESPNowPacket *packet{nullptr}; // NOLINT + ESPNowPacket packet; // NOLINT for (;;) { - // if (packet == nullptr) { - packet = new ESPNowPacket(); // NOLINT - // } if (xQueueReceive(this->receive_queue_, (void *) &packet, (TickType_t) 1) == pdTRUE) { - uint8_t *mac = packet->peer_as_bytes(); + uint8_t *mac = packet.peer_as_bytes(); + ESP_LOGD(TAG, "Handling received packet from 0x%12llx (%d.%d).", packet.peer, packet.sequents(), packet.attempts); - if (!esp_now_is_peer_exist(mac)) { - if (!this->auto_add_peer_) { - this->defer([this, packet]() { this->on_new_peer_(packet); }); - continue; - } else { - this->add_peer(packet->peer); - } + if (esp_now_is_peer_exist(mac)) { + this->call_on_receive_(packet); + } else if (this->auto_add_peer_) { + this->add_peer(packet.peer); + this->call_on_receive_(packet); + } else { + this->call_on_new_peer_(packet); } - this->defer([this, packet]() { this->on_receive_(packet); }); } - // if (packet == nullptr) { - packet = new ESPNowPacket(); // NOLINT - // } - if (xQueueReceive(this->send_queue_, (void *) packet, (TickType_t) 1) == pdTRUE) { - if (packet->attempts > MAX_NUMBER_OF_RETRYS) { - ESP_LOGW(TAG, "To many send retries. Packet dropped. 0x%04x", packet->sequents()); + if (xQueueReceive(this->send_queue_, (void *) &packet, (TickType_t) 1) == pdTRUE) { + ESP_LOGD(TAG, "Handling send packet for 0x%12llx (%d.%d).", packet.peer, packet.sequents(), packet.attempts); + + if (packet.attempts > MAX_NUMBER_OF_RETRYS) { + ESP_LOGE(TAG, "Dropped 0x%12llx (0x%04x.%d). To many send retries", packet.peer, packet.sequents(), + packet.attempts); this->unlock(); continue; } else if (this->is_locked()) { - if (millis() - packet->timestamp > 1000) { - ESP_LOGE(TAG, "TimeOut (0x%04x.%d).", packet->sequents(), packet->attempts); - packet->retry(); + if (millis() - packet.timestamp > 1000) { + ESP_LOGW(TAG, "TimeOut 0x%12llx (0x%04x.%d).", packet.peer, packet.sequents(), packet.attempts); + packet.retry(); this->unlock(); } } else { this->lock(); - packet->retry(); - packet->timestamp = millis(); - uint8_t *mac = packet->peer_as_bytes(); + packet.retry(); + packet.timestamp = millis(); + uint8_t *mac = packet.peer_as_bytes(); - esp_err_t err = esp_now_send(mac, packet->content_as_bytes(), packet->content_size()); + esp_err_t err = esp_now_send(mac, packet.content_as_bytes(), packet.content_size()); if (err == ESP_OK) { - ESP_LOGV(TAG, "S: 0x%04x.%d. Wait for conformation.", packet->sequents(), packet->attempts); + ESP_LOGV(TAG, "Sended 0x%12llx (%d.%d). Wait for conformation.", packet.peer, packet.sequents(), + packet.attempts); } else { - ESP_LOGE(TAG, "S: 0x%04x.%d B: %d.", packet->sequents(), packet->attempts, this->send_queue_used()); + ESP_LOGE(TAG, "Sending 0x%12llx (%d.%d) FAILED. B: %d.", packet.peer, packet.sequents(), packet.attempts, + this->send_queue_used()); this->unlock(); } } @@ -361,37 +332,34 @@ void ESPNowComponent::on_data_sent(const uint8_t *mac_addr, esp_now_send_status_ if ((ESPNowComponent::static_ == nullptr) || !ESPNowComponent::static_->use_sent_check_) { return; } - ESPNowPacket *packet = new ESPNowPacket(); // NOLINT + ESPNowPacket packet; // NOLINT uint64_t mac64 = (uint64_t) *mac_addr; - if (xQueuePeek(ESPNowComponent::static_->send_queue_, (void *) packet, 10 / portTICK_PERIOD_MS) == pdTRUE) { + if (xQueuePeek(ESPNowComponent::static_->send_queue_, (void *) &packet, 10 / portTICK_PERIOD_MS) == pdTRUE) { if (status != ESP_OK) { - ESP_LOGE(TAG, "sent packet failed (0x%04x.%d)", packet->sequents(), packet->attempts); - } else if (packet->peer != mac64) { - ESP_LOGE(TAG, " Invalid mac address. (0x%04x.%d) expected: 0x%12llx got: 0x%12llx", packet->sequents(), - packet->attempts, packet->peer, mac64); + ESP_LOGE(TAG, "sent packet failed (0x%04x.%d)", packet.sequents(), packet.attempts); + } else if (packet.peer != mac64) { + ESP_LOGE(TAG, " Invalid mac address. (0x%04x.%d) expected: 0x%12llx got: 0x%12llx", packet.sequents(), + packet.attempts, packet.peer, mac64); } else { - ESP_LOGV(TAG, "Confirm sent (0x%04x.%d)", packet->sequents(), packet->attempts); - ESPNowComponent::static_->defer([packet]() { - ESPNowComponent::static_->on_sent_(packet, true); - ESPNowPacket tmp; - xQueueReceive(ESPNowComponent::static_->send_queue_, (void *) &tmp, 10 / portTICK_PERIOD_MS); - ESPNowComponent::static_->unlock(); - }); + ESP_LOGV(TAG, "Confirm sent (0x%04x.%d)", packet.sequents(), packet.attempts); + ESPNowComponent::static_->call_on_sent_(packet, true); + xQueueReceive(ESPNowComponent::static_->send_queue_, (void *) &packet, 10 / portTICK_PERIOD_MS); return; } - ESPNowComponent::static_->defer([packet]() { - ESPNowComponent::static_->on_sent_(packet, false); - ESPNowComponent::static_->unlock(); - }); + ESPNowComponent::static_->call_on_sent_(packet, false); + ESPNowComponent::static_->unlock(); } } /* ESPNowProtocol ********************************************************************** */ -bool ESPNowProtocol::write(uint64_t peer, const uint8_t *data, uint8_t len) { - ESPNowPacket *packet = new ESPNowPacket(peer, data, len, this->get_protocol_component_id()); // NOLINT - packet->sequents(this->get_next_sequents()); - return this->parent_->write(packet); +bool ESPNowProtocol::send(uint64_t peer, const uint8_t *data, uint8_t len) { + ESPNowPacket packet(peer, data, len, this->get_protocol_component_id()); // NOLINT + packet.sequents(this->get_next_sequents()); + ESP_LOGD(TAG, "Created packet to Send for 0x%12llx (%d.%d) directly.", packet.peer, packet.sequents(), + packet.attempts); + + return this->parent_->send(packet); } } // namespace espnow diff --git a/esphome/components/espnow/espnow.h b/esphome/components/espnow/espnow.h index dac807eb0a..0af50cadea 100644 --- a/esphome/components/espnow/espnow.h +++ b/esphome/components/espnow/espnow.h @@ -7,6 +7,8 @@ #include "esphome/core/helpers.h" #include "esphome/core/bytebuffer.h" +#include "esphome/core/log.h" + #include #include @@ -51,15 +53,29 @@ struct ESPNowPacket { uint8_t payload[MAX_ESPNOW_DATA_SIZE + 1]{0}; } __attribute__((packed)) content; - ESPNowPacket() {} + inline ESPNowPacket() ESPHOME_ALWAYS_INLINE {} // Create packet to be send. - ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size, uint32_t protocol); + inline ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size, uint32_t protocol) ESPHOME_ALWAYS_INLINE { + assert(size <= MAX_ESPNOW_DATA_SIZE); + this->set_peer(peer); + + this->is_broadcast = + (std::memcmp((const void *) this->peer_as_bytes(), (const void *) &ESPNOW_BROADCAST_ADDR, 6) == 0); + this->protocol(protocol); + this->size = size; + std::memcpy(this->payload_as_bytes(), data, size); + this->calc_crc(); + } // Load received packet's. - ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size); + ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size) ESPHOME_ALWAYS_INLINE { + this->set_peer(peer); + std::memcpy(this->content_as_bytes(), data, size); + this->size = size - this->prefix_size(); + } - uint8_t *peer_as_bytes() { return (uint8_t *) &(this->peer); } - void set_peer(uint64_t peer) { + inline uint8_t *peer_as_bytes() const { return (uint8_t *) &(this->peer); } + inline void set_peer(uint64_t peer) ESPHOME_ALWAYS_INLINE { if (peer == 0) { this->peer = ESPNOW_BROADCAST_ADDR; } else { @@ -67,39 +83,48 @@ struct ESPNowPacket { } }; - inline uint8_t prefix_size() { return sizeof(this->content.prefix); } + uint8_t prefix_size() const { return sizeof((*this).content.prefix); } - inline uint8_t content_size() { return this->prefix_size() + this->size; } + uint8_t content_size() const { return ((*this).prefix_size() + (*this).size); } - inline uint32_t protocol() { return this->content.prefix.protocol; } - void protocol(uint32_t protocol) { + inline uint32_t protocol() const { return this->content.prefix.protocol; } + inline void protocol(uint32_t protocol) ESPHOME_ALWAYS_INLINE { this->content.prefix.protocol = protocol; this->calc_crc(); } - inline uint8_t sequents() { return this->content.prefix.sequents; } - void sequents(uint8_t sequents) { + uint8_t sequents() const { return (*this).content.prefix.sequents; } + inline void sequents(uint8_t sequents) ESPHOME_ALWAYS_INLINE { this->content.prefix.sequents = sequents; this->calc_crc(); } - uint8_t *content_as_bytes() { return (uint8_t *) &(this->content); } - uint8_t *payload_as_bytes() { return (uint8_t *) &(this->content.payload); } - uint8_t content_at(uint8_t pos) { + inline uint8_t *content_as_bytes() const { return (uint8_t *) &(this->content); } + inline uint8_t *payload_as_bytes() const { return (uint8_t *) &(this->content.payload); } + inline uint8_t content_at(uint8_t pos) const { assert(pos < this->size); return *(((uint8_t *) &this->content) + pos); } - uint8_t crc() { return this->content.prefix.crc; } - void crc(uint8_t crc) { this->content.prefix.crc = crc; } + inline uint8_t crc() const { return this->content.prefix.crc; } + inline void crc(uint8_t crc) { this->content.prefix.crc = crc; } + void calc_crc() { this->content.prefix.crc = 0; uint8_t crc = esp_crc8_le(0, this->peer_as_bytes(), 6); - this->content.prefix.crc = esp_crc8_le(crc, (const uint8_t *) &this->content, this->size); + this->content.prefix.crc = esp_crc8_le(crc, (const uint8_t *) this->content_as_bytes(), this->content_size()); } - void retry() { this->attempts++; } - bool is_valid(); + inline void retry() ESPHOME_ALWAYS_INLINE { attempts++; } + inline bool is_valid() { + uint16_t tmp_crc = crc(); + this->calc_crc(); + bool valid = (memcmp((const void *) this->content_as_bytes(), (const void *) &TRANSPORT_HEADER, 3) == 0); + valid &= (this->protocol() != 0); + valid &= (this->crc() == tmp_crc); + this->crc(tmp_crc); + return valid; + } }; class ESPNowComponent; @@ -108,9 +133,9 @@ class ESPNowProtocol : public Parented { public: ESPNowProtocol(){}; - virtual void on_receive(ESPNowPacket *packet){}; - virtual void on_sent(ESPNowPacket *packet, bool status){}; - virtual void on_new_peer(ESPNowPacket *packet){}; + virtual void on_receive(const ESPNowPacket &packet){}; + virtual void on_sent(const ESPNowPacket &packet, bool status){}; + virtual void on_new_peer(const ESPNowPacket &packet){}; virtual uint32_t get_protocol_component_id() = 0; uint8_t get_next_sequents() { @@ -129,10 +154,7 @@ class ESPNowProtocol : public Parented { return valid; } - bool write(uint64_t peer, const uint8_t *data, uint8_t len); - bool write(uint64_t peer, ByteBuffer &data) { - return this->write(peer, data.get_data().data(), (uint8_t) data.get_used_space()); - } + bool send(uint64_t peer, const uint8_t *data, uint8_t len); protected: uint8_t next_sequents_{255}; @@ -142,25 +164,25 @@ class ESPNowDefaultProtocol : public ESPNowProtocol { public: uint32_t get_protocol_component_id() override { return ESPNOW_MAIN_PROTOCOL_ID; }; - void add_on_receive_callback(std::function &&callback) { + void add_on_receive_callback(std::function &&callback) { this->on_receive_.add(std::move(callback)); } - void on_receive(ESPNowPacket *packet) override { this->on_receive_.call(packet); }; + void on_receive(const ESPNowPacket &packet) override { this->on_receive_.call(packet); }; - void add_on_sent_callback(std::function &&callback) { + void add_on_sent_callback(std::function &&callback) { this->on_sent_.add(std::move(callback)); } - void on_sent(ESPNowPacket *packet, bool status) override { this->on_sent_.call(packet, status); }; + void on_sent(const ESPNowPacket &packet, bool status) override { this->on_sent_.call(packet, status); }; - void add_on_peer_callback(std::function &&callback) { + void add_on_peer_callback(std::function &&callback) { this->on_new_peer_.add(std::move(callback)); } - void on_new_peer(ESPNowPacket *packet) override { this->on_new_peer_.call(packet); }; + void on_new_peer(const ESPNowPacket &packet) override { this->on_new_peer_.call(packet); }; protected: - CallbackManager on_sent_; - CallbackManager on_receive_; - CallbackManager on_new_peer_; + CallbackManager on_sent_; + CallbackManager on_receive_; + CallbackManager on_new_peer_; }; class ESPNowComponent : public Component { @@ -184,10 +206,11 @@ class ESPNowComponent : public Component { void set_use_sent_check(bool value) { this->use_sent_check_ = value; } void setup() override; + void loop() override; void runner(); - bool write(ESPNowPacket *packet); + bool send(ESPNowPacket packet); void register_protocol(ESPNowProtocol *protocol) { protocol->set_parent(this); @@ -208,7 +231,7 @@ class ESPNowComponent : public Component { ESPNowDefaultProtocol *get_default_protocol(); - void show_packet(const std::string &title, ESPNowPacket *packet); + void show_packet(std::string title, const ESPNowPacket &packet); protected: bool validate_channel_(uint8_t channel); @@ -220,9 +243,9 @@ class ESPNowComponent : public Component { bool use_sent_check_{true}; bool lock_{false}; - void on_receive_(ESPNowPacket *packet); - void on_sent_(ESPNowPacket *packet, bool status); - void on_new_peer_(ESPNowPacket *packet); + void call_on_receive_(const ESPNowPacket packet); + void call_on_sent_(const ESPNowPacket packet, bool status); + void call_on_new_peer_(const ESPNowPacket packet); QueueHandle_t receive_queue_{}; QueueHandle_t send_queue_{}; @@ -233,6 +256,7 @@ class ESPNowComponent : public Component { ESPNowDefaultProtocol *default_protocol_{nullptr}; TaskHandle_t espnow_task_handle_{nullptr}; + bool task_running_{false}; static ESPNowComponent *static_; // NOLINT }; @@ -243,21 +267,28 @@ template class SendAction : public Action, public Parente void set_data_template(std::function func) { this->data_func_ = func; this->static_ = false; + ESP_LOGCONFIG("ESPNOW:SendAction", "Add ByteBuffer lambda value to send"); } void set_data_static(const std::vector &data) { this->data_static_ = data; this->static_ = true; + ESP_LOGCONFIG("ESPNOW:SendAction", "Add static std:vector value to send"); } void play(Ts... x) override { - auto mac = this->mac_.value(x...); + ESP_LOGI("ESPNOW:SendAction", "Execute Play."); + /* + uint64_t mac = this->mac_.value(x...); - if (this->static_) { - this->parent_->get_default_protocol()->write(mac, this->data_static_.data(), this->data_static_.size()); - } else { - auto val = this->data_func_(x...); - this->parent_->get_default_protocol()->write(mac, val); - } + if (this->static_) { + ESP_LOGI("ESPNOW:SendAction", "Action Send static std:vector value now."); + // this->parent_->get_default_protocol()->send(mac, this->data_static_.data(), this->data_static_.size()); + } else { + ESP_LOGI("ESPNOW:SendAction", "Action Send ByteBuffer lambda value now"); + ByteBuffer data = this->data_func_(x...); + // this->parent_->get_default_protocol()->send(mac, data.get_data().data(), (uint8_t) data.get_used_space()); + } + */ } protected: @@ -291,25 +322,26 @@ template class DelPeerAction : public Action, public Pare TemplatableValue mac_{}; }; -class ESPNowSentTrigger : public Trigger { +class ESPNowSentTrigger : public Trigger { public: explicit ESPNowSentTrigger(ESPNowComponent *parent) { parent->get_default_protocol()->add_on_sent_callback( - [this](ESPNowPacket *packet, bool status) { this->trigger(packet, status); }); + [this](const ESPNowPacket packet, bool status) { this->trigger(packet, status); }); } }; -class ESPNowReceiveTrigger : public Trigger { +class ESPNowReceiveTrigger : public Trigger { public: explicit ESPNowReceiveTrigger(ESPNowComponent *parent) { - parent->get_default_protocol()->add_on_receive_callback([this](ESPNowPacket *packet) { this->trigger(packet); }); + parent->get_default_protocol()->add_on_receive_callback( + [this](const ESPNowPacket packet) { this->trigger(packet); }); } }; -class ESPNowNewPeerTrigger : public Trigger { +class ESPNowNewPeerTrigger : public Trigger { public: explicit ESPNowNewPeerTrigger(ESPNowComponent *parent) { - parent->get_default_protocol()->add_on_peer_callback([this](ESPNowPacket *packet) { this->trigger(packet); }); + parent->get_default_protocol()->add_on_peer_callback([this](const ESPNowPacket packet) { this->trigger(packet); }); } }; diff --git a/esphome/components/espnow/test.yaml b/esphome/components/espnow/test.yaml new file mode 100644 index 0000000000..ae05855478 --- /dev/null +++ b/esphome/components/espnow/test.yaml @@ -0,0 +1,54 @@ +# These substitutions allow the end user to override certain values +substitutions: + name: "lum-iot-test" + friendly_name: "Project Template" + +#xternal_components: +# - source: github://pr#7141 +# components: [ espnow ] +# refresh: 1 sec + +esp32: + board: esp32dev + framework: + type: esp-idf + +esphome: + name: "${name}" + # Friendly names are used where appropriate in Home Assistant + friendly_name: "${friendly_name}" + # Automatically add the mac address to the name + # so you can use a single firmware for all devices + name_add_mac_suffix: false + + # This will allow for (future) project identification, + # configuration and updates. + project: + name: esphome.project-template + version: "1.0" + +# To be able to get logs from the device via serial and api. +logger: + level: verbose + +espnow: + auto_add_peer: true + peers: + - FF:FF:FF:FF:FF:FF + on_receive: + - logger.log: + format: "Received: %s RSSI: %d" + args: [packet.payload_as_bytes(), packet.rssi] + +binary_sensor: + - platform: gpio + + pin: + number: GPIO00 + inverted: true + mode: + input: true + pullup: true + name: Button + on_click: + - espnow.send: "hallo everyone" diff --git a/tests/components/espnow/common.yaml b/tests/components/espnow/common.yaml index c640120f0c..4f121022c8 100644 --- a/tests/components/espnow/common.yaml +++ b/tests/components/espnow/common.yaml @@ -5,7 +5,7 @@ espnow: on_receive: - logger.log: format: "Received: %s RSSI: %d" - args: [packet->content_as_bytes(), packet->rssi] + args: [packet.content_as_bytes(), packet.rssi] binary_sensor: - platform: gpio