diff --git a/esphome/components/espnow/__init__.py b/esphome/components/espnow/__init__.py index b6c1a80d84..17fc02be82 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_MAC_ADDRESS, CONF_TRIGGER_ID +from esphome.const import CONF_DATA, CONF_ID, CONF_TRIGGER_ID from esphome.core import CORE CODEOWNERS = ["@nielsnl68", "@jesserockz"] @@ -30,14 +30,17 @@ SendAction = espnow_ns.class_("SendAction", automation.Action) NewPeerAction = espnow_ns.class_("NewPeerAction", automation.Action) DelPeerAction = espnow_ns.class_("DelPeerAction", automation.Action) +CONF_AUTO_ADD_PEER = "auto_add_peer" +CONF_CONVORMATION_TIMEOUT = "conformation_timeout" CONF_ESPNOW = "espnow" +CONF_RETRIES = "retries" CONF_ON_RECEIVE = "on_receive" CONF_ON_SENT = "on_sent" CONF_ON_NEW_PEER = "on_new_peer" -CONF_WIFI_CHANNEL = "wifi_channel" +CONF_PEER = "peer" CONF_PEERS = "peers" -CONF_AUTO_ADD_PEER = "auto_add_peer" CONF_USE_SENT_CHECK = "use_sent_check" +CONF_WIFI_CHANNEL = "wifi_channel" def validate_raw_data(value): @@ -56,6 +59,10 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional(CONF_WIFI_CHANNEL, default=0): cv.int_range(0, 14), cv.Optional(CONF_AUTO_ADD_PEER, default=False): cv.boolean, cv.Optional(CONF_USE_SENT_CHECK, default=True): cv.boolean, + cv.Optional( + CONF_CONVORMATION_TIMEOUT, default="5000ms" + ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_RETRIES, default=5): cv.int_range(min=1, max=10), cv.Optional(CONF_ON_RECEIVE): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESPNowReceiveTrigger), @@ -89,6 +96,8 @@ async def to_code(config): cg.add(var.set_wifi_channel(config[CONF_WIFI_CHANNEL])) cg.add(var.set_auto_add_peer(config[CONF_AUTO_ADD_PEER])) cg.add(var.set_use_sent_check(config[CONF_USE_SENT_CHECK])) + cg.add(var.set_convermation_timeout(config[CONF_CONVORMATION_TIMEOUT])) + cg.add(var.set_retries(config[CONF_RETRIES])) for conf in config.get(CONF_ON_SENT, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) @@ -133,7 +142,7 @@ async def register_protocol(var, config): cv.maybe_simple_value( { cv.GenerateID(): cv.use_id(ESPNowComponent), - cv.Optional(CONF_MAC_ADDRESS): cv.templatable(cv.mac_address), + cv.Optional(CONF_PEER): cv.templatable(cv.mac_address), cv.Required(CONF_DATA): cv.templatable(validate_raw_data), }, key=CONF_DATA, @@ -142,10 +151,8 @@ async def register_protocol(var, config): async def send_action(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) - if CONF_MAC_ADDRESS in config: - template_ = await cg.templatable( - config[CONF_MAC_ADDRESS].as_hex, args, cg.uint64 - ) + if CONF_PEER in config: + template_ = await cg.templatable(config[CONF_PEER].as_hex, args, cg.uint64) cg.add(var.set_mac(template_)) data = config.get(CONF_DATA, []) @@ -166,14 +173,14 @@ async def send_action(config, action_id, template_arg, args): cv.maybe_simple_value( { cv.GenerateID(): cv.use_id(ESPNowComponent), - cv.Required(CONF_MAC_ADDRESS): cv.templatable(cv.mac_address), + cv.Required(CONF_PEER): cv.templatable(cv.mac_address), }, - key=CONF_MAC_ADDRESS, + 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_MAC_ADDRESS].as_hex, args, cg.uint64) + template_ = await cg.templatable(config[CONF_PEER].as_hex, args, cg.uint64) cg.add(var.set_mac(template_)) return var @@ -184,13 +191,13 @@ async def new_peer_action(config, action_id, template_arg, args): cv.maybe_simple_value( { cv.GenerateID(): cv.use_id(ESPNowComponent), - cv.Required(CONF_MAC_ADDRESS): cv.templatable(cv.mac_address), + cv.Required(CONF_PEER): cv.templatable(cv.mac_address), }, - key=CONF_MAC_ADDRESS, + key=CONF_PEER, ), ) async def del_peer_action(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) - template_ = await cg.templatable(config[CONF_MAC_ADDRESS].as_hex, args, cg.uint64) + template_ = await cg.templatable(config[CONF_PEER].as_hex, args, cg.uint64) cg.add(var.set_mac(template_)) return var diff --git a/esphome/components/espnow/espnow.cpp b/esphome/components/espnow/espnow.cpp index f48d96fb25..7dc3ed63a5 100644 --- a/esphome/components/espnow/espnow.cpp +++ b/esphome/components/espnow/espnow.cpp @@ -41,15 +41,21 @@ ESPNowComponent::ESPNowComponent() { ESPNowComponent::static_ = this; } // NOLI void ESPNowComponent::dump_config() { ESP_LOGCONFIG(TAG, "esp_now:"); - ESP_LOGCONFIG(TAG, " MAC Address: 0x%12llx.", this->own_peer_address_); + + ESP_LOGCONFIG(TAG, " Own Peer Address: 0x%12llx.", this->own_peer_address_); + ESP_LOGCONFIG(TAG, " Wifi channel: %d.", this->wifi_channel_); + ESP_LOGCONFIG(TAG, " Auto add new peers: %s.", this->auto_add_peer_ ? "Yes" : "No"); + + ESP_LOGCONFIG(TAG, " Use sent status: %s.", this->use_sent_check_ ? "Yes" : "No"); + ESP_LOGCONFIG(TAG, " Conversation timeout: %dms.", this->conformation_timeout_); + ESP_LOGCONFIG(TAG, " Send retries: %d.", this->retries_); } void ESPNowComponent::show_packet(const std::string &title, const ESPNowPacket &packet) { - ESP_LOGV(TAG, - "%s packet. Peer: 0x%12llx Header: %c%c%c Protocol: 0x%02x%02x%02x%02x Sequents: %02x Size: %2d Valid: %s", - title.c_str(), packet.peer, 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.content_size(), packet.is_valid() ? "Yes" : "No"); + ESP_LOGV(TAG, "%s packet. Peer: 0x%12llx, Header: %c%c%c, Protocol:%c%c%c-%02x, Sequents: %d.%d, Size: %d, Valid: %s", + title.c_str(), packet.peer, packet.get_byte_at(0), packet.get_byte_at(1), packet.get_byte_at(2), + packet.get_byte_at(3), packet.get_byte_at(4), packet.get_byte_at(5), packet.get_byte_at(6), + packet.get_byte_at(7), packet.attempts, packet.content_size(), packet.is_valid() ? "Yes" : "No"); } bool ESPNowComponent::validate_channel_(uint8_t channel) { @@ -64,8 +70,6 @@ bool ESPNowComponent::validate_channel_(uint8_t channel) { } void ESPNowComponent::setup() { - ESP_LOGI(TAG, "Setting up ESP-NOW..."); - #ifndef USE_WIFI esp_event_loop_create_default(); @@ -103,6 +107,8 @@ void ESPNowComponent::setup() { return; } if (this->use_sent_check_) { + ESP_LOGI(TAG, "send check enabled"); + err = esp_now_register_send_cb(ESPNowComponent::on_data_sent); if (err != ESP_OK) { ESP_LOGE(TAG, "esp_now_register_send_cb failed: %s", esp_err_to_name(err)); @@ -114,7 +120,7 @@ void ESPNowComponent::setup() { esp_wifi_get_mac(WIFI_IF_STA, (uint8_t *) &this->own_peer_address_); for (auto &address : this->peers_) { - ESP_LOGI(TAG, "Add peer 0x%12llx.", address); + ESP_LOGV(TAG, "Add peer '%012llx'.", address); add_peer(address); } @@ -135,7 +141,7 @@ void ESPNowComponent::setup() { void ESPNowComponent::loop() { if (!this->task_running_) { - xTaskCreate(application_task, "espnow_task", 8192, this, 2, &this->espnow_task_handle_); + xTaskCreate(application_task, "espnow_task", 4096, this, tskIDLE_PRIORITY + 1, nullptr); this->task_running_ = true; } } @@ -167,36 +173,35 @@ esp_err_t ESPNowComponent::del_peer(uint64_t addr) { ESPNowDefaultProtocol *ESPNowComponent::get_default_protocol() { if (this->protocols_[ESPNOW_MAIN_PROTOCOL_ID] == nullptr) { - this->default_protocol_ = new ESPNowDefaultProtocol(); // NOLINT - this->register_protocol(this->default_protocol_); + this->register_protocol(new ESPNowDefaultProtocol()); } return (ESPNowDefaultProtocol *) this->protocols_[ESPNOW_MAIN_PROTOCOL_ID]; } ESPNowProtocol *ESPNowComponent::get_protocol_component_(uint32_t protocol) { if (this->protocols_[protocol] == nullptr) { - ESP_LOGE(TAG, "Protocol for '0x%06" PRIx32 "' is not registered", protocol); + ESP_LOGE(TAG, "Protocol for '%06x' is not registered", protocol); return nullptr; } return this->protocols_[protocol]; } -void ESPNowComponent::call_on_receive_(ESPNowPacket packet) { - ESPNowProtocol *protocol = this->get_protocol_component_(packet.protocol()); +void ESPNowComponent::call_on_receive_(ESPNowPacket &packet) { + ESPNowProtocol *protocol = this->get_protocol_component_(packet.get_protocol()); if (protocol != nullptr) { this->defer([protocol, packet]() { protocol->on_receive(packet); }); } } -void ESPNowComponent::call_on_sent_(ESPNowPacket packet, bool status) { - ESPNowProtocol *protocol = this->get_protocol_component_(packet.protocol()); +void ESPNowComponent::call_on_sent_(ESPNowPacket &packet, bool status) { + ESPNowProtocol *protocol = this->get_protocol_component_(packet.get_protocol()); if (protocol != nullptr) { this->defer([protocol, packet, status]() { protocol->on_sent(packet, status); }); } } -void ESPNowComponent::call_on_new_peer_(ESPNowPacket packet) { - ESPNowProtocol *protocol = this->get_protocol_component_(packet.protocol()); +void ESPNowComponent::call_on_new_peer_(ESPNowPacket &packet) { + ESPNowProtocol *protocol = this->get_protocol_component_(packet.get_protocol()); if (protocol != nullptr) { this->defer([protocol, packet]() { protocol->on_new_peer(packet); }); } @@ -225,7 +230,7 @@ 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((uint64_t) *addr, data, (uint8_t) size); // NOLINT + ESPNowPacket packet(addr, data, (uint8_t) size); // NOLINT packet.is_broadcast = broadcast; if (rx_ctrl != nullptr) { packet.rssi = rx_ctrl->rssi; @@ -243,9 +248,8 @@ void ESPNowComponent::on_data_received(const uint8_t *addr, const uint8_t *data, } bool ESPNowComponent::send(ESPNowPacket packet) { - uint8_t *mac = packet.peer_as_bytes(); + uint8_t *mac = packet.get_peer(); - this->show_packet("Prepare to send", packet); if (this->is_failed()) { ESP_LOGE(TAG, "Cannot send espnow packet, espnow failed to setup"); } else if (this->send_queue_full()) { @@ -253,15 +257,15 @@ bool ESPNowComponent::send(ESPNowPacket packet) { } else if (!esp_now_is_peer_exist(mac)) { ESP_LOGE(TAG, "Peer not registered: 0x%12llx.", packet.peer); } else if (!packet.is_valid()) { - ESP_LOGE(TAG, "This Packet is invalid: 0x%012llx (%d.%d)", packet.peer, packet.sequents(), packet.attempts); + ESP_LOGE(TAG, "This Packet is invalid: '%012llx' (%d.%d)", packet.peer, packet.get_sequents(), packet.attempts); } else if (this->use_sent_check_) { - ESP_LOGV(TAG, "Placing 0x%012llx (%d.%d) into send buffer. Used: %d of %d", packet.peer, packet.sequents(), + ESP_LOGV(TAG, "Placing '%012llx' (%d.%d) into send buffer. Used: %d of %d", packet.peer, packet.get_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_LOGD(TAG, "Sended 0x%012llx (%d.%d) directly%s.", packet.peer, packet.sequents(), packet.attempts, + esp_err_t err = esp_now_send((uint8_t *) &mac, packet.get_content(), packet.content_size()); + ESP_LOGV(TAG, "Sended '%012llx' (%d.%d) directly%s.", packet.peer, packet.get_sequents(), packet.attempts, (err == ESP_OK) ? "" : " FAILED"); this->call_on_sent_(packet, err == ESP_OK); @@ -275,43 +279,40 @@ void ESPNowComponent::runner() { ESPNowPacket packet; // NOLINT for (;;) { if (xQueueReceive(this->receive_queue_, (void *) &packet, (TickType_t) 1) == pdTRUE) { - uint8_t *mac = packet.peer_as_bytes(); - ESP_LOGD(TAG, "Handling received packet from 0x%012llx (%d.%d).", packet.peer, packet.sequents(), - packet.attempts); - + uint8_t *mac = packet.get_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 { + if (this->auto_add_peer_) { + this->add_peer(packet.peer); + } this->call_on_new_peer_(packet); } } if (xQueueReceive(this->send_queue_, (void *) &packet, (TickType_t) 1) == pdTRUE) { - if (packet.attempts > MAX_NUMBER_OF_RETRYS) { - ESP_LOGE(TAG, "Dropped 0x%012llx (%d.%d). To many send retries.", packet.peer, packet.sequents(), + if (packet.attempts > this->retries_) { + ESP_LOGE(TAG, "Dropped '%012llx' (%d.%d). To many retries.", packet.peer, packet.get_sequents(), packet.attempts); this->unlock(); continue; } else if (this->is_locked()) { - if (millis() - packet.timestamp > this->conformation_timeout_) { - ESP_LOGW(TAG, "TimeOut 0x%012llx (%d.%d).", packet.peer, packet.sequents(), packet.attempts); + if (packet.timestamp + this->conformation_timeout_ < millis()) { + ESP_LOGW(TAG, "TimeOut '%012llx' (%d.%d).", packet.peer, packet.get_sequents(), packet.attempts); this->unlock(); } } else { this->lock(); packet.retry(); packet.timestamp = millis(); - uint8_t *mac = packet.peer_as_bytes(); + uint8_t *mac = packet.get_peer(); - esp_err_t err = esp_now_send(mac, packet.content_as_bytes(), packet.content_size()); + esp_err_t err = esp_now_send(mac, packet.get_content(), packet.content_size()); if (err == ESP_OK) { - ESP_LOGD(TAG, "Sended 0x%012llx (%d.%d) from buffer. Wait for conformation.", packet.peer, packet.sequents(), - packet.attempts); + ESP_LOGD(TAG, "Sended '%012llx' (%d.%d) from buffer. Wait for conformation.", packet.peer, + packet.get_sequents(), packet.attempts); } else { - ESP_LOGE(TAG, "Sending 0x%012llx (%d.%d) FAILED. B: %d.", packet.peer, packet.sequents(), packet.attempts, + ESP_LOGE(TAG, "Sending '%012llx' (%d.%d) FAILED. B: %d.", packet.peer, packet.get_sequents(), packet.attempts, this->send_queue_used()); this->unlock(); } @@ -322,23 +323,19 @@ void ESPNowComponent::runner() { } void ESPNowComponent::on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) { - if ((ESPNowComponent::static_ == nullptr) || !ESPNowComponent::static_->use_sent_check_) { - return; - } ESPNowPacket packet; // NOLINT - uint64_t mac64 = 0; - - memcpy((void *) &mac64, (void *) mac_addr, 6); + uint64_t mac64; + memcpy((void *) &mac64, mac_addr, 6); if (xQueuePeek(ESPNowComponent::static_->send_queue_, (void *) &packet, 10 / portTICK_PERIOD_MS) == pdTRUE) { - if (packet.peer != mac64) { - ESP_LOGE(TAG, " Invalid mac address. Expected: 0x%012llx (%d.%d) got: 0x%012llx", packet.peer, packet.sequents(), - packet.attempts, mac64); + if (!packet.is_peer(mac_addr)) { + ESP_LOGE(TAG, " Invalid mac address. Expected: '%012llx' (%d.%d) got: '%012llx'", packet.peer, + packet.get_sequents(), packet.attempts, mac64); return; - } else if (status == ESP_OK) { - ESP_LOGV(TAG, "Confirm packet sent 0x%012llx (%d.%d)", packet.peer, packet.sequents(), packet.attempts); - xQueueReceive(ESPNowComponent::static_->send_queue_, (void *) &packet, 10 / portTICK_PERIOD_MS); + } else if (status != ESP_OK) { + ESP_LOGE(TAG, "Sent packet failed for '%012llx' (%d.%d)", packet.peer, packet.get_sequents(), packet.attempts); } else { - ESP_LOGE(TAG, "Sent packet failed for 0x%012llx (%d.%d)", packet.peer, packet.sequents(), packet.attempts); + ESP_LOGV(TAG, "Confirm packet sent '%012llx' (%d.%d)", packet.peer, packet.get_sequents(), packet.attempts); + xQueueReceive(ESPNowComponent::static_->send_queue_, (void *) &packet, 10 / portTICK_PERIOD_MS); } ESPNowComponent::static_->call_on_sent_(packet, status == ESP_OK); ESPNowComponent::static_->unlock(); @@ -349,10 +346,7 @@ void ESPNowComponent::on_data_sent(const uint8_t *mac_addr, esp_now_send_status_ 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_LOGV(TAG, "Created packet to Send for 0x%12llx (%d.%d) directly.", packet.peer, packet.sequents(), - packet.attempts); - + packet.set_sequents(this->get_next_sequents()); return this->parent_->send(packet); } diff --git a/esphome/components/espnow/espnow.h b/esphome/components/espnow/espnow.h index 1cd77f3fd2..5d79de1e5f 100644 --- a/esphome/components/espnow/espnow.h +++ b/esphome/components/espnow/espnow.h @@ -6,7 +6,7 @@ #include "esphome/core/component.h" #include "esphome/core/helpers.h" #include "esphome/core/bytebuffer.h" - +#include "esphome/core/log.h" #include #include @@ -21,22 +21,19 @@ namespace espnow { static const uint64_t ESPNOW_BROADCAST_ADDR = 0xFFFFFFFFFFFF; -static const uint8_t ESPNOW_DATA_HEADER = 0x00; -static const uint8_t ESPNOW_DATA_PROTOCOL = 0x03; -static const uint8_t ESPNOW_DATA_PACKET = 0x07; -static const uint8_t ESPNOW_DATA_CONTENT = 0x08; - static const uint8_t MAX_ESPNOW_DATA_SIZE = 241; -static const uint8_t MAX_NUMBER_OF_RETRYS = 5; +static const uint8_t TRANSPORT_HEADER[] = {'N', '0', 'w'}; +static const uint32_t ESPNOW_MAIN_PROTOCOL_ID = 0x447453; // = StD -static const uint32_t TRANSPORT_HEADER = 0xC19983; -static const uint32_t ESPNOW_MAIN_PROTOCOL_ID = 0x11CFAF; +static const uint8_t ESPNOW_COMMAND_ACK = 0x06; +static const uint8_t ESPNOW_COMMAND_NAK = 0x15; +static const uint8_t ESPNOW_COMMAND_RESEND = 0x05; struct ESPNowPacket { uint64_t peer{0}; uint8_t rssi{0}; - uint8_t attempts{0}; + int8_t attempts{0}; bool is_broadcast{false}; uint32_t timestamp{0}; uint8_t size{0}; @@ -51,46 +48,58 @@ struct ESPNowPacket { inline ESPNowPacket() ESPHOME_ALWAYS_INLINE {} // Create packet to be send. - inline ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size, uint32_t protocol) ESPHOME_ALWAYS_INLINE { + inline ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size, uint32_t protocol, + uint8_t command = 0) ESPHOME_ALWAYS_INLINE { assert(size <= MAX_ESPNOW_DATA_SIZE); + if (peer == 0) { + peer = ESPNOW_BROADCAST_ADDR; + } - this->set_peer(peer); + this->peer = peer; - this->is_broadcast = - (std::memcmp((const void *) this->peer_as_bytes(), (const void *) &ESPNOW_BROADCAST_ADDR, 6) == 0); - this->protocol(protocol); + this->set_protocol(protocol); + if (command != 0) { + this->set_command(command); + } this->size = size; - std::memcpy(this->payload_as_bytes(), data, size); + std::memcpy(this->get_payload(), data, size); } // Load received packet's. - ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size) ESPHOME_ALWAYS_INLINE { + ESPNowPacket(const uint8_t *peer, const uint8_t *data, uint8_t size) ESPHOME_ALWAYS_INLINE { this->set_peer(peer); - std::memcpy(this->content_as_bytes(), data, size); + std::memcpy(this->get_content(), data, size); this->size = size - this->prefix_size(); } - 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 { - this->peer = peer; + inline uint8_t *get_peer() const { return (uint8_t *) &(this->peer); } + inline void set_peer(const uint8_t *peer) ESPHOME_ALWAYS_INLINE { + if (*peer == 0) { + peer = (uint8_t *) &ESPNOW_BROADCAST_ADDR; } + memcpy((void *) this->get_peer(), (const void *) peer, 6); }; + inline bool is_peer(const uint8_t *peer) const { return memcmp(peer, this->get_peer(), 6) == 0; } - uint8_t prefix_size() const { return sizeof((*this).content.prefix); } + uint8_t prefix_size() const { return sizeof(this->content.prefix); } - uint8_t content_size() const { return ((*this).prefix_size() + (*this).size); } + uint8_t content_size() const { return (this->prefix_size() + this->size); } - inline uint32_t protocol() const { return this->content.prefix.protocol; } - inline void protocol(uint32_t protocol) ESPHOME_ALWAYS_INLINE { this->content.prefix.protocol = protocol; } + inline uint32_t get_protocol() const { return this->content.prefix.protocol & 0x00FFFFFF; } + inline void set_protocol(uint32_t protocol) { + this->content.prefix.protocol = (this->content.prefix.protocol & 0xFF000000) + (protocol & 0x00FFFFFF); + } - uint8_t sequents() const { return (*this).content.prefix.sequents; } - inline void sequents(uint8_t sequents) ESPHOME_ALWAYS_INLINE { this->content.prefix.sequents = sequents; } + inline uint8_t get_command() const { return this->content.prefix.protocol >> 24; } + inline void set_command(uint32_t command) ESPHOME_ALWAYS_INLINE { + this->content.prefix.protocol = (this->content.prefix.protocol & 0x00FFFFFF) + (command << 24); + } - 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 { + uint8_t get_sequents() const { return this->content.prefix.sequents; } + inline void set_sequents(uint8_t sequents) ESPHOME_ALWAYS_INLINE { this->content.prefix.sequents = sequents; } + + inline uint8_t *get_content() const { return (uint8_t *) &(this->content); } + inline uint8_t *get_payload() const { return (uint8_t *) &(this->content.payload); } + inline uint8_t get_byte_at(uint8_t pos) const { assert(pos < this->size); return *(((uint8_t *) &this->content) + pos); } @@ -98,9 +107,14 @@ struct ESPNowPacket { inline void retry() ESPHOME_ALWAYS_INLINE { attempts++; } inline bool is_valid() const { - // bool valid = (memcmp((const void *) this->content_as_bytes(), (const void *) &TRANSPORT_HEADER, 3) == 0); - // valid &= (this->protocol() != 0); - return true; // valid; + bool valid = (memcmp((const void *) this->get_content(), (const void *) &TRANSPORT_HEADER, 3) == 0); + valid &= (this->get_protocol() != 0); + return valid; + } + + protected: + static uint32_t protocol_(uint8_t *protocol) { + return (*(protocol + 2) << 0) + (*(protocol + 1) << 8) + (*(protocol + 0) << 16); } }; @@ -181,6 +195,11 @@ class ESPNowComponent : public Component { void set_wifi_channel(uint8_t channel) { this->wifi_channel_ = channel; } void set_auto_add_peer(bool value) { this->auto_add_peer_ = value; } void set_use_sent_check(bool value) { this->use_sent_check_ = value; } + void set_convermation_timeout(uint32_t timeout) { + this->conformation_timeout_ = timeout; + ESP_LOGD("ESPNOW", "%d", timeout); + } + void set_retries(uint8_t value) { this->retries_ = value; } void setup() override; void loop() override; @@ -214,29 +233,27 @@ class ESPNowComponent : public Component { bool validate_channel_(uint8_t channel); ESPNowProtocol *get_protocol_component_(uint32_t protocol); + uint64_t own_peer_address_{0}; uint8_t wifi_channel_{0}; + uint32_t conformation_timeout_{5000}; + uint8_t retries_{5}; + bool auto_add_peer_{false}; bool use_sent_check_{true}; + bool lock_{false}; - void call_on_receive_(ESPNowPacket packet); - void call_on_sent_(ESPNowPacket packet, bool status); - void call_on_new_peer_(ESPNowPacket packet); + void call_on_receive_(ESPNowPacket &packet); + void call_on_sent_(ESPNowPacket &packet, bool status); + void call_on_new_peer_(ESPNowPacket &packet); QueueHandle_t receive_queue_{}; QueueHandle_t send_queue_{}; std::map protocols_{}; std::vector peers_{}; - uint64_t own_peer_address_{0}; - ESPNowDefaultProtocol *default_protocol_{nullptr}; - - TaskHandle_t espnow_task_handle_{nullptr}; bool task_running_{false}; - - uint32_t conformation_timeout_{5000}; - static ESPNowComponent *static_; // NOLINT }; diff --git a/esphome/components/espnow/test.yaml b/esphome/components/espnow/test.yaml index 0dc5889fa4..57b129cbaf 100644 --- a/esphome/components/espnow/test.yaml +++ b/esphome/components/espnow/test.yaml @@ -38,9 +38,8 @@ espnow: on_receive: - logger.log: format: "Received: %s RSSI: %d" - args: [packet.payload_as_bytes(), packet.rssi] - + args: [packet.get_payload(), packet.rssi] interval: - - interval: 1min + - interval: 10sec then: - espnow.send: "hallo everyone"