From a9f3ae9ead435d021be678b3baeb30b947c3ff5f Mon Sep 17 00:00:00 2001
From: NP v/d Spek <github_mail@lumensoft.nl>
Date: Thu, 19 Sep 2024 15:40:13 +0200
Subject: [PATCH] - move the automations to there own header file - split the
 structural data from the ESPNowPacket component - implement getters and
 setters for the data structure

---
 esphome/components/espnow/automations,h |  57 ++++++
 esphome/components/espnow/espnow.cpp    | 181 +++++++++---------
 esphome/components/espnow/espnow.h      | 236 +++++++++++-------------
 3 files changed, 255 insertions(+), 219 deletions(-)
 create mode 100644 esphome/components/espnow/automations,h

diff --git a/esphome/components/espnow/automations,h b/esphome/components/espnow/automations,h
new file mode 100644
index 0000000000..350b4eff74
--- /dev/null
+++ b/esphome/components/espnow/automations,h
@@ -0,0 +1,57 @@
+#pragma once
+
+#include "esphome/components/esphome/esphome.h"
+#include "esphome/core/automation.h"
+#include "esphome/core/component.h"
+
+namespace esphome {
+namespace espnow {
+
+template<typename... Ts> class NewPeerAction : public Action<Ts...>, public Parented<ESPNowComponent> {
+ public:
+  template<typename V> void set_mac(V mac) { this->mac_ = mac; }
+  void play(Ts... x) override {
+    auto mac = this->mac_.value(x...);
+    parent_->add_peer(mac);
+  }
+
+ protected:
+  TemplatableValue<uint64_t, Ts...> mac_{};
+};
+
+template<typename... Ts> class DelPeerAction : public Action<Ts...>, public Parented<ESPNowComponent> {
+ public:
+  template<typename V> void set_mac(V mac) { this->mac_ = mac; }
+  void play(Ts... x) override {
+    auto mac = this->mac_.value(x...);
+    parent_->del_peer(mac);
+  }
+
+ protected:
+  TemplatableValue<uint64_t, Ts...> mac_{};
+};
+
+class ESPNowSentTrigger : public Trigger<ESPNowPacket *, bool> {
+ public:
+  explicit ESPNowSentTrigger(ESPNowComponent *parent) {
+    parent->get_default_protocol()->add_on_sent_callback(
+        [this](ESPNowPacket *packet, bool status) { this->trigger(packet, status); });
+  }
+};
+
+class ESPNowReceiveTrigger : public Trigger<ESPNowPacket *> {
+ public:
+  explicit ESPNowReceiveTrigger(ESPNowComponent *parent) {
+    parent->get_default_protocol()->add_on_receive_callback([this](ESPNowPacket *packet) { this->trigger(packet); });
+  }
+};
+
+class ESPNowNewPeerTrigger : public Trigger<ESPNowPacket *> {
+ public:
+  explicit ESPNowNewPeerTrigger(ESPNowComponent *parent) {
+    parent->get_default_protocol()->add_on_peer_callback([this](ESPNowPacket *packet) { this->trigger(packet); });
+  }
+};
+
+}
+}
diff --git a/esphome/components/espnow/espnow.cpp b/esphome/components/espnow/espnow.cpp
index 423bd3ae88..a33fb811a4 100644
--- a/esphome/components/espnow/espnow.cpp
+++ b/esphome/components/espnow/espnow.cpp
@@ -19,6 +19,8 @@
 #include "esphome/core/version.h"
 #include "esphome/core/log.h"
 
