From 3bee619049cea8e97b2ce7eba4d756b8469fac17 Mon Sep 17 00:00:00 2001 From: NP v/d Spek Date: Sun, 22 Sep 2024 18:33:43 +0200 Subject: [PATCH] reworked the packet class back to a struct --- esphome/components/espnow/espnow.cpp | 240 ++++++++++++--------------- esphome/components/espnow/espnow.h | 220 ++++++++++++------------ 2 files changed, 213 insertions(+), 247 deletions(-) diff --git a/esphome/components/espnow/espnow.cpp b/esphome/components/espnow/espnow.cpp index 2ac6e51d79..473a7439e8 100644 --- a/esphome/components/espnow/espnow.cpp +++ b/esphome/components/espnow/espnow.cpp @@ -34,54 +34,33 @@ static void application_task(void *param) { application->runner(); } -#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 1) -struct { - uint16_t frame_head; - uint16_t duration; - uint8_t destination_address[6]; - uint8_t source_address[6]; - uint8_t broadcast_address[6]; - uint16_t sequence_control; - - uint8_t category_code; - uint8_t organization_identifier[3]; // 0x18fe34 - uint8_t random_values[4]; - struct { - uint8_t element_id; // 0xdd - uint8_t lenght; // - uint8_t organization_identifier[3]; // 0x18fe34 - uint8_t type; // 4 - uint8_t version; - uint8_t body[0]; - } vendor_specific_content; -} __attribute__((packed)) espnow_frame_format_t; -#endif - /* ESPNowPacket ********************************************************************** */ -ESPNowPacket::ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size, uint32_t protocol) : ESPNowPacket() { - this->peer(peer); +ESPNowPacket::ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size, uint32_t protocol) { + this->set_peer(peer); - this->broadcast(std::memcmp((const void *) this->peer_as_bytes(), (const void *) &ESPNOW_BROADCAST_ADDR, 6) == 0); - this->protocol_id(protocol); - this->content()->put_bytes(data, size); - - this->calc_crc(); + this->is_broadcast = + (std::memcmp((const void *) this->peer_as_bytes(), (const void *) &ESPNOW_BROADCAST_ADDR, 6) == 0); + this->set_protocol(protocol); + this->payload()->put_bytes(data, size); + this->update_payload_(); } -ESPNowPacket::ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size) : ESPNowPacket() { - this->peer(peer); - this->content_->set_position(0); - this->content_->put_bytes(data, size); +ESPNowPacket::ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size) { + this->set_peer(peer); + std::memcpy(&(this->content), data, this->prefix_size()); + size -= this->prefix_size(); + this->payload()->put_bytes(data + this->prefix_size(), size - 1); + this->update_payload_(); + this->content.payload[this->size] = *(data + size); } bool ESPNowPacket::is_valid() { - uint16_t crc = this->crc(); - this->calc_crc(); - bool valid = (memcmp((const void *) this->content_bytes(), (const void *) &TRANSPORT_HEADER, 3) == 0); - valid &= (this->protocol_id() != 0); - valid &= (this->crc() == crc); - this->crc(crc); + uint16_t crc = this->content.payload[this->size]; + bool valid = (memcmp((const void *) &this->content, (const void *) &TRANSPORT_HEADER, 3) == 0); + valid &= (this->get_protocol() != 0); + valid &= (this->calc_crc_() == crc); + return valid; } @@ -89,18 +68,8 @@ bool ESPNowPacket::is_valid() { bool ESPNowProtocol::write(uint64_t peer, const uint8_t *data, uint8_t len) { ESPNowPacket *packet = new ESPNowPacket(peer, data, len, this->get_protocol_id()); - return this->parent_->write(packet); -} -bool ESPNowProtocol::write(uint64_t peer, std::vector &data) { - ESPNowPacket *packet = - new ESPNowPacket(peer, (uint8_t *) data.data(), (uint8_t) data.size(), this->get_protocol_id()); - return this->parent_->write(packet); -} -bool ESPNowProtocol::write(ESPNowPacket *packet) { - packet->protocol_id(this->get_protocol_id()); - packet->packet_id(this->get_next_ref_id()); - packet->calc_crc(); - return this->parent_->write(packet); + packet->set_sequents(this->get_next_sequents()); + return this->parent_->write(std::move(packet)); } ESPNowComponent::ESPNowComponent() { global_esp_now = this; } @@ -110,14 +79,13 @@ void ESPNowComponent::dump_config() { ESP_LOGCONFIG(TAG, " MAC Address: 0x%12llx.", ESPNOW_ADDR_SELF); ESPNowPacket *packet = new ESPNowPacket(0x112233445566, (uint8_t *) TAG, 6, 0xabcdef); ESP_LOGI(TAG, "test: %s |H:%02x%02x%02x A:%02x%02x%02x %02x T:%02x C:%02x%02x S:%02d", packet->content_bytes(), - packet->content(0), packet->content(1), packet->content(2), packet->content(3), packet->content(4), - packet->content(5), packet->content(6), packet->content(7), packet->content(8), packet->content(9), - packet->size()); + 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_at(8), packet->content_at(9), packet->get_size()); - ESP_LOGI(TAG, "test: A:%06" PRIx32 " R:%02x C:%04x S:%d", packet->protocol_id(), packet->packet_id(), packet->crc(), - packet->size()); - ESP_LOGI(TAG, "test: is_valid: %s", - packet->is_valid() ? "Yes" : "No"); // ESP_LOGCONFIG(TAG, " WiFi Channel: %n", WiFi.channel()); + ESP_LOGI(TAG, "test: A:%06" PRIx32 " R:%02x C:%04x S:%d", packet->get_protocol(), packet->get_sequents(), + packet->crc(), packet->get_size()); + ESP_LOGI(TAG, "test: is_valid: %s", packet->is_valid() ? "Yes" : "No"); } bool ESPNowComponent::validate_channel_(uint8_t channel) { @@ -134,9 +102,7 @@ bool ESPNowComponent::validate_channel_(uint8_t channel) { void ESPNowComponent::setup() { ESP_LOGI(TAG, "Setting up ESP-NOW..."); -#ifdef USE_WIFI - wifi::global_wifi_component->disable(); -#else // Set device as a Wi-Fi Station +#ifndef USE_WIFI esp_event_loop_create_default(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); @@ -148,9 +114,6 @@ void ESPNowComponent::setup() { ESP_ERROR_CHECK(esp_wifi_start()); ESP_ERROR_CHECK(esp_wifi_disconnect()); -#endif - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - #ifdef CONFIG_ESPNOW_ENABLE_LONG_RANGE esp_wifi_get_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCOL_LR); #endif @@ -158,6 +121,9 @@ void ESPNowComponent::setup() { esp_wifi_set_promiscuous(true); esp_wifi_set_channel(this->wifi_channel_, WIFI_SECOND_CHAN_NONE); esp_wifi_set_promiscuous(false); +#else + // this->wifi_channel_ = wifi::global_wifi_component-> +#endif esp_err_t err = esp_now_init(); if (err != ESP_OK) { @@ -187,14 +153,14 @@ void ESPNowComponent::setup() { add_peer(address); } - this->send_queue_ = xQueueCreate(SEND_BUFFER_SIZE, sizeof(ESPNowData)); + this->send_queue_ = xQueueCreate(SEND_BUFFER_SIZE, sizeof(ESPNowPacket)); if (this->send_queue_ == nullptr) { ESP_LOGE(TAG, "Failed to create send queue"); this->mark_failed(); return; } - this->receive_queue_ = xQueueCreate(SEND_BUFFER_SIZE, sizeof(ESPNowData)); + this->receive_queue_ = xQueueCreate(SEND_BUFFER_SIZE, sizeof(ESPNowPacket)); if (this->receive_queue_ == nullptr) { ESP_LOGE(TAG, "Failed to create receive queue"); this->mark_failed(); @@ -248,23 +214,23 @@ ESPNowProtocol *ESPNowComponent::get_protocol_(uint32_t protocol) { } void ESPNowComponent::on_receive_(ESPNowPacket *packet) { - ESPNowProtocol *protocol = this->get_protocol_(packet->protocol_id()); + ESPNowProtocol *protocol = this->get_protocol_(packet->get_protocol()); if (protocol != nullptr) { - protocol->on_receive(packet); + protocol->on_receive(std::move(packet)); } } void ESPNowComponent::on_sent_(ESPNowPacket *packet, bool status) { - ESPNowProtocol *protocol = this->get_protocol_(packet->protocol_id()); + ESPNowProtocol *protocol = this->get_protocol_(packet->get_protocol()); if (protocol != nullptr) { - protocol->on_sent(packet, status); + protocol->on_sent(std::move(packet), status); } } void ESPNowComponent::on_new_peer_(ESPNowPacket *packet) { - ESPNowProtocol *protocol = this->get_protocol_(packet->protocol_id()); + ESPNowProtocol *protocol = this->get_protocol_(packet->get_protocol()); if (protocol != nullptr) { - protocol->on_new_peer(packet); + protocol->on_new_peer(std::move(packet)); } } @@ -284,143 +250,145 @@ void ESPNowComponent::on_data_received(const uint8_t *addr, const uint8_t *data, rx_ctrl = recv_info->rx_ctrl; #else wifi_promiscuous_pkt_t *promiscuous_pkt = - (wifi_promiscuous_pkt_t *) (data - sizeof(wifi_pkt_rx_ctrl_t) - sizeof(espnow_frame_format_t)); + (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, size); - packet.broadcast(broadcast); + ESPNowPacket *packet = new ESPNowPacket((uint64_t) *addr, data, (uint8_t) size); + 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(); } - ESP_LOGVV(TAG, "Read: %s |H:%02x%02x%02x A:%02x%02x%02x %02x T:%02x C:%02x%02x S:%02d", packet.content_bytes(), - packet.content(0), packet.content(1), packet.content(2), packet.content(3), packet.content(4), - packet.content(5), packet.content(6), packet.content(7), packet.content(8), packet.content(9), - packet.size()); + ESP_LOGVV(TAG, "Read: H:%02x%02x%02x P:%02x%02x%02x%02x T:%02x S:%02d", 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_at(8), + packet->content_at(9), packet->get_size()); - if (packet.is_valid()) { - xQueueSendToBack(global_esp_now->receive_queue_, packet.retrieve(), 10); + if (packet->is_valid()) { + xQueueSendToBack(global_esp_now->receive_queue_, packet, 10); } else { ESP_LOGE(TAG, "Invalid ESP-NOW packet received (CRC)"); } } bool ESPNowComponent::write(ESPNowPacket *packet) { - ESP_LOGVV(TAG, "Write: %s |H:%02x%02x%02x A:%02x%02x%02x %02x T:%02x C:%02x%02x S:%02d", packet->content_bytes(), - packet->content(0), packet->content(1), packet->content(2), packet->content(3), packet->content(4), - packet->content(5), packet->content(6), packet->content(7), packet->content(8), packet->content(9), - packet->size()); uint8_t *mac = packet->peer_as_bytes(); + + ESP_LOGVV(TAG, "Write: H:%02x%02x%02x P:%02x%02x%02x%02x T:%02x C:%02x%02x S:%02d", 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_at(8), + packet->content_at(9), packet->get_size()); 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()); + 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_, packet->retrieve(), 10); - ESP_LOGVV(TAG, "Send (0x%04x.%d): 0x%12llx. Buffer Used: %d", packet->packet_id(), packet->attempts(), - packet->peer(), this->send_queue_used()); + xQueueSendToBack(this->send_queue_, packet, 10); + ESP_LOGVV(TAG, "Send to 0x%12llx (%d.%d): Buffer Used: %d", packet->peer, packet->get_sequents(), packet->attempts, + this->send_queue_used()); + return true; } else { - esp_err_t err = esp_now_send((uint8_t *) &mac, packet->content_bytes(), packet->size()); - ESP_LOGVV(TAG, "S: 0x%04x.%d B: %d%s.", packet->packet_id(), packet->attempts(), this->send_queue_used(), + esp_err_t err = esp_now_send((uint8_t *) &mac, packet->content_bytes(), packet->get_size()); + ESP_LOGVV(TAG, "S: 0x%04x.%d B: %d%s.", packet->get_sequents(), packet->attempts, this->send_queue_used(), (err == ESP_OK) ? "" : " FAILED"); - this->defer([this, packet, err]() { this->on_sent_(packet, err == ESP_OK); }); + this->defer([this, packet, err]() { this->on_sent_(std::move(packet), err == ESP_OK); }); + return true; } + return false; } -void ESPNowComponent::loop() { - // runner(); -} - void ESPNowComponent::runner() { - ESPNowPacket *packet = new ESPNowPacket(); - ESPNowData data; + ESPNowPacket *packet{nullptr}; for (;;) { - if (xQueueReceive(this->receive_queue_, &data, (TickType_t) 1) == pdTRUE) { - packet->store(data); + if (packet != nullptr) + delete packet; + packet = new ESPNowPacket(); + if (xQueueReceive(this->receive_queue_, packet, (TickType_t) 1) == pdTRUE) { uint8_t *mac = packet->peer_as_bytes(); if (!esp_now_is_peer_exist(mac)) { if (!this->auto_add_peer_) { - this->defer([this, packet]() { this->on_new_peer_((ESPNowPacket *) &packet); }); + this->defer([this, packet]() { this->on_new_peer_(std::move(packet)); }); + continue; } else { - this->add_peer(packet->peer()); + this->add_peer(packet->peer); } } - this->defer([this, packet]() { this->on_receive_((ESPNowPacket *) &packet); }); + this->defer([this, packet]() { this->on_receive_(std::move(packet)); }); } - if (xQueueReceive(this->send_queue_, &data, (TickType_t) 1) == pdTRUE) { - packet->store(data); - - if (packet->attempts() > MAX_NUMBER_OF_RETRYS) { - ESP_LOGW(TAG, "To many send retries. Packet dropped. 0x%04x", packet->packet_id()); + if (packet != nullptr) + delete packet; + packet = new ESPNowPacket(); + if (xQueueReceive(this->send_queue_, packet, (TickType_t) 1) == pdTRUE) { + if (packet->attempts > MAX_NUMBER_OF_RETRYS) { + ESP_LOGW(TAG, "To many send retries. Packet dropped. 0x%04x", packet->get_sequents()); this->unlock(); continue; } else if (this->is_locked()) { - if (millis() - packet->timestamp() > 1000) { - ESP_LOGE(TAG, "TimeOut (0x%04x.%d).", packet->packet_id(), packet->attempts()); + if (millis() - packet->timestamp > 1000) { + ESP_LOGE(TAG, "TimeOut (0x%04x.%d).", packet->get_sequents(), packet->attempts); packet->retry(); this->unlock(); } } else { this->lock(); packet->retry(); - packet->timestamp(millis()); + packet->timestamp = millis(); uint8_t *mac = packet->peer_as_bytes(); - esp_err_t err = esp_now_send(mac, packet->content_bytes(), packet->size()); + esp_err_t err = esp_now_send(mac, packet->content_bytes(), packet->get_size() + 1); if (err == ESP_OK) { - ESP_LOGV(TAG, "S: 0x%04x.%d. Wait for conformation. M: %s", packet->packet_id(), packet->attempts(), - packet->content_bytes()); + ESP_LOGV(TAG, "S: 0x%04x.%d. Wait for conformation.", packet->get_sequents(), packet->attempts); } else { - ESP_LOGE(TAG, "S: 0x%04x.%d B: %d.", packet->packet_id(), packet->attempts(), this->send_queue_used()); + ESP_LOGE(TAG, "S: 0x%04x.%d B: %d.", packet->get_sequents(), packet->attempts, this->send_queue_used()); this->unlock(); } } - xQueueSendToFront(this->send_queue_, packet->retrieve(), 10 / portTICK_PERIOD_MS); + xQueueSendToFront(this->send_queue_, packet, 10 / portTICK_PERIOD_MS); } } } void ESPNowComponent::on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) { ESPNowPacket *packet = new ESPNowPacket(); - ESPNowData data; if (!global_esp_now->use_sent_check_) { return; } uint64_t mac64 = (uint64_t) *mac_addr; - if (xQueuePeek(global_esp_now->send_queue_, &data, 10 / portTICK_PERIOD_MS) == pdTRUE) { - packet->store(data); + if (xQueuePeek(global_esp_now->send_queue_, packet, 10 / portTICK_PERIOD_MS) == pdTRUE) { if (status != ESP_OK) { - ESP_LOGE(TAG, "sent packet failed (0x%04x.%d)", packet->packet_id(), packet->attempts()); - } else if (packet->peer() != mac64) { - ESP_LOGE(TAG, " Invalid mac address. (0x%04x.%d) expected: 0x%12llx got: 0x%12llx", packet->packet_id(), - packet->attempts(), packet->peer(), mac64); + ESP_LOGE(TAG, "sent packet failed (0x%04x.%d)", packet->get_sequents(), packet->attempts); + } else if (packet->peer != mac64) { + ESP_LOGE(TAG, " Invalid mac address. (0x%04x.%d) expected: 0x%12llx got: 0x%12llx", packet->get_sequents(), + packet->attempts, packet->peer, mac64); } else { - ESP_LOGV(TAG, "Confirm sent (0x%04x.%d)", packet->packet_id(), packet->attempts()); + ESP_LOGV(TAG, "Confirm sent (0x%04x.%d)", packet->get_sequents(), packet->attempts); global_esp_now->defer([packet]() { - global_esp_now->on_sent_((ESPNowPacket *) &packet, true); - ESPNowData data; - xQueueReceive(global_esp_now->send_queue_, &data, 10 / portTICK_PERIOD_MS); + global_esp_now->on_sent_(std::move(packet), true); + delete packet; + ESPNowPacket tmp; + xQueueReceive(global_esp_now->send_queue_, &tmp, 10 / portTICK_PERIOD_MS); + global_esp_now->unlock(); }); return; } global_esp_now->defer([packet]() { - global_esp_now->on_sent_((ESPNowPacket *) &packet, false); - ESPNowData data; - xQueueReceive(global_esp_now->send_queue_, &data, 10 / portTICK_PERIOD_MS); - uint8_t *xyz = packet->retrieve(); - xQueueSendToFront(global_esp_now->send_queue_, xyz, 10 / portTICK_PERIOD_MS); + global_esp_now->on_sent_(std::move(packet), false); + ESPNowPacket tmp; + xQueueReceive(global_esp_now->send_queue_, &tmp, 10 / portTICK_PERIOD_MS); + xQueueSendToFront(global_esp_now->send_queue_, &tmp, 10 / portTICK_PERIOD_MS); + global_esp_now->unlock(); }); } diff --git a/esphome/components/espnow/espnow.h b/esphome/components/espnow/espnow.h index 08567915db..4b06870c2e 100644 --- a/esphome/components/espnow/espnow.h +++ b/esphome/components/espnow/espnow.h @@ -29,8 +29,7 @@ static uint64_t ESPNOW_ADDR_SELF = {0}; 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_CRC = 0x08; -static const uint8_t ESPNOW_DATA_CONTENT = 0x0A; +static const uint8_t ESPNOW_DATA_CONTENT = 0x08; static const uint8_t MAX_ESPNOW_DATA_SIZE = 240; @@ -41,120 +40,97 @@ static const uint32_t ESPNOW_MAIN_PROTOCOL_ID = 0x11CFAF; static uint8_t last_ref_id = 0; -struct ESPNowData { +struct ESPNowPacket { uint64_t peer{0}; uint8_t rssi{0}; uint8_t attempts{0}; bool is_broadcast{false}; uint32_t timestamp{0}; uint8_t size{0}; - uint8_t content[251]{0}; -} __attribute__((packed)); + struct { + uint8_t header[3]{'N', '0', 'w'}; + uint32_t protocol{0}; + uint8_t sequents{0}; + uint8_t payload[MAX_ESPNOW_DATA_SIZE + 2]{0}; + } __attribute__((packed)) content; + + ESPNowPacket() { this->payload_buffer_ = new ByteBuffer(MAX_ESPNOW_DATA_SIZE); }; -class ESPNowPacket { - public: - ESPNowPacket() { - memset((void *) &(this->data_), 0, sizeof(ESPNowData)); - this->content_ = new ByteBuffer(251); - this->content_->put_uint24(TRANSPORT_HEADER); - }; // Create packet to be send. ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size, uint32_t protocol); // Load received packet's. ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size); - ESPNowPacket(ESPNowData data) : ESPNowPacket() { this->store(data); } - - void store(ESPNowData data) { - memcpy((void *) &(this->data_), (void *) &(data), sizeof(ESPNowData)); - this->content_->clear(); - this->content_->put_bytes((uint8_t *) &(data.content), data.size); - } - - uint8_t *retrieve() { - memcpy((void *) &(this->data_.content), this->content_bytes(), this->size()); - this->data_.size = this->size(); - return (uint8_t *) &(this->data_); - } - - uint64_t peer() { return this->data_.peer; } - uint8_t *peer_as_bytes() { return (uint8_t *) &(this->data_.peer); } - void peer(uint64_t peer) { + uint8_t *peer_as_bytes() { return (uint8_t *) &(this->peer); } + void set_peer(uint64_t peer) { if (peer == 0) { - this->data_.peer = ESPNOW_BROADCAST_ADDR; + this->peer = ESPNOW_BROADCAST_ADDR; } else { - this->data_.peer = peer; + this->peer = peer; } + }; + + inline uint8_t prefix_size() { return sizeof(this->content) - sizeof(this->content.payload); } + + uint8_t get_size() { + this->update_payload_(); + return this->size; + }; + + inline uint32_t get_protocol() { return this->content.protocol; } + void set_protocol(uint32_t protocol) { + this->content.protocol = protocol; + this->update_payload_(); } - bool broadcast() { return this->data_.is_broadcast; }; - void broadcast(bool state) { this->data_.is_broadcast = state; } - - uint32_t timestamp() { return this->data_.timestamp; }; - void timestamp(uint32_t timestamp) { this->data_.timestamp = timestamp; }; - - uint8_t rssi() { return this->data_.rssi; } - void rssi(uint8_t rssi) { this->data_.rssi = rssi; } - - uint8_t size() { - if (this->content_->get_used_space() <= ESPNOW_DATA_CONTENT) { - return ESPNOW_DATA_CONTENT; - } - return this->content_->get_used_space(); + inline uint8_t get_sequents() { return this->content.sequents; } + void set_sequents(uint8_t sequents) { + this->content.sequents = sequents; + this->update_payload_(); } - uint32_t protocol_id() { - this->content_->set_position(ESPNOW_DATA_PROTOCOL); - return this->content_->get_uint24(); - } - void protocol_id(uint32_t protocol) { - this->content_->set_position(ESPNOW_DATA_PROTOCOL); - this->content_->put_uint24(protocol); + ByteBuffer *payload() { + this->payload_buffer_->set_position(this->payload_buffer_->get_used_space()); + return this->payload_buffer_; } - uint8_t packet_id() { - this->content_->set_position(ESPNOW_DATA_PACKET); - return this->content_->get_uint8(); - } - void packet_id(uint8_t packet_id) { - this->content_->set_position(ESPNOW_DATA_PACKET); - this->content_->put_uint8(packet_id); + uint8_t content_at(uint8_t pos) { + this->update_payload_(); + assert(pos < this->size); + return *(((uint8_t *) &this->content) + pos); } - uint16_t crc() { - this->content_->set_position(ESPNOW_DATA_CRC); - return this->content_->get_uint16(); - } - void crc(uint16_t crc) { - this->content_->set_position(ESPNOW_DATA_CRC); - this->content_->put_uint16(crc); + uint8_t *content_bytes() { + this->update_payload_(); + return (uint8_t *) &(this->content); } - ByteBuffer *content() { - this->content_->set_position(this->size()); - return this->content_; - } - - uint8_t content(uint8_t pos) { - this->content_->set_position(pos); - return this->content_->get_uint8(); - } - uint8_t *content_bytes() { return this->content_->get_data().data(); }; - - void retry() { this->data_.attempts++; } - uint8_t attempts() { return this->data_.attempts; } - - void calc_crc() { - this->crc(0); - this->crc(esp_crc16_le(this->packet_id(), this->content_bytes(), this->size())); + uint8_t crc() { + this->update_payload_(); + return this->content.payload[this->size]; } + void retry() { this->attempts++; } bool is_valid(); private: - ByteBuffer *content_{nullptr}; - ESPNowData data_; + ByteBuffer *payload_buffer_{nullptr}; + + uint8_t calc_crc_() { + uint8_t crc = esp_crc8_le(0, (const uint8_t *) &(this->content.protocol), 2); + crc = esp_crc8_le(crc, this->peer_as_bytes(), 6); + return esp_crc8_le(crc, (const uint8_t *) &this->content, this->size); + } + + void update_payload_() { + if (this->payload_buffer_->is_changed()) { + this->payload_buffer_->flip(); + this->payload_buffer_->get_bytes((uint8_t *) &(this->content.payload), this->payload_buffer_->get_used_space()); + this->size = this->payload_buffer_->get_used_space() + this->prefix_size(); + } + this->content.payload[this->size] = this->calc_crc_(); + } }; class ESPNowComponent; @@ -163,38 +139,55 @@ 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(ESPNowPacket *data_packet){}; + virtual void on_sent(ESPNowPacket *data_packet, bool status){}; + virtual void on_new_peer(ESPNowPacket *data_packet){}; virtual uint32_t get_protocol_id() = 0; - uint8_t get_next_ref_id() { return next_ref_id_++; } + uint8_t get_next_sequents() { + if (this->next_sequents_ == 255) { + this->next_sequents_ = 0; + } else { + this->next_sequents_++; + } + return this->next_sequents_; + } + bool is_valid_squence(uint8_t received_sequence) { + bool valid = this->next_sequents_ + 1 == received_sequence; + if (valid) { + this->next_sequents_ = received_sequence; + } + return valid; + } bool write(uint64_t peer, const uint8_t *data, uint8_t len); - bool write(uint64_t peer, std::vector &data); - bool write(ESPNowPacket *packet); + bool write(uint64_t peer, ByteBuffer &data) { + return this->write(peer, data.get_data().data(), (uint8_t) data.get_used_space()); + } protected: - uint8_t next_ref_id_{0}; + uint8_t next_sequents_{255}; }; - class ESPNowDefaultProtocol : public ESPNowProtocol { public: - void on_receive(ESPNowPacket *packet) override { this->on_receive_.call(packet); }; - void on_sent(ESPNowPacket *packet, bool status) override { this->on_sent_.call(packet, status); }; - void on_new_peer(ESPNowPacket *packet) override { this->on_new_peer_.call(packet); }; - uint32_t get_protocol_id() override { return ESPNOW_MAIN_PROTOCOL_ID; }; + void add_on_receive_callback(std::function &&callback) { + this->on_receive_.add(std::move(callback)); + } + void on_receive(ESPNowPacket *data_packet) override { this->on_receive_.call(std::move(data_packet)); }; + void add_on_sent_callback(std::function &&callback) { this->on_sent_.add(std::move(callback)); } - void add_on_receive_callback(std::function &&callback) { - this->on_receive_.add(std::move(callback)); - } + void on_sent(ESPNowPacket *data_packet, bool status) override { + this->on_sent_.call(std::move(data_packet), status); + }; + void add_on_peer_callback(std::function &&callback) { this->on_new_peer_.add(std::move(callback)); } + void on_new_peer(ESPNowPacket *data_packet) override { this->on_new_peer_.call(std::move(data_packet)); }; protected: CallbackManager on_sent_; @@ -225,9 +218,8 @@ class ESPNowComponent : public Component { void setup() override; void runner(); - void loop() override; - bool write(ESPNowPacket *packet); + bool write(ESPNowPacket *data_packet); void register_protocol(ESPNowProtocol *protocol) { protocol->set_parent(this); @@ -258,9 +250,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 on_receive_(ESPNowPacket *data_packet); + void on_sent_(ESPNowPacket *data_packet, bool status); + void on_new_peer_(ESPNowPacket *data_packet); QueueHandle_t receive_queue_{}; QueueHandle_t send_queue_{}; @@ -274,7 +266,7 @@ class ESPNowComponent : public Component { template class SendAction : public Action, public Parented { public: template void set_mac(V mac) { this->mac_ = mac; } - void set_data_template(std::function(Ts...)> func) { + void set_data_template(std::function func) { this->data_func_ = func; this->static_ = false; } @@ -287,7 +279,7 @@ template class SendAction : public Action, public Parente auto mac = this->mac_.value(x...); if (this->static_) { - this->parent_->get_default_protocol()->write(mac, this->data_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); @@ -297,7 +289,7 @@ template class SendAction : public Action, public Parente protected: TemplatableValue mac_{}; bool static_{false}; - std::function(Ts...)> data_func_{}; + std::function data_func_{}; std::vector data_static_{}; }; @@ -325,28 +317,34 @@ template class DelPeerAction : public Action, public Pare TemplatableValue mac_{}; }; +/* + 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](ESPNowPacket * packet, bool status) { this->trigger(std::move(packet), status); }); } }; 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](ESPNowPacket * packet) { this->trigger(std::move(packet)); }); } }; 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](ESPNowPacket * packet) { this->trigger(std::move(packet)); }); } }; +*/ + extern ESPNowComponent *global_esp_now; } // namespace espnow