mirror of
https://github.com/esphome/esphome.git
synced 2025-03-04 09:48:16 +00:00
- move the automations to there own header file
- split the structural data from the ESPNowPacket component - implement getters and setters for the data structure
This commit is contained in:
parent
252dca528f
commit
a9f3ae9ead
57
esphome/components/espnow/automations,h
Normal file
57
esphome/components/espnow/automations,h
Normal file
@ -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); });
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
@ -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) {
|
||||
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 {
|
||||
ESP_LOGE(TAG, "TimeOut (0x%04x.%d).", packet->packet_id(), packet->retrys());
|
||||
} 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 {
|
||||
packet->retry();
|
||||
if (packet->retrys() == 6) {
|
||||
ESP_LOGW(TAG, "To many send retries. Packet dropped. 0x%04x", packet->packet_id());
|
||||
// continue;
|
||||
return;
|
||||
} else {
|
||||
packet->timestamp = millis();
|
||||
this->lock();
|
||||
espnow_addr_t mac;
|
||||
packet->get_mac(&mac);
|
||||
packet->retry();
|
||||
packet->timestamp(millis());
|
||||
uint8_t *mac = packet->peer_as_bytes();
|
||||
|
||||
esp_err_t err = esp_now_send((uint8_t *) &mac, packet->data, packet->size + 10);
|
||||
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->retrys(),
|
||||
packet->to_str().c_str());
|
||||
ESP_LOGV(TAG, "S: 0x%04x.%d. Wait for conformation. M: %s", packet->packet_id(), packet->attempts(),
|
||||
packet->content_bytes());
|
||||
} else {
|
||||
ESP_LOGE(TAG, "S: 0x%04x.%d B: %d.", packet->packet_id(), packet->retrys(), this->send_queue_used());
|
||||
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());
|
||||
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();
|
||||
global_esp_now->defer([packet]() { global_esp_now->on_sent_(packet, true); });
|
||||
});
|
||||
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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ESPNowComponent *global_esp_now = nullptr;
|
||||
|
@ -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,55 +34,80 @@ 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);
|
||||
}
|
||||
else {
|
||||
std::memcpy(&this->peer_, &peer, 6);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
size() {
|
||||
if (this->content_->get_used() <= ESPNOW_DATA_CONTENT) {
|
||||
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();
|
||||
return this->content_->get_used_space();
|
||||
}
|
||||
|
||||
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();
|
||||
@ -111,34 +137,32 @@ void crc(uint16_t crc) {
|
||||
|
||||
ByteBuffer *content() {
|
||||
this->content_->set_position(this->size());
|
||||
return &this->content_;
|
||||
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(); };
|
||||
uint8_t *content_bytes() { return this->content_->get_data().data(); };
|
||||
|
||||
void retry() {
|
||||
if (this->retrys_ < 7) {
|
||||
this->retrys_ = this->retrys_ + 1;
|
||||
}
|
||||
}
|
||||
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(), this->dataptr(), this->size()));
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user