+#include <memory>
+
 namespace esphome {
 namespace espnow {
 
@@ -57,17 +59,17 @@ struct {
 
 /* ESPNowPacket ********************************************************************** */
 
-ESPNowPacket::ESPNowPacket(espnow_addr_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) : ESPNowPacket() {
+  this->peer(peer);
 
-  this->is_broadcast_ = memcpr(&this->peer(), &ESPNOW_BROADCAST_ADDR, 6);
+  this->broadcast(std::memcmp((const void *) this->peer_as_bytes(), (const void *) &ESPNOW_BROADCAST_ADDR, 6) == 0);
   this->protocol(protocol);
   this->content()->put_bytes(data, size);
 
-  this->recalc();
+  this->calc_crc();
 }
 
-ESPNowPacket::ESPNowPacket(espnow_addr_t *peer, const uint8_t *data, uint8_t size) : ESPNowPacket() {
+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);
@@ -76,7 +78,7 @@ ESPNowPacket::ESPNowPacket(espnow_addr_t *peer, const uint8_t *data, uint8_t siz
 bool ESPNowPacket::is_valid() {
   uint16_t crc = this->crc();
   this->calc_crc();
-  bool valid = (std::memcmp(this->header(), &TRANSPORT_HEADER, 3) == 0);
+  bool valid = (memcmp((const void *) this->content_bytes(), (const void *) &TRANSPORT_HEADER, 3) == 0);
   valid &= (this->protocol() != 0);
   valid &= (this->crc() == crc);
   this->crc(crc);
@@ -97,7 +99,7 @@ bool ESPNowProtocol::write(uint64_t mac_address, std::vector<uint8_t> &data) {
 bool ESPNowProtocol::write(ESPNowPacket *packet) {
   packet->protocol(this->get_protocol_id());
   packet->packet_id(this->get_next_ref_id());
-  packet->recalc();
+  packet->calc_crc();
   return this->parent_->write(packet);
 }
 
@@ -106,7 +108,7 @@ ESPNowComponent::ESPNowComponent() { global_esp_now = this; }
 void ESPNowComponent::dump_config() {
   ESP_LOGCONFIG(TAG, "esp_now:");
   ESP_LOGCONFIG(TAG, "  MAC Address: " MACSTR, MAC2STR(ESPNOW_ADDR_SELF));
-  ESPNowPacket *packet = new ESPNowPacket(0x112233445566, (uint8_t *) TAG, 5, 0x111111);
+  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),
@@ -178,21 +180,21 @@ void ESPNowComponent::setup() {
     return;
   }
 
-  esp_wifi_get_mac(WIFI_IF_STA, ESPNOW_ADDR_SELF);
+  esp_wifi_get_mac(WIFI_IF_STA, (uint8_t *) &ESPNOW_ADDR_SELF);
 
   for (auto &address : this->peers_) {
-    ESP_LOGI(TAG, "Add peer 0x%s .", format_hex(address).c_str());
+    ESP_LOGI(TAG, "Add peer 0x%12x.", address);
     add_peer(address);
   }
 
-  this->send_queue_ = xQueueCreate(SEND_BUFFER_SIZE, sizeof(ESPNowPacket));
+  this->send_queue_ = xQueueCreate(SEND_BUFFER_SIZE, sizeof(ESPNowData));
   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(ESPNowPacket));
+  this->receive_queue_ = xQueueCreate(SEND_BUFFER_SIZE, sizeof(ESPNowData));
   if (this->receive_queue_ == nullptr) {
     ESP_LOGE(TAG, "Failed to create receive queue");
     this->mark_failed();
@@ -209,7 +211,6 @@ esp_err_t ESPNowComponent::add_peer(uint64_t addr) {
     this->peers_.push_back(addr);
     return ESP_OK;
   } else {
-    uint8_t mac[6];
     this->del_peer(addr);
 
     esp_now_peer_info_t peer_info = {};
@@ -245,6 +246,7 @@ ESPNowProtocol *ESPNowComponent::get_protocol_(uint32_t protocol) {
   }
   return this->protocols_[protocol];
 }
+
 void ESPNowComponent::on_receive_(ESPNowPacket *packet) {
   ESPNowProtocol *protocol = this->get_protocol_(packet->protocol());
   if (protocol != nullptr) {
@@ -273,27 +275,27 @@ void ESPNowComponent::on_data_received(const esp_now_recv_info_t *recv_info, con
 void ESPNowComponent::on_data_received(const uint8_t *addr, const uint8_t *data, int size)
 #endif
 {
-  ESPNowPacket *packet = new ESPNowPacket(espnow_addr_t(*addr), data, size);
+  ESPNowPacket packet((uint64_t) *addr, data, size);
   wifi_pkt_rx_ctrl_t *rx_ctrl = nullptr;
 
 #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 1)
   uint8_t *addr = recv_info->src_addr;
-  packet->broadcast(*recv_info->des_addr == ESPNOW_BROADCAST_ADDR);
+  packet.broadcast(*recv_info->des_addr == ESPNOW_BROADCAST_ADDR);
   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));
   rx_ctrl = &promiscuous_pkt->rx_ctrl;
 #endif
-  packet->rssi(rx_ctrl->rssi);
-  packet->timestamp(rx_ctrl->timestamp);
-  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);
+  packet.rssi(rx_ctrl->rssi);
+  packet.timestamp(rx_ctrl->timestamp);
+  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());
 
-  if (packet->is_valid()) {
-    xQueueSendToBack(global_esp_now->receive_queue_, packet, 10);
+  if (packet.is_valid()) {
+    xQueueSendToBack(global_esp_now->receive_queue_, packet.retrieve(), 10);
   } else {
     ESP_LOGE(TAG, "Invalid ESP-NOW packet received (CRC)");
   }
@@ -303,25 +305,24 @@ 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);
-  espnow_addr_t *mac;
-  mac = packet->peer();
+            packet->size());
+  uint8_t *mac = packet->peer_as_bytes();
   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((uint8_t *) mac)) {
-    ESP_LOGW(TAG, "Peer not registered: 0x%12x.", (uint64_t) *mac);
+  } else if (!esp_now_is_peer_exist(mac)) {
+    ESP_LOGW(TAG, "Peer not registered: 0x%12x.", packet->peer());
   } else if (!packet->is_valid()) {
-    ESP_LOGW(TAG, "Packet is invalid. maybe you need to ::recalc(). the packat before writing.");
+    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, 10);
-    ESP_LOGVV(TAG, "Send (0x%04x.%d): 0x%s. Buffer Used: %d", packet->packet_id, packet->retrys(),
-              format_hex(packet->peer()).c_str(), this->send_queue_used());
+    xQueueSendToBack(this->send_queue_, packet->retrieve(), 10);
+    ESP_LOGVV(TAG, "Send (0x%04x.%d): 0x%12x. Buffer Used: %d", packet->packet_id, packet->attempts(), packet->peer(),
+              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->retrys(), this->send_queue_used(),
+    ESP_LOGVV(TAG, "S: 0x%04x.%d B: %d%s.", packet->packet_id(), packet->attempts(), this->send_queue_used(),
               (err == ESP_OK) ? "" : " FAILED");
     this->defer([this, packet, err]() { this->on_sent_(packet, err == ESP_OK); });
   }
@@ -333,90 +334,90 @@ void ESPNowComponent::loop() {
 }
 
 void ESPNowComponent::runner() {
-  ESPNowPacket *packet;
+  ESPNowPacket *packet = new ESPNowPacket();
+  ESPNowData data;
 
   for (;;) {
-    if (xQueueReceive(this->receive_queue_, packet, (TickType_t) 1) == pdTRUE) {
-      espnow_addr_t *mac;
-      mac = packet->peer();
+    if (xQueueReceive(this->receive_queue_, &data, (TickType_t) 1) == pdTRUE) {
+      packet->store(data);
+      uint8_t *mac = packet->peer_as_bytes();
 
-      if (!esp_now_is_peer_exist((uint8_t *) mac)) {
-        if (this->auto_add_peer_) {
-          this->add_peer(mac);
+      if (!esp_now_is_peer_exist(mac)) {
+        if (!this->auto_add_peer_) {
+          this->defer([this, packet, mac]() { this->on_new_peer_((ESPNowPacket *) &packet); });
         } else {
-          this->defer([this, packet]() { this->on_new_peer_(packet); });
-          continue;
+          this->add_peer(packet->peer());
         }
       }
-      if (esp_now_is_peer_exist((uint8_t *) &mac)) {
-        this->defer([this, packet]() { this->on_receive_(packet); });
-      } else {
-        ESP_LOGE(TAG, "Peer not registered: %s", format_hex(packet->mac64).c_str());
-      }
+      this->defer([this, packet]() { this->on_receive_((ESPNowPacket *) &packet); });
     }
-    if (xQueueReceive(this->send_queue_, &packet, (TickType_t) 1) == pdTRUE) {
-      if (this->is_locked()) {
-        if (millis() - packet->timestamp > 1000) {
-          if (packet->retrys() == 6) {
-            ESP_LOGW(TAG, "To many send retries. Packet dropped. 0x%04x", packet->packet_id());
-            this->unlock();
-            continue;
-          } else {
-            ESP_LOGE(TAG, "TimeOut (0x%04x.%d).", packet->packet_id(), packet->retrys());
-            packet->retry();
-          }
+    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());
+        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());
+          packet->retry();
           this->unlock();
         }
       } else {
+        this->lock();
         packet->retry();
-        if (packet->retrys() == 6) {
-          ESP_LOGW(TAG, "To many send retries. Packet dropped. 0x%04x", packet->packet_id());
-          // continue;
-          return;
+        packet->timestamp(millis());
+        uint8_t *mac = packet->peer_as_bytes();
+
+        esp_err_t err = esp_now_send(mac, packet->content_bytes(), packet->size());
+
+        if (err == ESP_OK) {
+          ESP_LOGV(TAG, "S: 0x%04x.%d. Wait for conformation. M: %s", packet->packet_id(), packet->attempts(),
+                   packet->content_bytes());
         } else {
-          packet->timestamp = millis();
-          this->lock();
-          espnow_addr_t mac;
-          packet->get_mac(&mac);
-
-          esp_err_t err = esp_now_send((uint8_t *) &mac, packet->data, packet->size + 10);
-
-          if (err == ESP_OK) {
-            ESP_LOGV(TAG, "S: 0x%04x.%d. Wait for conformation. M: %s", packet->packet_id(), packet->retrys(),
-                     packet->to_str().c_str());
-          } else {
-            ESP_LOGE(TAG, "S: 0x%04x.%d B: %d.", packet->packet_id(), packet->retrys(), this->send_queue_used());
-            this->unlock();
-          }
+          ESP_LOGE(TAG, "S: 0x%04x.%d B: %d.", packet->packet_id(), packet->attempts(), this.send_queue_used());
+          this->unlock();
         }
       }
-      xQueueSendToFront(this->send_queue_, &packet, 10 / portTICK_PERIOD_MS);
+      xQueueSendToFront(this->send_queue_, packet->retrieve(), 10 / portTICK_PERIOD_MS);
     }
   }
 }
 
 void ESPNowComponent::on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) {
-  ESPNowPacket *packet;
+  ESPNowPacket *packet = new ESPNowPacket();
+  ESPNowData data;
   if (!global_esp_now->use_sent_check_) {
     return;
   }
-  uint64_t mac64 = packet->to_mac64((espnow_addr_t *) mac_addr);
-  if (xQueueReceive(global_esp_now->send_queue_, &packet, 10 / portTICK_PERIOD_MS) == pdTRUE) {
+  uint64_t mac64 = (uint64_t) *mac_addr;
+  if (xQueuePeek(global_esp_now->send_queue_, &data, 10 / portTICK_PERIOD_MS) == pdTRUE) {
+    packet->store(data);
     if (status != ESP_OK) {
-      ESP_LOGE(TAG, "sent packet failed (0x%04x.%d)", packet->packet_id(), packet->retrys());
-    } else if (packet->mac64 != mac64) {
-      ESP_LOGE(TAG, " Invalid mac address. (0x%04x.%d) expected: %s got %s", packet->packet_id(), packet->retrys,
-               packet->to_str().c_str(), packet->to_str(mac64).c_str());
+      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%12x got: 0x%12x", packet->packet_id(),
+               packet->retrys, packet->peer(), mac64);
     } else {
-      ESP_LOGV(TAG, "Confirm sent (0x%04x.%d)", packet->packet_id(), packet->retrys());
-      global_esp_now->unlock();
-      global_esp_now->defer([packet]() { global_esp_now->on_sent_(packet, true); });
+      ESP_LOGV(TAG, "Confirm sent (0x%04x.%d)", packet->packet_id(), 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->unlock();
+      });
       return;
     }
-    global_esp_now->defer([packet]() { global_esp_now->on_sent_(packet, false); });
-    xQueueSendToFront(global_esp_now->send_queue_, &packet, 10 / portTICK_PERIOD_MS);
+    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->unlock();
+    });
   }
-  global_esp_now->unlock();
 }
 
 ESPNowComponent *global_esp_now = nullptr;
diff --git a/esphome/components/espnow/espnow.h b/esphome/components/espnow/espnow.h
index 05eac49808..b94463e7c5 100644
--- a/esphome/components/espnow/espnow.h
+++ b/esphome/components/espnow/espnow.h
@@ -22,8 +22,9 @@ namespace espnow {
 
 typedef uint8_t espnow_addr_t[6];
 
-static const espnow_addr_t ESPNOW_BROADCAST_ADDR = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-static espnow_addr_t ESPNOW_ADDR_SELF = {0};
+static const uint64_t ESPNOW_BROADCAST_ADDR = 0xFFFFFFFFFFFF;
+
+static uint64_t ESPNOW_ADDR_SELF = {0};
 
 static const uint8_t ESPNOW_DATA_HEADER = 0x00;
 static const uint8_t ESPNOW_DATA_PROTOCOL = 0x03;
@@ -33,112 +34,135 @@ static const uint8_t ESPNOW_DATA_CONTENT = 0x0A;
 
 static const uint8_t MAX_ESPNOW_DATA_SIZE = 240;
 
+static const uint8_t MAX_NUMBER_OF_RETRYS = 5;
+
 static const uint32_t TRANSPORT_HEADER = 0xC19983;
+static const uint32_t ESPNOW_DEFAULT_APP_ID = 0x11CFAF;
 
 static uint8_t last_ref_id = 0;
 
+struct ESPNowData {
+  union {
+    struct {
+      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};
+    };
+    uint8_t bytes[251 + 16];
+  };
+};
 class ESPNowPacket {
- private:
-  espnow_addr_t peer_{0};
-  uint8_t rssi_{0};
-  uint8_t retrys_{0};
-  bool is_broadcast_{false};
-  uint32_t timestamp_{0};
-  ByteBuffer *content_;
-
  public:
   ESPNowPacket() {
+    memset((void *) &(this->data_.bytes), 0, sizeof(this->data_));
     this->content_ = new ByteBuffer(251);
     this->content_->put_uint24(TRANSPORT_HEADER);
   };
   // Create packet to be send.
-  ESPNowPacket(espnow_addr_t peer, const uint8_t *data, uint8_t size, uint32_t app_id);
+  ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size, uint32_t app_id);
 
   // Load received packet's.
-  ESPNowPacket(espnow_addr_t *peer, const uint8_t *data, uint8_t size);
+  ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size);
 
-  espnow_addr_t *peer() { return &this->peer_; }
-  void peer(espnow_addr_t *peer) {
-    if (*peer[0] == 0) {
-      std::memcpy(&this->peer_, &ESPNOW_BROADCAST_ADDR, 6);
+  ESPNowPacket(ESPNowData data) : ESPNowPacket() { this->store(data); }
+
+  void store(ESPNowData data) {
+    memcpy((void *) &(this->data_.bytes), (void *) &(data.bytes), 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_.bytes);
+  }
+
+  uint64_t peer() { return this->data_.peer; }
+  uint8_t *peer_as_bytes() { return (uint8_t *) &(this->data_.peer); }
+  void peer(uint64_t peer) {
+    if (peer == 0) {
+      this->data_.peer = ESPNOW_BROADCAST_ADDR;
+    } else {
+      this->data_.peer = peer;
     }
   }
-  else {
-    std::memcpy(&this->peer_, &peer, 6);
+
+  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();
   }
-}
 
-uint8_t
-size() {
-  if (this->content_->get_used() <= ESPNOW_DATA_CONTENT) {
-    return ESPNOW_DATA_CONTENT;
+  uint32_t protocol() {
+    this->content_->set_position(ESPNOW_DATA_PROTOCOL);
+    return this->content_->get_uint24();
   }
-  return this->content_->get_used();
-}
-
-bool broadcast(){return this->is_broadcast_};
-void broadcast(bool state) { this->is_broadcast_ = state; }
-
-uint32_t timestamp() { return this->timestamp_; };
-void timestamp(uint32_t timestamp) { this->timestamp_ = timestamp; };
-
-uint32_t protocol() {
-  this->content_->set_position(ESPNOW_DATA_PROTOCOL);
-  return this->content_->get_uint24();
-}
-void protocol(uint32_t protocol) {
-  this->content_->set_position(ESPNOW_DATA_PROTOCOL);
-  this->content_->put_uint24(protocol);
-}
-
-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);
-}
-
-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);
-}
-
-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() {
-  if (this->retrys_ < 7) {
-    this->retrys_ = this->retrys_ + 1;
+  void protocol(uint32_t protocol) {
+    this->content_->set_position(ESPNOW_DATA_PROTOCOL);
+    this->content_->put_uint24(protocol);
   }
-}
 
-void calc_crc() {
-  this->crc(0);
-  this->crc(esp_crc16_le(this->packet(), this->dataptr(), this->size()));
-}
+  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);
+  }
 
