mirror of
https://github.com/esphome/esphome.git
synced 2024-12-26 15:34:53 +01:00
extend and update the yaml options
This commit is contained in:
parent
a1e12bbd23
commit
6396595989
4 changed files with 139 additions and 122 deletions
|
@ -1,7 +1,7 @@
|
|||
from esphome import automation
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_DATA, CONF_ID, CONF_MAC_ADDRESS, CONF_TRIGGER_ID
|
||||
from esphome.const import CONF_DATA, CONF_ID, CONF_TRIGGER_ID
|
||||
from esphome.core import CORE
|
||||
|
||||
CODEOWNERS = ["@nielsnl68", "@jesserockz"]
|
||||
|
@ -30,14 +30,17 @@ SendAction = espnow_ns.class_("SendAction", automation.Action)
|
|||
NewPeerAction = espnow_ns.class_("NewPeerAction", automation.Action)
|
||||
DelPeerAction = espnow_ns.class_("DelPeerAction", automation.Action)
|
||||
|
||||
CONF_AUTO_ADD_PEER = "auto_add_peer"
|
||||
CONF_CONVORMATION_TIMEOUT = "conformation_timeout"
|
||||
CONF_ESPNOW = "espnow"
|
||||
CONF_RETRIES = "retries"
|
||||
CONF_ON_RECEIVE = "on_receive"
|
||||
CONF_ON_SENT = "on_sent"
|
||||
CONF_ON_NEW_PEER = "on_new_peer"
|
||||
CONF_WIFI_CHANNEL = "wifi_channel"
|
||||
CONF_PEER = "peer"
|
||||
CONF_PEERS = "peers"
|
||||
CONF_AUTO_ADD_PEER = "auto_add_peer"
|
||||
CONF_USE_SENT_CHECK = "use_sent_check"
|
||||
CONF_WIFI_CHANNEL = "wifi_channel"
|
||||
|
||||
|
||||
def validate_raw_data(value):
|
||||
|
@ -56,6 +59,10 @@ CONFIG_SCHEMA = cv.Schema(
|
|||
cv.Optional(CONF_WIFI_CHANNEL, default=0): cv.int_range(0, 14),
|
||||
cv.Optional(CONF_AUTO_ADD_PEER, default=False): cv.boolean,
|
||||
cv.Optional(CONF_USE_SENT_CHECK, default=True): cv.boolean,
|
||||
cv.Optional(
|
||||
CONF_CONVORMATION_TIMEOUT, default="5000ms"
|
||||
): cv.positive_time_period_milliseconds,
|
||||
cv.Optional(CONF_RETRIES, default=5): cv.int_range(min=1, max=10),
|
||||
cv.Optional(CONF_ON_RECEIVE): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESPNowReceiveTrigger),
|
||||
|
@ -89,6 +96,8 @@ async def to_code(config):
|
|||
cg.add(var.set_wifi_channel(config[CONF_WIFI_CHANNEL]))
|
||||
cg.add(var.set_auto_add_peer(config[CONF_AUTO_ADD_PEER]))
|
||||
cg.add(var.set_use_sent_check(config[CONF_USE_SENT_CHECK]))
|
||||
cg.add(var.set_convermation_timeout(config[CONF_CONVORMATION_TIMEOUT]))
|
||||
cg.add(var.set_retries(config[CONF_RETRIES]))
|
||||
|
||||
for conf in config.get(CONF_ON_SENT, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
|
@ -133,7 +142,7 @@ async def register_protocol(var, config):
|
|||
cv.maybe_simple_value(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(ESPNowComponent),
|
||||
cv.Optional(CONF_MAC_ADDRESS): cv.templatable(cv.mac_address),
|
||||
cv.Optional(CONF_PEER): cv.templatable(cv.mac_address),
|
||||
cv.Required(CONF_DATA): cv.templatable(validate_raw_data),
|
||||
},
|
||||
key=CONF_DATA,
|
||||
|
@ -142,10 +151,8 @@ async def register_protocol(var, config):
|
|||
async def send_action(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
if CONF_MAC_ADDRESS in config:
|
||||
template_ = await cg.templatable(
|
||||
config[CONF_MAC_ADDRESS].as_hex, args, cg.uint64
|
||||
)
|
||||
if CONF_PEER in config:
|
||||
template_ = await cg.templatable(config[CONF_PEER].as_hex, args, cg.uint64)
|
||||
cg.add(var.set_mac(template_))
|
||||
|
||||
data = config.get(CONF_DATA, [])
|
||||
|
@ -166,14 +173,14 @@ async def send_action(config, action_id, template_arg, args):
|
|||
cv.maybe_simple_value(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(ESPNowComponent),
|
||||
cv.Required(CONF_MAC_ADDRESS): cv.templatable(cv.mac_address),
|
||||
cv.Required(CONF_PEER): cv.templatable(cv.mac_address),
|
||||
},
|
||||
key=CONF_MAC_ADDRESS,
|
||||
key=CONF_PEER,
|
||||
),
|
||||
)
|
||||
async def new_peer_action(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
template_ = await cg.templatable(config[CONF_MAC_ADDRESS].as_hex, args, cg.uint64)
|
||||
template_ = await cg.templatable(config[CONF_PEER].as_hex, args, cg.uint64)
|
||||
cg.add(var.set_mac(template_))
|
||||
return var
|
||||
|
||||
|
@ -184,13 +191,13 @@ async def new_peer_action(config, action_id, template_arg, args):
|
|||
cv.maybe_simple_value(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(ESPNowComponent),
|
||||
cv.Required(CONF_MAC_ADDRESS): cv.templatable(cv.mac_address),
|
||||
cv.Required(CONF_PEER): cv.templatable(cv.mac_address),
|
||||
},
|
||||
key=CONF_MAC_ADDRESS,
|
||||
key=CONF_PEER,
|
||||
),
|
||||
)
|
||||
async def del_peer_action(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
template_ = await cg.templatable(config[CONF_MAC_ADDRESS].as_hex, args, cg.uint64)
|
||||
template_ = await cg.templatable(config[CONF_PEER].as_hex, args, cg.uint64)
|
||||
cg.add(var.set_mac(template_))
|
||||
return var
|
||||
|
|
|
@ -41,15 +41,21 @@ ESPNowComponent::ESPNowComponent() { ESPNowComponent::static_ = this; } // NOLI
|
|||
|
||||
void ESPNowComponent::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "esp_now:");
|
||||
ESP_LOGCONFIG(TAG, " MAC Address: 0x%12llx.", this->own_peer_address_);
|
||||
|
||||
ESP_LOGCONFIG(TAG, " Own Peer Address: 0x%12llx.", this->own_peer_address_);
|
||||
ESP_LOGCONFIG(TAG, " Wifi channel: %d.", this->wifi_channel_);
|
||||
ESP_LOGCONFIG(TAG, " Auto add new peers: %s.", this->auto_add_peer_ ? "Yes" : "No");
|
||||
|
||||
ESP_LOGCONFIG(TAG, " Use sent status: %s.", this->use_sent_check_ ? "Yes" : "No");
|
||||
ESP_LOGCONFIG(TAG, " Conversation timeout: %dms.", this->conformation_timeout_);
|
||||
ESP_LOGCONFIG(TAG, " Send retries: %d.", this->retries_);
|
||||
}
|
||||
|
||||
void ESPNowComponent::show_packet(const std::string &title, const ESPNowPacket &packet) {
|
||||
ESP_LOGV(TAG,
|
||||
"%s packet. Peer: 0x%12llx Header: %c%c%c Protocol: 0x%02x%02x%02x%02x Sequents: %02x Size: %2d Valid: %s",
|
||||
title.c_str(), packet.peer, 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_size(), packet.is_valid() ? "Yes" : "No");
|
||||
ESP_LOGV(TAG, "%s packet. Peer: 0x%12llx, Header: %c%c%c, Protocol:%c%c%c-%02x, Sequents: %d.%d, Size: %d, Valid: %s",
|
||||
title.c_str(), packet.peer, packet.get_byte_at(0), packet.get_byte_at(1), packet.get_byte_at(2),
|
||||
packet.get_byte_at(3), packet.get_byte_at(4), packet.get_byte_at(5), packet.get_byte_at(6),
|
||||
packet.get_byte_at(7), packet.attempts, packet.content_size(), packet.is_valid() ? "Yes" : "No");
|
||||
}
|
||||
|
||||
bool ESPNowComponent::validate_channel_(uint8_t channel) {
|
||||
|
@ -64,8 +70,6 @@ bool ESPNowComponent::validate_channel_(uint8_t channel) {
|
|||
}
|
||||
|
||||
void ESPNowComponent::setup() {
|
||||
ESP_LOGI(TAG, "Setting up ESP-NOW...");
|
||||
|
||||
#ifndef USE_WIFI
|
||||
esp_event_loop_create_default();
|
||||
|
||||
|
@ -103,6 +107,8 @@ void ESPNowComponent::setup() {
|
|||
return;
|
||||
}
|
||||
if (this->use_sent_check_) {
|
||||
ESP_LOGI(TAG, "send check enabled");
|
||||
|
||||
err = esp_now_register_send_cb(ESPNowComponent::on_data_sent);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_now_register_send_cb failed: %s", esp_err_to_name(err));
|
||||
|
@ -114,7 +120,7 @@ void ESPNowComponent::setup() {
|
|||
esp_wifi_get_mac(WIFI_IF_STA, (uint8_t *) &this->own_peer_address_);
|
||||
|
||||
for (auto &address : this->peers_) {
|
||||
ESP_LOGI(TAG, "Add peer 0x%12llx.", address);
|
||||
ESP_LOGV(TAG, "Add peer '%012llx'.", address);
|
||||
add_peer(address);
|
||||
}
|
||||
|
||||
|
@ -135,7 +141,7 @@ void ESPNowComponent::setup() {
|
|||
|
||||
void ESPNowComponent::loop() {
|
||||
if (!this->task_running_) {
|
||||
xTaskCreate(application_task, "espnow_task", 8192, this, 2, &this->espnow_task_handle_);
|
||||
xTaskCreate(application_task, "espnow_task", 4096, this, tskIDLE_PRIORITY + 1, nullptr);
|
||||
this->task_running_ = true;
|
||||
}
|
||||
}
|
||||
|
@ -167,36 +173,35 @@ esp_err_t ESPNowComponent::del_peer(uint64_t addr) {
|
|||
|
||||
ESPNowDefaultProtocol *ESPNowComponent::get_default_protocol() {
|
||||
if (this->protocols_[ESPNOW_MAIN_PROTOCOL_ID] == nullptr) {
|
||||
this->default_protocol_ = new ESPNowDefaultProtocol(); // NOLINT
|
||||
this->register_protocol(this->default_protocol_);
|
||||
this->register_protocol(new ESPNowDefaultProtocol());
|
||||
}
|
||||
return (ESPNowDefaultProtocol *) this->protocols_[ESPNOW_MAIN_PROTOCOL_ID];
|
||||
}
|
||||
|
||||
ESPNowProtocol *ESPNowComponent::get_protocol_component_(uint32_t protocol) {
|
||||
if (this->protocols_[protocol] == nullptr) {
|
||||
ESP_LOGE(TAG, "Protocol for '0x%06" PRIx32 "' is not registered", protocol);
|
||||
ESP_LOGE(TAG, "Protocol for '%06x' is not registered", protocol);
|
||||
return nullptr;
|
||||
}
|
||||
return this->protocols_[protocol];
|
||||
}
|
||||
|
||||
void ESPNowComponent::call_on_receive_(ESPNowPacket packet) {
|
||||
ESPNowProtocol *protocol = this->get_protocol_component_(packet.protocol());
|
||||
void ESPNowComponent::call_on_receive_(ESPNowPacket &packet) {
|
||||
ESPNowProtocol *protocol = this->get_protocol_component_(packet.get_protocol());
|
||||
if (protocol != nullptr) {
|
||||
this->defer([protocol, packet]() { protocol->on_receive(packet); });
|
||||
}
|
||||
}
|
||||
|
||||
void ESPNowComponent::call_on_sent_(ESPNowPacket packet, bool status) {
|
||||
ESPNowProtocol *protocol = this->get_protocol_component_(packet.protocol());
|
||||
void ESPNowComponent::call_on_sent_(ESPNowPacket &packet, bool status) {
|
||||
ESPNowProtocol *protocol = this->get_protocol_component_(packet.get_protocol());
|
||||
if (protocol != nullptr) {
|
||||
this->defer([protocol, packet, status]() { protocol->on_sent(packet, status); });
|
||||
}
|
||||
}
|
||||
|
||||
void ESPNowComponent::call_on_new_peer_(ESPNowPacket packet) {
|
||||
ESPNowProtocol *protocol = this->get_protocol_component_(packet.protocol());
|
||||
void ESPNowComponent::call_on_new_peer_(ESPNowPacket &packet) {
|
||||
ESPNowProtocol *protocol = this->get_protocol_component_(packet.get_protocol());
|
||||
if (protocol != nullptr) {
|
||||
this->defer([protocol, packet]() { protocol->on_new_peer(packet); });
|
||||
}
|
||||
|
@ -225,7 +230,7 @@ void ESPNowComponent::on_data_received(const uint8_t *addr, const uint8_t *data,
|
|||
(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, (uint8_t) size); // NOLINT
|
||||
ESPNowPacket packet(addr, data, (uint8_t) size); // NOLINT
|
||||
packet.is_broadcast = broadcast;
|
||||
if (rx_ctrl != nullptr) {
|
||||
packet.rssi = rx_ctrl->rssi;
|
||||
|
@ -243,9 +248,8 @@ void ESPNowComponent::on_data_received(const uint8_t *addr, const uint8_t *data,
|
|||
}
|
||||
|
||||
bool ESPNowComponent::send(ESPNowPacket packet) {
|
||||
uint8_t *mac = packet.peer_as_bytes();
|
||||
uint8_t *mac = packet.get_peer();
|
||||
|
||||
this->show_packet("Prepare to send", packet);
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, "Cannot send espnow packet, espnow failed to setup");
|
||||
} else if (this->send_queue_full()) {
|
||||
|
@ -253,15 +257,15 @@ bool ESPNowComponent::send(ESPNowPacket packet) {
|
|||
} else if (!esp_now_is_peer_exist(mac)) {
|
||||
ESP_LOGE(TAG, "Peer not registered: 0x%12llx.", packet.peer);
|
||||
} else if (!packet.is_valid()) {
|
||||
ESP_LOGE(TAG, "This Packet is invalid: 0x%012llx (%d.%d)", packet.peer, packet.sequents(), packet.attempts);
|
||||
ESP_LOGE(TAG, "This Packet is invalid: '%012llx' (%d.%d)", packet.peer, packet.get_sequents(), packet.attempts);
|
||||
} else if (this->use_sent_check_) {
|
||||
ESP_LOGV(TAG, "Placing 0x%012llx (%d.%d) into send buffer. Used: %d of %d", packet.peer, packet.sequents(),
|
||||
ESP_LOGV(TAG, "Placing '%012llx' (%d.%d) into send buffer. Used: %d of %d", packet.peer, packet.get_sequents(),
|
||||
packet.attempts, this->send_queue_used(), SEND_BUFFER_SIZE);
|
||||
xQueueSendToBack(this->send_queue_, (void *) &packet, 10);
|
||||
return true;
|
||||
} else {
|
||||
esp_err_t err = esp_now_send((uint8_t *) &mac, packet.content_as_bytes(), packet.content_size());
|
||||
ESP_LOGD(TAG, "Sended 0x%012llx (%d.%d) directly%s.", packet.peer, packet.sequents(), packet.attempts,
|
||||
esp_err_t err = esp_now_send((uint8_t *) &mac, packet.get_content(), packet.content_size());
|
||||
ESP_LOGV(TAG, "Sended '%012llx' (%d.%d) directly%s.", packet.peer, packet.get_sequents(), packet.attempts,
|
||||
(err == ESP_OK) ? "" : " FAILED");
|
||||
|
||||
this->call_on_sent_(packet, err == ESP_OK);
|
||||
|
@ -275,43 +279,40 @@ void ESPNowComponent::runner() {
|
|||
ESPNowPacket packet; // NOLINT
|
||||
for (;;) {
|
||||
if (xQueueReceive(this->receive_queue_, (void *) &packet, (TickType_t) 1) == pdTRUE) {
|
||||
uint8_t *mac = packet.peer_as_bytes();
|
||||
ESP_LOGD(TAG, "Handling received packet from 0x%012llx (%d.%d).", packet.peer, packet.sequents(),
|
||||
packet.attempts);
|
||||
|
||||
uint8_t *mac = packet.get_peer();
|
||||
if (esp_now_is_peer_exist(mac)) {
|
||||
this->call_on_receive_(packet);
|
||||
} else if (this->auto_add_peer_) {
|
||||
this->add_peer(packet.peer);
|
||||
this->call_on_receive_(packet);
|
||||
} else {
|
||||
if (this->auto_add_peer_) {
|
||||
this->add_peer(packet.peer);
|
||||
}
|
||||
this->call_on_new_peer_(packet);
|
||||
}
|
||||
}
|
||||
if (xQueueReceive(this->send_queue_, (void *) &packet, (TickType_t) 1) == pdTRUE) {
|
||||
if (packet.attempts > MAX_NUMBER_OF_RETRYS) {
|
||||
ESP_LOGE(TAG, "Dropped 0x%012llx (%d.%d). To many send retries.", packet.peer, packet.sequents(),
|
||||
if (packet.attempts > this->retries_) {
|
||||
ESP_LOGE(TAG, "Dropped '%012llx' (%d.%d). To many retries.", packet.peer, packet.get_sequents(),
|
||||
packet.attempts);
|
||||
this->unlock();
|
||||
continue;
|
||||
} else if (this->is_locked()) {
|
||||
if (millis() - packet.timestamp > this->conformation_timeout_) {
|
||||
ESP_LOGW(TAG, "TimeOut 0x%012llx (%d.%d).", packet.peer, packet.sequents(), packet.attempts);
|
||||
if (packet.timestamp + this->conformation_timeout_ < millis()) {
|
||||
ESP_LOGW(TAG, "TimeOut '%012llx' (%d.%d).", packet.peer, packet.get_sequents(), packet.attempts);
|
||||
this->unlock();
|
||||
}
|
||||
} else {
|
||||
this->lock();
|
||||
packet.retry();
|
||||
packet.timestamp = millis();
|
||||
uint8_t *mac = packet.peer_as_bytes();
|
||||
uint8_t *mac = packet.get_peer();
|
||||
|
||||
esp_err_t err = esp_now_send(mac, packet.content_as_bytes(), packet.content_size());
|
||||
esp_err_t err = esp_now_send(mac, packet.get_content(), packet.content_size());
|
||||
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGD(TAG, "Sended 0x%012llx (%d.%d) from buffer. Wait for conformation.", packet.peer, packet.sequents(),
|
||||
packet.attempts);
|
||||
ESP_LOGD(TAG, "Sended '%012llx' (%d.%d) from buffer. Wait for conformation.", packet.peer,
|
||||
packet.get_sequents(), packet.attempts);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Sending 0x%012llx (%d.%d) FAILED. B: %d.", packet.peer, packet.sequents(), packet.attempts,
|
||||
ESP_LOGE(TAG, "Sending '%012llx' (%d.%d) FAILED. B: %d.", packet.peer, packet.get_sequents(), packet.attempts,
|
||||
this->send_queue_used());
|
||||
this->unlock();
|
||||
}
|
||||
|
@ -322,23 +323,19 @@ void ESPNowComponent::runner() {
|
|||
}
|
||||
|
||||
void ESPNowComponent::on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) {
|
||||
if ((ESPNowComponent::static_ == nullptr) || !ESPNowComponent::static_->use_sent_check_) {
|
||||
return;
|
||||
}
|
||||
ESPNowPacket packet; // NOLINT
|
||||
uint64_t mac64 = 0;
|
||||
|
||||
memcpy((void *) &mac64, (void *) mac_addr, 6);
|
||||
uint64_t mac64;
|
||||
memcpy((void *) &mac64, mac_addr, 6);
|
||||
if (xQueuePeek(ESPNowComponent::static_->send_queue_, (void *) &packet, 10 / portTICK_PERIOD_MS) == pdTRUE) {
|
||||
if (packet.peer != mac64) {
|
||||
ESP_LOGE(TAG, " Invalid mac address. Expected: 0x%012llx (%d.%d) got: 0x%012llx", packet.peer, packet.sequents(),
|
||||
packet.attempts, mac64);
|
||||
if (!packet.is_peer(mac_addr)) {
|
||||
ESP_LOGE(TAG, " Invalid mac address. Expected: '%012llx' (%d.%d) got: '%012llx'", packet.peer,
|
||||
packet.get_sequents(), packet.attempts, mac64);
|
||||
return;
|
||||
} else if (status == ESP_OK) {
|
||||
ESP_LOGV(TAG, "Confirm packet sent 0x%012llx (%d.%d)", packet.peer, packet.sequents(), packet.attempts);
|
||||
xQueueReceive(ESPNowComponent::static_->send_queue_, (void *) &packet, 10 / portTICK_PERIOD_MS);
|
||||
} else if (status != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Sent packet failed for '%012llx' (%d.%d)", packet.peer, packet.get_sequents(), packet.attempts);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Sent packet failed for 0x%012llx (%d.%d)", packet.peer, packet.sequents(), packet.attempts);
|
||||
ESP_LOGV(TAG, "Confirm packet sent '%012llx' (%d.%d)", packet.peer, packet.get_sequents(), packet.attempts);
|
||||
xQueueReceive(ESPNowComponent::static_->send_queue_, (void *) &packet, 10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
ESPNowComponent::static_->call_on_sent_(packet, status == ESP_OK);
|
||||
ESPNowComponent::static_->unlock();
|
||||
|
@ -349,10 +346,7 @@ void ESPNowComponent::on_data_sent(const uint8_t *mac_addr, esp_now_send_status_
|
|||
|
||||
bool ESPNowProtocol::send(uint64_t peer, const uint8_t *data, uint8_t len) {
|
||||
ESPNowPacket packet(peer, data, len, this->get_protocol_component_id()); // NOLINT
|
||||
packet.sequents(this->get_next_sequents());
|
||||
ESP_LOGV(TAG, "Created packet to Send for 0x%12llx (%d.%d) directly.", packet.peer, packet.sequents(),
|
||||
packet.attempts);
|
||||
|
||||
packet.set_sequents(this->get_next_sequents());
|
||||
return this->parent_->send(packet);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/bytebuffer.h"
|
||||
|
||||
#include "esphome/core/log.h"
|
||||
#include <esp_now.h>
|
||||
|
||||
#include <array>
|
||||
|
@ -21,22 +21,19 @@ namespace espnow {
|
|||
|
||||
static const uint64_t ESPNOW_BROADCAST_ADDR = 0xFFFFFFFFFFFF;
|
||||
|
||||
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_CONTENT = 0x08;
|
||||
|
||||
static const uint8_t MAX_ESPNOW_DATA_SIZE = 241;
|
||||
|
||||
static const uint8_t MAX_NUMBER_OF_RETRYS = 5;
|
||||
static const uint8_t TRANSPORT_HEADER[] = {'N', '0', 'w'};
|
||||
static const uint32_t ESPNOW_MAIN_PROTOCOL_ID = 0x447453; // = StD
|
||||
|
||||
static const uint32_t TRANSPORT_HEADER = 0xC19983;
|
||||
static const uint32_t ESPNOW_MAIN_PROTOCOL_ID = 0x11CFAF;
|
||||
static const uint8_t ESPNOW_COMMAND_ACK = 0x06;
|
||||
static const uint8_t ESPNOW_COMMAND_NAK = 0x15;
|
||||
static const uint8_t ESPNOW_COMMAND_RESEND = 0x05;
|
||||
|
||||
struct ESPNowPacket {
|
||||
uint64_t peer{0};
|
||||
uint8_t rssi{0};
|
||||
uint8_t attempts{0};
|
||||
int8_t attempts{0};
|
||||
bool is_broadcast{false};
|
||||
uint32_t timestamp{0};
|
||||
uint8_t size{0};
|
||||
|
@ -51,46 +48,58 @@ struct ESPNowPacket {
|
|||
|
||||
inline ESPNowPacket() ESPHOME_ALWAYS_INLINE {}
|
||||
// Create packet to be send.
|
||||
inline ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size, uint32_t protocol) ESPHOME_ALWAYS_INLINE {
|
||||
inline ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size, uint32_t protocol,
|
||||
uint8_t command = 0) ESPHOME_ALWAYS_INLINE {
|
||||
assert(size <= MAX_ESPNOW_DATA_SIZE);
|
||||
if (peer == 0) {
|
||||
peer = ESPNOW_BROADCAST_ADDR;
|
||||
}
|
||||
|
||||
this->set_peer(peer);
|
||||
this->peer = peer;
|
||||
|
||||
this->is_broadcast =
|
||||
(std::memcmp((const void *) this->peer_as_bytes(), (const void *) &ESPNOW_BROADCAST_ADDR, 6) == 0);
|
||||
this->protocol(protocol);
|
||||
this->set_protocol(protocol);
|
||||
if (command != 0) {
|
||||
this->set_command(command);
|
||||
}
|
||||
this->size = size;
|
||||
std::memcpy(this->payload_as_bytes(), data, size);
|
||||
std::memcpy(this->get_payload(), data, size);
|
||||
}
|
||||
// Load received packet's.
|
||||
ESPNowPacket(uint64_t peer, const uint8_t *data, uint8_t size) ESPHOME_ALWAYS_INLINE {
|
||||
ESPNowPacket(const uint8_t *peer, const uint8_t *data, uint8_t size) ESPHOME_ALWAYS_INLINE {
|
||||
this->set_peer(peer);
|
||||
std::memcpy(this->content_as_bytes(), data, size);
|
||||
std::memcpy(this->get_content(), data, size);
|
||||
this->size = size - this->prefix_size();
|
||||
}
|
||||
|
||||
inline uint8_t *peer_as_bytes() const { return (uint8_t *) &(this->peer); }
|
||||
inline void set_peer(uint64_t peer) ESPHOME_ALWAYS_INLINE {
|
||||
if (peer == 0) {
|
||||
this->peer = ESPNOW_BROADCAST_ADDR;
|
||||
} else {
|
||||
this->peer = peer;
|
||||
inline uint8_t *get_peer() const { return (uint8_t *) &(this->peer); }
|
||||
inline void set_peer(const uint8_t *peer) ESPHOME_ALWAYS_INLINE {
|
||||
if (*peer == 0) {
|
||||
peer = (uint8_t *) &ESPNOW_BROADCAST_ADDR;
|
||||
}
|
||||
memcpy((void *) this->get_peer(), (const void *) peer, 6);
|
||||
};
|
||||
inline bool is_peer(const uint8_t *peer) const { return memcmp(peer, this->get_peer(), 6) == 0; }
|
||||
|
||||
uint8_t prefix_size() const { return sizeof((*this).content.prefix); }
|
||||
uint8_t prefix_size() const { return sizeof(this->content.prefix); }
|
||||
|
||||
uint8_t content_size() const { return ((*this).prefix_size() + (*this).size); }
|
||||
uint8_t content_size() const { return (this->prefix_size() + this->size); }
|
||||
|
||||
inline uint32_t protocol() const { return this->content.prefix.protocol; }
|
||||
inline void protocol(uint32_t protocol) ESPHOME_ALWAYS_INLINE { this->content.prefix.protocol = protocol; }
|
||||
inline uint32_t get_protocol() const { return this->content.prefix.protocol & 0x00FFFFFF; }
|
||||
inline void set_protocol(uint32_t protocol) {
|
||||
this->content.prefix.protocol = (this->content.prefix.protocol & 0xFF000000) + (protocol & 0x00FFFFFF);
|
||||
}
|
||||
|
||||
uint8_t sequents() const { return (*this).content.prefix.sequents; }
|
||||
inline void sequents(uint8_t sequents) ESPHOME_ALWAYS_INLINE { this->content.prefix.sequents = sequents; }
|
||||
inline uint8_t get_command() const { return this->content.prefix.protocol >> 24; }
|
||||
inline void set_command(uint32_t command) ESPHOME_ALWAYS_INLINE {
|
||||
this->content.prefix.protocol = (this->content.prefix.protocol & 0x00FFFFFF) + (command << 24);
|
||||
}
|
||||
|
||||
inline uint8_t *content_as_bytes() const { return (uint8_t *) &(this->content); }
|
||||
inline uint8_t *payload_as_bytes() const { return (uint8_t *) &(this->content.payload); }
|
||||
inline uint8_t content_at(uint8_t pos) const {
|
||||
uint8_t get_sequents() const { return this->content.prefix.sequents; }
|
||||
inline void set_sequents(uint8_t sequents) ESPHOME_ALWAYS_INLINE { this->content.prefix.sequents = sequents; }
|
||||
|
||||
inline uint8_t *get_content() const { return (uint8_t *) &(this->content); }
|
||||
inline uint8_t *get_payload() const { return (uint8_t *) &(this->content.payload); }
|
||||
inline uint8_t get_byte_at(uint8_t pos) const {
|
||||
assert(pos < this->size);
|
||||
return *(((uint8_t *) &this->content) + pos);
|
||||
}
|
||||
|
@ -98,9 +107,14 @@ struct ESPNowPacket {
|
|||
inline void retry() ESPHOME_ALWAYS_INLINE { attempts++; }
|
||||
|
||||
inline bool is_valid() const {
|
||||
// bool valid = (memcmp((const void *) this->content_as_bytes(), (const void *) &TRANSPORT_HEADER, 3) == 0);
|
||||
// valid &= (this->protocol() != 0);
|
||||
return true; // valid;
|
||||
bool valid = (memcmp((const void *) this->get_content(), (const void *) &TRANSPORT_HEADER, 3) == 0);
|
||||
valid &= (this->get_protocol() != 0);
|
||||
return valid;
|
||||
}
|
||||
|
||||
protected:
|
||||
static uint32_t protocol_(uint8_t *protocol) {
|
||||
return (*(protocol + 2) << 0) + (*(protocol + 1) << 8) + (*(protocol + 0) << 16);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -181,6 +195,11 @@ class ESPNowComponent : public Component {
|
|||
void set_wifi_channel(uint8_t channel) { this->wifi_channel_ = channel; }
|
||||
void set_auto_add_peer(bool value) { this->auto_add_peer_ = value; }
|
||||
void set_use_sent_check(bool value) { this->use_sent_check_ = value; }
|
||||
void set_convermation_timeout(uint32_t timeout) {
|
||||
this->conformation_timeout_ = timeout;
|
||||
ESP_LOGD("ESPNOW", "%d", timeout);
|
||||
}
|
||||
void set_retries(uint8_t value) { this->retries_ = value; }
|
||||
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
|
@ -214,29 +233,27 @@ class ESPNowComponent : public Component {
|
|||
bool validate_channel_(uint8_t channel);
|
||||
ESPNowProtocol *get_protocol_component_(uint32_t protocol);
|
||||
|
||||
uint64_t own_peer_address_{0};
|
||||
uint8_t wifi_channel_{0};
|
||||
|
||||
uint32_t conformation_timeout_{5000};
|
||||
uint8_t retries_{5};
|
||||
|
||||
bool auto_add_peer_{false};
|
||||
bool use_sent_check_{true};
|
||||
|
||||
bool lock_{false};
|
||||
|
||||
void call_on_receive_(ESPNowPacket packet);
|
||||
void call_on_sent_(ESPNowPacket packet, bool status);
|
||||
void call_on_new_peer_(ESPNowPacket packet);
|
||||
void call_on_receive_(ESPNowPacket &packet);
|
||||
void call_on_sent_(ESPNowPacket &packet, bool status);
|
||||
void call_on_new_peer_(ESPNowPacket &packet);
|
||||
|
||||
QueueHandle_t receive_queue_{};
|
||||
QueueHandle_t send_queue_{};
|
||||
|
||||
std::map<uint32_t, ESPNowProtocol *> protocols_{};
|
||||
std::vector<uint64_t> peers_{};
|
||||
uint64_t own_peer_address_{0};
|
||||
ESPNowDefaultProtocol *default_protocol_{nullptr};
|
||||
|
||||
TaskHandle_t espnow_task_handle_{nullptr};
|
||||
bool task_running_{false};
|
||||
|
||||
uint32_t conformation_timeout_{5000};
|
||||
|
||||
static ESPNowComponent *static_; // NOLINT
|
||||
};
|
||||
|
||||
|
|
|
@ -38,9 +38,8 @@ espnow:
|
|||
on_receive:
|
||||
- logger.log:
|
||||
format: "Received: %s RSSI: %d"
|
||||
args: [packet.payload_as_bytes(), packet.rssi]
|
||||
|
||||
args: [packet.get_payload(), packet.rssi]
|
||||
interval:
|
||||
- interval: 1min
|
||||
- interval: 10sec
|
||||
then:
|
||||
- espnow.send: "hallo everyone"
|
||||
|
|
Loading…
Reference in a new issue