mirror of
https://github.com/esphome/esphome.git
synced 2024-11-24 16:08:10 +01:00
reworked the packet class back to a struct
This commit is contained in:
parent
a1f2d0afa5
commit
3bee619049
2 changed files with 213 additions and 247 deletions
|
@ -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<uint8_t> &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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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<ESPNowComponent> {
|
|||
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<uint8_t> &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<void(ESPNowPacket *)> &&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<void(ESPNowPacket *, bool status)> &&callback) {
|
||||
this->on_sent_.add(std::move(callback));
|
||||
}
|
||||
void add_on_receive_callback(std::function<void(ESPNowPacket *)> &&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<void(ESPNowPacket *)> &&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<void(ESPNowPacket *, bool)> 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<typename... Ts> class SendAction : public Action<Ts...>, public Parented<ESPNowComponent> {
|
||||
public:
|
||||
template<typename V> void set_mac(V mac) { this->mac_ = mac; }
|
||||
void set_data_template(std::function<std::vector<uint8_t>(Ts...)> func) {
|
||||
void set_data_template(std::function<ByteBuffer(Ts...)> func) {
|
||||
this->data_func_ = func;
|
||||
this->static_ = false;
|
||||
}
|
||||
|
@ -287,7 +279,7 @@ template<typename... Ts> class SendAction : public Action<Ts...>, 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<typename... Ts> class SendAction : public Action<Ts...>, public Parente
|
|||
protected:
|
||||
TemplatableValue<uint64_t, Ts...> mac_{};
|
||||
bool static_{false};
|
||||
std::function<std::vector<uint8_t>(Ts...)> data_func_{};
|
||||
std::function<ByteBuffer(Ts...)> data_func_{};
|
||||
std::vector<uint8_t> data_static_{};
|
||||
};
|
||||
|
||||
|
@ -325,28 +317,34 @@ template<typename... Ts> class DelPeerAction : public Action<Ts...>, public Pare
|
|||
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); });
|
||||
[this](ESPNowPacket * packet, bool status) { this->trigger(std::move(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); });
|
||||
parent->get_default_protocol()->add_on_receive_callback(
|
||||
[this](ESPNowPacket * packet) { this->trigger(std::move(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); });
|
||||
parent->get_default_protocol()->add_on_peer_callback(
|
||||
[this](ESPNowPacket * packet) { this->trigger(std::move(packet)); });
|
||||
}
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
extern ESPNowComponent *global_esp_now;
|
||||
|
||||
} // namespace espnow
|
||||
|
|
Loading…
Reference in a new issue