-bool is_valid();
+  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);
+  }
 
+  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()));
+  }
+
+  bool is_valid();
+
+ private:
+  ByteBuffer *content_{nullptr};
+  ESPNowData data_;
 };
 
 class ESPNowComponent;
 
-static const uint32_t ESPNOW_DEFAULT_APP_ID = 0x11CFAF;
-
 class ESPNowProtocol : public Parented<ESPNowComponent> {
  public:
   ESPNowProtocol(){};
@@ -150,8 +174,8 @@ class ESPNowProtocol : public Parented<ESPNowComponent> {
   virtual uint32_t get_protocol_id() = 0;
   uint8_t get_next_ref_id() { return next_ref_id_++; }
 
-  bool write(uint64_t mac_address, const uint8_t *data, uint8_t len);
-  bool write(uint64_t mac_address, std::vector<uint8_t> &data);
+  bool write(uint64_t peer, const uint8_t *data, uint8_t len);
+  bool write(uint64_t peer, std::vector<uint8_t> &data);
   bool write(ESPNowPacket *packet);
 
  protected:
@@ -281,52 +305,6 @@ template<typename... Ts> class SendAction : public Action<Ts...>, public Parente
   std::vector<uint8_t> data_static_{};
 };
 
-template<typename... Ts> class NewPeerAction : public Action<Ts...>, public Parented<ESPNowComponent> {
- public:
-  template<typename V> void set_mac(V mac) { this->mac_ = mac; }
-  void play(Ts... x) override {
-    auto mac = this->mac_.value(x...);
-    parent_->add_peer(mac);
-  }
-
- protected:
-  TemplatableValue<uint64_t, Ts...> mac_{};
-};
-
-template<typename... Ts> class DelPeerAction : public Action<Ts...>, public Parented<ESPNowComponent> {
- public:
-  template<typename V> void set_mac(V mac) { this->mac_ = mac; }
-  void play(Ts... x) override {
-    auto mac = this->mac_.value(x...);
-    parent_->del_peer(mac);
-  }
-
- protected:
-  TemplatableValue<uint64_t, Ts...> mac_{};
-};
-
-class ESPNowSentTrigger : public Trigger<ESPNowPacket *, bool> {
- public:
-  explicit ESPNowSentTrigger(ESPNowComponent *parent) {
-    parent->get_default_protocol()->add_on_sent_callback(
-        [this](ESPNowPacket *packet, bool status) { this->trigger(packet, status); });
-  }
-};
-
-class ESPNowReceiveTrigger : public Trigger<ESPNowPacket *> {
- public:
-  explicit ESPNowReceiveTrigger(ESPNowComponent *parent) {
-    parent->get_default_protocol()->add_on_receive_callback([this](ESPNowPacket *packet) { this->trigger(packet); });
-  }
-};
-
-class ESPNowNewPeerTrigger : public Trigger<ESPNowPacket *> {
- public:
-  explicit ESPNowNewPeerTrigger(ESPNowComponent *parent) {
-    parent->get_default_protocol()->add_on_peer_callback([this](ESPNowPacket *packet) { this->trigger(packet); });
-  }
-};
-
 extern ESPNowComponent *global_esp_now;
 
 }  // namespace espnow