mirror of
https://github.com/esphome/esphome.git
synced 2025-03-04 09:48:16 +00:00
wip
This commit is contained in:
parent
66edf966ba
commit
37df47914d
1
.gitignore
vendored
1
.gitignore
vendored
@ -140,3 +140,4 @@ sdkconfig.*
|
|||||||
/components
|
/components
|
||||||
/managed_components
|
/managed_components
|
||||||
|
|
||||||
|
esphome/components/espnow/test.yaml
|
||||||
|
5
esphome/components/espnow/.gitignore
vendored
Normal file
5
esphome/components/espnow/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Gitignore settings for ESPHome
|
||||||
|
# This is an example and may include too much for your use-case.
|
||||||
|
# You can modify this file to suit your needs.
|
||||||
|
/.esphome/
|
||||||
|
/secrets.yaml
|
@ -55,20 +55,22 @@ struct {
|
|||||||
} __attribute__((packed)) espnow_frame_format_t;
|
} __attribute__((packed)) espnow_frame_format_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ESPNowPacket::ESPNowPacket(espnow_addr_t peer, const uint8_t *data, uint8_t size, uint32_t protocol) : ESPNowPacket() {
|
/* ESPNowPacket ********************************************************************** */
|
||||||
if (this->peer() == {0})
|
|
||||||
this->peer(ESPNOW_BROADCAST_ADDR);
|
ESPNowPacket::ESPNowPacket(espnow_addr_t peer, const uint8_t *data, uint8_t size, uint32_t protocol) : ESPNowPacket() {
|
||||||
this->is_broadcast = memcpr(&this->peer(), &ESPNOW_BROADCAST_ADDR, 6);
|
this->peer(&peer);
|
||||||
this->protocol(protocol);
|
|
||||||
this->content_->get_data().std::memcpy(&this->data, (uint8_t *) data, this->size);
|
this->is_broadcast_ = memcpr(&this->peer(), &ESPNOW_BROADCAST_ADDR, 6);
|
||||||
|
this->protocol(protocol);
|
||||||
|
this->content()->put_bytes(data, size);
|
||||||
|
|
||||||
this->data[this->size + 1] = 0;
|
|
||||||
this->recalc();
|
this->recalc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESPNowPacket::info(std::string place) {
|
ESPNowPacket::ESPNowPacket(espnow_addr_t *peer, const uint8_t *data, uint8_t size) : ESPNowPacket() {
|
||||||
ESP_LOGVV(TAG, "%s: M:%s A:0x%06x R:0x%02x C:0x%04x S:%02x", place.c_str(), this->to_str().c_str(), this->app_id,
|
this->peer(peer);
|
||||||
this->ref_id, this->random, this->size);
|
this->content_->set_position(0);
|
||||||
|
this->content_->put_bytes(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESPNowPacket::is_valid() {
|
bool ESPNowPacket::is_valid() {
|
||||||
@ -77,26 +79,25 @@ bool ESPNowPacket::is_valid() {
|
|||||||
bool valid = (std::memcmp(this->header(), &TRANSPORT_HEADER, 3) == 0);
|
bool valid = (std::memcmp(this->header(), &TRANSPORT_HEADER, 3) == 0);
|
||||||
valid &= (this->protocol() != 0);
|
valid &= (this->protocol() != 0);
|
||||||
valid &= (this->crc() == crc);
|
valid &= (this->crc() == crc);
|
||||||
if (!valid) {
|
|
||||||
ESP_LOGV("Packet", "Invalid H:%02x%02x%02x A:%06x R:%02x C:%04x ipv. %04x\n", this->header()[0], this->header()[1],
|
|
||||||
this->header()[2], this->protocol(), this->packet_id(), crc, this->crc());
|
|
||||||
}
|
|
||||||
this->crc(crc);
|
this->crc(crc);
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ESPNowProtocol ********************************************************************** */
|
||||||
|
|
||||||
bool ESPNowProtocol::write(uint64_t mac_address, const uint8_t *data, uint8_t len) {
|
bool ESPNowProtocol::write(uint64_t mac_address, const uint8_t *data, uint8_t len) {
|
||||||
ESPNowPacket packet(mac_address, data, len, this->get_protocol_id());
|
ESPNowPacket *packet = new ESPNowPacket(mac_address, data, len, this->get_protocol_id());
|
||||||
return this->parent_->write(packet);
|
return this->parent_->write(packet);
|
||||||
}
|
}
|
||||||
bool ESPNowProtocol::write(uint64_t mac_address, std::vector<uint8_t> &data) {
|
bool ESPNowProtocol::write(uint64_t mac_address, std::vector<uint8_t> &data) {
|
||||||
ESPNowPacket packet(mac_address, (uint8_t *) data.data(), (uint8_t) data.size(), this->get_protocol_id());
|
ESPNowPacket *packet =
|
||||||
|
new ESPNowPacket(mac_address, (uint8_t *) data.data(), (uint8_t) data.size(), this->get_protocol_id());
|
||||||
return this->parent_->write(packet);
|
return this->parent_->write(packet);
|
||||||
}
|
}
|
||||||
bool ESPNowProtocol::write(ESPNowPacket packet) {
|
bool ESPNowProtocol::write(ESPNowPacket *packet) {
|
||||||
packet.protocol(this->get_protocol_id());
|
packet->protocol(this->get_protocol_id());
|
||||||
packet.ref_id = this->get_next_ref_id();
|
packet->packet_id(this->get_next_ref_id());
|
||||||
packet.recalc();
|
packet->recalc();
|
||||||
return this->parent_->write(packet);
|
return this->parent_->write(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,14 +106,16 @@ ESPNowComponent::ESPNowComponent() { global_esp_now = this; }
|
|||||||
void ESPNowComponent::dump_config() {
|
void ESPNowComponent::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, "esp_now:");
|
ESP_LOGCONFIG(TAG, "esp_now:");
|
||||||
ESP_LOGCONFIG(TAG, " MAC Address: " MACSTR, MAC2STR(ESPNOW_ADDR_SELF));
|
ESP_LOGCONFIG(TAG, " MAC Address: " MACSTR, MAC2STR(ESPNOW_ADDR_SELF));
|
||||||
ESPNowPacket packet(0x112233445566, (uint8_t *) TAG, 5, 0x111111);
|
ESPNowPacket *packet = new ESPNowPacket(0x112233445566, (uint8_t *) TAG, 5, 0x111111);
|
||||||
ESP_LOGI(TAG, "test: %s |H:%02x%02x%02x A:%02x%02x%02x %02x T:%02x C:%02x%02x S:%02d", packet.to_str().c_str(),
|
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(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(5), packet->content(6), packet->content(7), packet->content(8), packet->content(9),
|
||||||
|
packet->size());
|
||||||
|
|
||||||
ESP_LOGI(TAG, "test: A:%06x R:%02x C:%04x S:%02d", packet.app_id, packet.ref_id, packet.crc16, packet.size);
|
ESP_LOGI(TAG, "test: A:%06x R:%02x C:%04x S:%02d", packet->app_id(), packet->packet_id(), packet->crc16(),
|
||||||
|
packet->size());
|
||||||
ESP_LOGI(TAG, "test: is_valid: %s",
|
ESP_LOGI(TAG, "test: is_valid: %s",
|
||||||
packet.is_valid() ? "Yes" : "No"); // ESP_LOGCONFIG(TAG, " WiFi Channel: %n", WiFi.channel());
|
packet->is_valid() ? "Yes" : "No"); // ESP_LOGCONFIG(TAG, " WiFi Channel: %n", WiFi.channel());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESPNowComponent::validate_channel_(uint8_t channel) {
|
bool ESPNowComponent::validate_channel_(uint8_t channel) {
|
||||||
@ -235,27 +238,31 @@ ESPNowDefaultProtocol *ESPNowComponent::get_default_protocol() {
|
|||||||
return (ESPNowDefaultProtocol *) this->protocols_[ESPNOW_DEFAULT_APP_ID];
|
return (ESPNowDefaultProtocol *) this->protocols_[ESPNOW_DEFAULT_APP_ID];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESPNowComponent::on_receive_(ESPNowPacket packet) {
|
ESPNowProtocol *ESPNowComponent::get_protocol_(uint32_t protocol) {
|
||||||
if (this->protocols_[packet.app_id] == nullptr) {
|
if (this->protocols_[protocol] == nullptr) {
|
||||||
ESP_LOGE(TAG, "Protocol for '%06x' is not registered", packet.app_id);
|
ESP_LOGE(TAG, "Protocol for '%06x' is not registered", protocol);
|
||||||
} else {
|
return nullptr;
|
||||||
this->protocols_[packet.app_id]->on_receive(packet);
|
}
|
||||||
|
return this->protocols_[protocol];
|
||||||
|
}
|
||||||
|
void ESPNowComponent::on_receive_(ESPNowPacket *packet) {
|
||||||
|
ESPNowProtocol *protocol = this->get_protocol_(packet->protocol());
|
||||||
|
if (protocol != nullptr) {
|
||||||
|
protocol->on_receive(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESPNowComponent::on_sent_(ESPNowPacket packet, bool status) {
|
void ESPNowComponent::on_sent_(ESPNowPacket *packet, bool status) {
|
||||||
if (this->protocols_[packet.app_id] == nullptr) {
|
ESPNowProtocol *protocol = this->get_protocol_(packet->protocol());
|
||||||
ESP_LOGE(TAG, "Protocol for '%06x' is not registered", packet.app_id);
|
if (protocol != nullptr) {
|
||||||
} else {
|
protocol->on_sent(packet, status);
|
||||||
this->protocols_[packet.app_id]->on_sent(packet, status);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESPNowComponent::on_new_peer_(ESPNowPacket packet) {
|
void ESPNowComponent::on_new_peer_(ESPNowPacket *packet) {
|
||||||
if (this->protocols_[packet.app_id] == nullptr) {
|
ESPNowProtocol *protocol = this->get_protocol_(packet->protocol());
|
||||||
ESP_LOGE(TAG, "Protocol for '%06x' is not registered", packet.app_id);
|
if (protocol != nullptr) {
|
||||||
} else {
|
protocol->on_new_peer(packet);
|
||||||
this->protocols_[packet.app_id]->on_new_peer(packet);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,56 +273,55 @@ 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)
|
void ESPNowComponent::on_data_received(const uint8_t *addr, const uint8_t *data, int size)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
ESPNowPacket packet;
|
ESPNowPacket *packet = new ESPNowPacket(espnow_addr_t(*addr), data, size);
|
||||||
wifi_pkt_rx_ctrl_t *rx_ctrl = nullptr;
|
wifi_pkt_rx_ctrl_t *rx_ctrl = nullptr;
|
||||||
|
|
||||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 1)
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 1)
|
||||||
uint8_t *addr = recv_info->src_addr;
|
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;
|
rx_ctrl = recv_info->rx_ctrl;
|
||||||
#else
|
#else
|
||||||
wifi_promiscuous_pkt_t *promiscuous_pkt =
|
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) - sizeof(espnow_frame_format_t));
|
||||||
rx_ctrl = &promiscuous_pkt->rx_ctrl;
|
rx_ctrl = &promiscuous_pkt->rx_ctrl;
|
||||||
#endif
|
#endif
|
||||||
packet.set_mac((espnow_addr_t *) addr);
|
packet->rssi(rx_ctrl->rssi);
|
||||||
packet.rssi = rx_ctrl->rssi;
|
packet->timestamp(rx_ctrl->timestamp);
|
||||||
memcpy((void *) &packet.content, (void *) data, size);
|
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.size = size - 10;
|
packet->content(0), packet->content(1), packet->content(2), packet->content(3), packet->content(4),
|
||||||
packet.timestamp = rx_ctrl->timestamp;
|
packet->content(5), packet->content(6), packet->content(7), packet->content(8), packet->content(9),
|
||||||
ESP_LOGVV(TAG, "Read: %s |H:%02x%02x%02x A:%02x%02x%02x %02x T:%02x C:%02x%02x S:%02d", packet.to_str().c_str(),
|
packet->size);
|
||||||
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()) {
|
if (packet->is_valid()) {
|
||||||
xQueueSendToBack(global_esp_now->receive_queue_, &packet, 10);
|
xQueueSendToBack(global_esp_now->receive_queue_, packet, 10);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "Invalid ESP-NOW packet received (CRC)");
|
ESP_LOGE(TAG, "Invalid ESP-NOW packet received (CRC)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESPNowComponent::write(ESPNowPacket packet) {
|
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.to_str().c_str(),
|
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(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(5), packet->content(6), packet->content(7), packet->content(8), packet->content(9),
|
||||||
espnow_addr_t mac;
|
packet->size);
|
||||||
packet.get_mac(&mac);
|
espnow_addr_t *mac;
|
||||||
|
mac = packet->peer();
|
||||||
if (this->is_failed()) {
|
if (this->is_failed()) {
|
||||||
ESP_LOGE(TAG, "Cannot send espnow packet, espnow failed to setup");
|
ESP_LOGE(TAG, "Cannot send espnow packet, espnow failed to setup");
|
||||||
} else if (this->send_queue_full()) {
|
} else if (this->send_queue_full()) {
|
||||||
ESP_LOGE(TAG, "Send Buffer Out of Memory.");
|
ESP_LOGE(TAG, "Send Buffer Out of Memory.");
|
||||||
} else if (!esp_now_is_peer_exist((uint8_t *) &mac)) {
|
} else if (!esp_now_is_peer_exist((uint8_t *) mac)) {
|
||||||
ESP_LOGW(TAG, "Peer not registered: 0x%s.", packet.to_str().c_str());
|
ESP_LOGW(TAG, "Peer not registered: 0x%12x.", (uint64_t) *mac);
|
||||||
} else if (!packet.is_valid()) {
|
} 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 ::recalc(). the packat before writing.");
|
||||||
} else if (this->use_sent_check_) {
|
} else if (this->use_sent_check_) {
|
||||||
xQueueSendToBack(this->send_queue_, &packet, 10);
|
xQueueSendToBack(this->send_queue_, packet, 10);
|
||||||
ESP_LOGVV(TAG, "Send (0x%04x.%d): 0x%s. Buffer Used: %d", packet.ref_id, packet.retrys,
|
ESP_LOGVV(TAG, "Send (0x%04x.%d): 0x%s. Buffer Used: %d", packet->packet_id, packet->retrys(),
|
||||||
format_hex(packet.mac64).c_str(), this->send_queue_used());
|
format_hex(packet->peer()).c_str(), this->send_queue_used());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
esp_err_t err = esp_now_send((uint8_t *) &mac, (uint8_t *) &packet.content, packet.size + 10);
|
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.ref_id, packet.retrys, this->send_queue_used(),
|
ESP_LOGVV(TAG, "S: 0x%04x.%d B: %d%s.", packet->packet_id(), packet->retrys(), this->send_queue_used(),
|
||||||
(err == ESP_OK) ? "" : " FAILED");
|
(err == ESP_OK) ? "" : " FAILED");
|
||||||
this->defer([this, packet, err]() { this->on_sent_(packet, err == ESP_OK); });
|
this->defer([this, packet, err]() { this->on_sent_(packet, err == ESP_OK); });
|
||||||
}
|
}
|
||||||
@ -327,16 +333,16 @@ void ESPNowComponent::loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ESPNowComponent::runner() {
|
void ESPNowComponent::runner() {
|
||||||
ESPNowPacket packet;
|
ESPNowPacket *packet;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (xQueueReceive(this->receive_queue_, &packet, (TickType_t) 1) == pdTRUE) {
|
if (xQueueReceive(this->receive_queue_, packet, (TickType_t) 1) == pdTRUE) {
|
||||||
espnow_addr_t mac;
|
espnow_addr_t *mac;
|
||||||
packet.get_mac(&mac);
|
mac = packet->peer();
|
||||||
|
|
||||||
if (!esp_now_is_peer_exist((uint8_t *) &mac)) {
|
if (!esp_now_is_peer_exist((uint8_t *) mac)) {
|
||||||
if (this->auto_add_peer_) {
|
if (this->auto_add_peer_) {
|
||||||
this->add_peer(packet.mac64);
|
this->add_peer(mac);
|
||||||
} else {
|
} else {
|
||||||
this->defer([this, packet]() { this->on_new_peer_(packet); });
|
this->defer([this, packet]() { this->on_new_peer_(packet); });
|
||||||
continue;
|
continue;
|
||||||
@ -345,41 +351,41 @@ void ESPNowComponent::runner() {
|
|||||||
if (esp_now_is_peer_exist((uint8_t *) &mac)) {
|
if (esp_now_is_peer_exist((uint8_t *) &mac)) {
|
||||||
this->defer([this, packet]() { this->on_receive_(packet); });
|
this->defer([this, packet]() { this->on_receive_(packet); });
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "Peer not registered: %s", format_hex(packet.mac64).c_str());
|
ESP_LOGE(TAG, "Peer not registered: %s", format_hex(packet->mac64).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (xQueueReceive(this->send_queue_, &packet, (TickType_t) 1) == pdTRUE) {
|
if (xQueueReceive(this->send_queue_, &packet, (TickType_t) 1) == pdTRUE) {
|
||||||
if (this->is_locked()) {
|
if (this->is_locked()) {
|
||||||
if (millis() - packet.timestamp > 1000) {
|
if (millis() - packet->timestamp > 1000) {
|
||||||
if (packet.retrys == 6) {
|
if (packet->retrys() == 6) {
|
||||||
ESP_LOGW(TAG, "To many send retries. Packet dropped. 0x%04x", packet.ref_id);
|
ESP_LOGW(TAG, "To many send retries. Packet dropped. 0x%04x", packet->packet_id());
|
||||||
this->unlock();
|
this->unlock();
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "TimeOut (0x%04x.%d).", packet.ref_id, packet.retrys);
|
ESP_LOGE(TAG, "TimeOut (0x%04x.%d).", packet->packet_id(), packet->retrys());
|
||||||
packet.retry();
|
packet->retry();
|
||||||
}
|
}
|
||||||
this->unlock();
|
this->unlock();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
packet.retry();
|
packet->retry();
|
||||||
if (packet.retrys == 6) {
|
if (packet->retrys() == 6) {
|
||||||
ESP_LOGW(TAG, "To many send retries. Packet dropped. 0x%04x", packet.ref_id);
|
ESP_LOGW(TAG, "To many send retries. Packet dropped. 0x%04x", packet->packet_id());
|
||||||
// continue;
|
// continue;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
packet.timestamp = millis();
|
packet->timestamp = millis();
|
||||||
this->lock();
|
this->lock();
|
||||||
espnow_addr_t mac;
|
espnow_addr_t mac;
|
||||||
packet.get_mac(&mac);
|
packet->get_mac(&mac);
|
||||||
|
|
||||||
esp_err_t err = esp_now_send((uint8_t *) &mac, packet.data, packet.size + 10);
|
esp_err_t err = esp_now_send((uint8_t *) &mac, packet->data, packet->size + 10);
|
||||||
|
|
||||||
if (err == ESP_OK) {
|
if (err == ESP_OK) {
|
||||||
ESP_LOGV(TAG, "S: 0x%04x.%d. Wait for conformation. M: %s", packet.ref_id, packet.retrys,
|
ESP_LOGV(TAG, "S: 0x%04x.%d. Wait for conformation. M: %s", packet->packet_id(), packet->retrys(),
|
||||||
packet.to_str().c_str());
|
packet->to_str().c_str());
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "S: 0x%04x.%d B: %d.", packet.ref_id, packet.retrys, this->send_queue_used());
|
ESP_LOGE(TAG, "S: 0x%04x.%d B: %d.", packet->packet_id(), packet->retrys(), this->send_queue_used());
|
||||||
this->unlock();
|
this->unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -390,19 +396,19 @@ void ESPNowComponent::runner() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ESPNowComponent::on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) {
|
void ESPNowComponent::on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) {
|
||||||
ESPNowPacket packet;
|
ESPNowPacket *packet;
|
||||||
if (!global_esp_now->use_sent_check_) {
|
if (!global_esp_now->use_sent_check_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint64_t mac64 = packet.to_mac64((espnow_addr_t *) mac_addr);
|
uint64_t mac64 = packet->to_mac64((espnow_addr_t *) mac_addr);
|
||||||
if (xQueueReceive(global_esp_now->send_queue_, &packet, 10 / portTICK_PERIOD_MS) == pdTRUE) {
|
if (xQueueReceive(global_esp_now->send_queue_, &packet, 10 / portTICK_PERIOD_MS) == pdTRUE) {
|
||||||
if (status != ESP_OK) {
|
if (status != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "sent packet failed (0x%04x.%d)", packet.ref_id, packet.retrys);
|
ESP_LOGE(TAG, "sent packet failed (0x%04x.%d)", packet->packet_id(), packet->retrys());
|
||||||
} else if (packet.mac64 != mac64) {
|
} else if (packet->mac64 != mac64) {
|
||||||
ESP_LOGE(TAG, " Invalid mac address. (0x%04x.%d) expected: %s got %s", packet.ref_id, packet.retrys,
|
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());
|
packet->to_str().c_str(), packet->to_str(mac64).c_str());
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGV(TAG, "Confirm sent (0x%04x.%d)", packet.ref_id, packet.retrys);
|
ESP_LOGV(TAG, "Confirm sent (0x%04x.%d)", packet->packet_id(), packet->retrys());
|
||||||
global_esp_now->unlock();
|
global_esp_now->unlock();
|
||||||
global_esp_now->defer([packet]() { global_esp_now->on_sent_(packet, true); });
|
global_esp_now->defer([packet]() { global_esp_now->on_sent_(packet, true); });
|
||||||
return;
|
return;
|
||||||
|
@ -33,21 +33,8 @@ static const uint8_t ESPNOW_DATA_CONTENT = 0x0A;
|
|||||||
|
|
||||||
static const uint8_t MAX_ESPNOW_DATA_SIZE = 240;
|
static const uint8_t MAX_ESPNOW_DATA_SIZE = 240;
|
||||||
|
|
||||||
static const uint8_t MAX_ESPNOW_DATA_SIZE = 240;
|
|
||||||
|
|
||||||
static const uint32_t TRANSPORT_HEADER = 0xC19983;
|
static const uint32_t TRANSPORT_HEADER = 0xC19983;
|
||||||
|
|
||||||
template<typename... Args> std::string string_format(const std::string &format, Args... args) {
|
|
||||||
int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0'
|
|
||||||
if (size_s <= 0) {
|
|
||||||
return ("Error during formatting.");
|
|
||||||
}
|
|
||||||
auto size = static_cast<size_t>(size_s);
|
|
||||||
std::unique_ptr<char[]> buf(new char[size]);
|
|
||||||
std::snprintf(buf.get(), size, format.c_str(), args...);
|
|
||||||
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t last_ref_id = 0;
|
static uint8_t last_ref_id = 0;
|
||||||
|
|
||||||
class ESPNowPacket {
|
class ESPNowPacket {
|
||||||
@ -57,30 +44,39 @@ class ESPNowPacket {
|
|||||||
uint8_t retrys_{0};
|
uint8_t retrys_{0};
|
||||||
bool is_broadcast_{false};
|
bool is_broadcast_{false};
|
||||||
uint32_t timestamp_{0};
|
uint32_t timestamp_{0};
|
||||||
ByteBuffer content_(251);
|
ByteBuffer *content_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ESPNowPacket() ESPHOME_ALWAYS_INLINE { this->content_.put_uint24(TRANSPORT_HEADER); }
|
ESPNowPacket() {
|
||||||
|
this->content_ = new ByteBuffer(251);
|
||||||
|
this->content_->put_uint24(TRANSPORT_HEADER);
|
||||||
|
};
|
||||||
// Create packet to be send.
|
// Create packet to be send.
|
||||||
ESPNowPacket(espnow_addr_t peer, const uint8_t *data, uint8_t size, uint32_t app_id);
|
ESPNowPacket(espnow_addr_t peer, const uint8_t *data, uint8_t size, uint32_t app_id);
|
||||||
|
|
||||||
// Load received packet's.
|
// Load received packet's.
|
||||||
ESPNowPacket(espnow_addr_t peer, const uint8_t *data, uint8_t size);
|
ESPNowPacket(espnow_addr_t *peer, const uint8_t *data, uint8_t size);
|
||||||
|
|
||||||
inline void info(std::string place);
|
espnow_addr_t *peer() { return &this->peer_; }
|
||||||
|
void peer(espnow_addr_t *peer) {
|
||||||
uint8_T *peer() { return this->peer_; }
|
if (*peer[0] == 0) {
|
||||||
void peer(espnow_addr_t mac_addres) { std::memcpy(&this->peer_, &mac_addres, 6); }
|
std::memcpy(&this->peer_, &ESPNOW_BROADCAST_ADDR, 6);
|
||||||
|
|
||||||
uint8_T size() {
|
|
||||||
if (this->content_->get_used() <= 10) {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return this->content_->get_used();
|
}
|
||||||
|
else {
|
||||||
|
std::memcpy(&this->peer_, &peer, 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool broadcast(){return this->is_broadcast_};
|
uint8_t
|
||||||
|
size() {
|
||||||
|
if (this->content_->get_used() <= ESPNOW_DATA_CONTENT) {
|
||||||
|
return ESPNOW_DATA_CONTENT;
|
||||||
|
}
|
||||||
|
return this->content_->get_used();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool broadcast(){return this->is_broadcast_};
|
||||||
void broadcast(bool state) { this->is_broadcast_ = state; }
|
void broadcast(bool state) { this->is_broadcast_ = state; }
|
||||||
|
|
||||||
uint32_t timestamp() { return this->timestamp_; };
|
uint32_t timestamp() { return this->timestamp_; };
|
||||||
@ -114,10 +110,16 @@ void crc(uint16_t crc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer *content() {
|
ByteBuffer *content() {
|
||||||
this->content_.set_position(ESPNOW_DATA_CONTENT + this->size_);
|
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(); };
|
||||||
|
|
||||||
void retry() {
|
void retry() {
|
||||||
if (this->retrys_ < 7) {
|
if (this->retrys_ < 7) {
|
||||||
this->retrys_ = this->retrys_ + 1;
|
this->retrys_ = this->retrys_ + 1;
|
||||||
@ -126,12 +128,11 @@ void retry() {
|
|||||||
|
|
||||||
void calc_crc() {
|
void calc_crc() {
|
||||||
this->crc(0);
|
this->crc(0);
|
||||||
this->crc(esp_crc16_le(this->packet(), this->dataptr(), 10 + size()));
|
this->crc(esp_crc16_le(this->packet(), this->dataptr(), this->size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_valid();
|
bool is_valid();
|
||||||
|
|
||||||
uint8_t *dataptr() { return this->content_->get_data()->data(); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ESPNowComponent;
|
class ESPNowComponent;
|
||||||
@ -142,16 +143,16 @@ class ESPNowProtocol : public Parented<ESPNowComponent> {
|
|||||||
public:
|
public:
|
||||||
ESPNowProtocol(){};
|
ESPNowProtocol(){};
|
||||||
|
|
||||||
virtual void on_receive(ESPNowPacket packet){};
|
virtual void on_receive(ESPNowPacket *packet){};
|
||||||
virtual void on_sent(ESPNowPacket packet, bool status){};
|
virtual void on_sent(ESPNowPacket *packet, bool status){};
|
||||||
virtual void on_new_peer(ESPNowPacket packet){};
|
virtual void on_new_peer(ESPNowPacket *packet){};
|
||||||
|
|
||||||
virtual uint32_t get_protocol_id() = 0;
|
virtual uint32_t get_protocol_id() = 0;
|
||||||
uint8_t get_next_ref_id() { return next_ref_id_++; }
|
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, const uint8_t *data, uint8_t len);
|
||||||
bool write(uint64_t mac_address, std::vector<uint8_t> &data);
|
bool write(uint64_t mac_address, std::vector<uint8_t> &data);
|
||||||
bool write(ESPNowPacket packet);
|
bool write(ESPNowPacket *packet);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint8_t next_ref_id_{0};
|
uint8_t next_ref_id_{0};
|
||||||
@ -159,26 +160,26 @@ class ESPNowProtocol : public Parented<ESPNowComponent> {
|
|||||||
|
|
||||||
class ESPNowDefaultProtocol : public ESPNowProtocol {
|
class ESPNowDefaultProtocol : public ESPNowProtocol {
|
||||||
public:
|
public:
|
||||||
void on_receive(ESPNowPacket packet) override { this->on_receive_.call(packet); };
|
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_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); };
|
void on_new_peer(ESPNowPacket *packet) override { this->on_new_peer_.call(packet); };
|
||||||
|
|
||||||
uint32_t get_protocol_id() override { return ESPNOW_DEFAULT_APP_ID; };
|
uint32_t get_protocol_id() override { return ESPNOW_DEFAULT_APP_ID; };
|
||||||
|
|
||||||
void add_on_sent_callback(std::function<void(ESPNowPacket, bool status)> &&callback) {
|
void add_on_sent_callback(std::function<void(ESPNowPacket *, bool status)> &&callback) {
|
||||||
this->on_sent_.add(std::move(callback));
|
this->on_sent_.add(std::move(callback));
|
||||||
}
|
}
|
||||||
void add_on_receive_callback(std::function<void(ESPNowPacket)> &&callback) {
|
void add_on_receive_callback(std::function<void(ESPNowPacket *)> &&callback) {
|
||||||
this->on_receive_.add(std::move(callback));
|
this->on_receive_.add(std::move(callback));
|
||||||
}
|
}
|
||||||
void add_on_peer_callback(std::function<void(ESPNowPacket)> &&callback) {
|
void add_on_peer_callback(std::function<void(ESPNowPacket *)> &&callback) {
|
||||||
this->on_new_peer_.add(std::move(callback));
|
this->on_new_peer_.add(std::move(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CallbackManager<void(ESPNowPacket, bool)> on_sent_;
|
CallbackManager<void(ESPNowPacket *, bool)> on_sent_;
|
||||||
CallbackManager<void(ESPNowPacket)> on_receive_;
|
CallbackManager<void(ESPNowPacket *)> on_receive_;
|
||||||
CallbackManager<void(ESPNowPacket)> on_new_peer_;
|
CallbackManager<void(ESPNowPacket *)> on_new_peer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ESPNowComponent : public Component {
|
class ESPNowComponent : public Component {
|
||||||
@ -206,7 +207,7 @@ class ESPNowComponent : public Component {
|
|||||||
void runner();
|
void runner();
|
||||||
void loop() override;
|
void loop() override;
|
||||||
|
|
||||||
bool write(ESPNowPacket packet);
|
bool write(ESPNowPacket *packet);
|
||||||
|
|
||||||
void register_protocol(ESPNowProtocol *protocol) {
|
void register_protocol(ESPNowProtocol *protocol) {
|
||||||
protocol->set_parent(this);
|
protocol->set_parent(this);
|
||||||
@ -229,6 +230,7 @@ class ESPNowComponent : public Component {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool validate_channel_(uint8_t channel);
|
bool validate_channel_(uint8_t channel);
|
||||||
|
ESPNowProtocol *get_protocol_(uint32_t protocol);
|
||||||
|
|
||||||
uint8_t wifi_channel_{0};
|
uint8_t wifi_channel_{0};
|
||||||
|
|
||||||
@ -236,9 +238,9 @@ class ESPNowComponent : public Component {
|
|||||||
bool use_sent_check_{true};
|
bool use_sent_check_{true};
|
||||||
bool lock_{false};
|
bool lock_{false};
|
||||||
|
|
||||||
void on_receive_(ESPNowPacket packet);
|
void on_receive_(ESPNowPacket *packet);
|
||||||
void on_sent_(ESPNowPacket packet, bool status);
|
void on_sent_(ESPNowPacket *packet, bool status);
|
||||||
void on_new_peer_(ESPNowPacket packet);
|
void on_new_peer_(ESPNowPacket *packet);
|
||||||
|
|
||||||
QueueHandle_t receive_queue_{};
|
QueueHandle_t receive_queue_{};
|
||||||
QueueHandle_t send_queue_{};
|
QueueHandle_t send_queue_{};
|
||||||
@ -303,25 +305,25 @@ template<typename... Ts> class DelPeerAction : public Action<Ts...>, public Pare
|
|||||||
TemplatableValue<uint64_t, Ts...> mac_{};
|
TemplatableValue<uint64_t, Ts...> mac_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class ESPNowSentTrigger : public Trigger<ESPNowPacket, bool> {
|
class ESPNowSentTrigger : public Trigger<ESPNowPacket *, bool> {
|
||||||
public:
|
public:
|
||||||
explicit ESPNowSentTrigger(ESPNowComponent *parent) {
|
explicit ESPNowSentTrigger(ESPNowComponent *parent) {
|
||||||
parent->get_default_protocol()->add_on_sent_callback(
|
parent->get_default_protocol()->add_on_sent_callback(
|
||||||
[this](ESPNowPacket value, bool status) { this->trigger(value, status); });
|
[this](ESPNowPacket *packet, bool status) { this->trigger(packet, status); });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ESPNowReceiveTrigger : public Trigger<ESPNowPacket> {
|
class ESPNowReceiveTrigger : public Trigger<ESPNowPacket *> {
|
||||||
public:
|
public:
|
||||||
explicit ESPNowReceiveTrigger(ESPNowComponent *parent) {
|
explicit ESPNowReceiveTrigger(ESPNowComponent *parent) {
|
||||||
parent->get_default_protocol()->add_on_receive_callback([this](ESPNowPacket value) { this->trigger(value); });
|
parent->get_default_protocol()->add_on_receive_callback([this](ESPNowPacket *packet) { this->trigger(packet); });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ESPNowNewPeerTrigger : public Trigger<ESPNowPacket> {
|
class ESPNowNewPeerTrigger : public Trigger<ESPNowPacket *> {
|
||||||
public:
|
public:
|
||||||
explicit ESPNowNewPeerTrigger(ESPNowComponent *parent) {
|
explicit ESPNowNewPeerTrigger(ESPNowComponent *parent) {
|
||||||
parent->get_default_protocol()->add_on_peer_callback([this](ESPNowPacket value) { this->trigger(value); });
|
parent->get_default_protocol()->add_on_peer_callback([this](ESPNowPacket *packet) { this->trigger(packet); });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ std::vector<uint8_t> ByteBuffer::get_vector(size_t length) {
|
|||||||
this->update_used_();
|
this->update_used_();
|
||||||
return {start, start + length};
|
return {start, start + length};
|
||||||
}
|
}
|
||||||
void ByteBuffer::get_data(const uint8_t *data, size_t length) {
|
void ByteBuffer::get_bytes(const uint8_t *data, size_t length) {
|
||||||
assert(this->get_remaining() >= length);
|
assert(this->get_remaining() >= length);
|
||||||
auto start = this->data_.begin() + this->position_;
|
auto start = this->data_.begin() + this->position_;
|
||||||
copy(start, start + length, data);
|
copy(start, start + length, data);
|
||||||
@ -178,7 +178,7 @@ void ByteBuffer::put_vector(const std::vector<uint8_t> &value) {
|
|||||||
this->position_ += value.size();
|
this->position_ += value.size();
|
||||||
this->update_used_();
|
this->update_used_();
|
||||||
}
|
}
|
||||||
void ByteBuffer::put_array(const uint8_t *data, size_t size) {
|
void ByteBuffer::put_bytes(const uint8_t *data, size_t size) {
|
||||||
assert(this->get_remaining() >= size);
|
assert(this->get_remaining() >= size);
|
||||||
std::copy(data[0], data[size], this->data_.begin() + this->position_);
|
std::copy(data[0], data[size], this->data_.begin() + this->position_);
|
||||||
this->position_ += size;
|
this->position_ += size;
|
||||||
|
@ -92,7 +92,7 @@ class ByteBuffer {
|
|||||||
bool get_bool() { return this->get_uint8(); }
|
bool get_bool() { return this->get_uint8(); }
|
||||||
// Get vector of bytes, increment by length
|
// Get vector of bytes, increment by length
|
||||||
std::vector<uint8_t> get_vector(size_t length);
|
std::vector<uint8_t> get_vector(size_t length);
|
||||||
void get_data(const uint8_t *data, size_t length);
|
void get_bytes(const uint8_t *data, size_t length);
|
||||||
|
|
||||||
// Put values into the buffer, increment the position accordingly
|
// Put values into the buffer, increment the position accordingly
|
||||||
// put any integral value, length represents the number of bytes
|
// put any integral value, length represents the number of bytes
|
||||||
@ -113,7 +113,7 @@ class ByteBuffer {
|
|||||||
void put_double(double value);
|
void put_double(double value);
|
||||||
void put_bool(bool value) { this->put_uint8(value); }
|
void put_bool(bool value) { this->put_uint8(value); }
|
||||||
void put_vector(const std::vector<uint8_t> &value);
|
void put_vector(const std::vector<uint8_t> &value);
|
||||||
void put_array(const uint8_t *data, size_t size);
|
void put_bytes(const uint8_t *data, size_t size);
|
||||||
|
|
||||||
inline size_t get_capacity() const { return this->data_.size(); }
|
inline size_t get_capacity() const { return this->data_.size(); }
|
||||||
inline size_t get_position() const { return this->position_; }
|
inline size_t get_position() const { return this->position_; }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user