1
0
mirror of https://github.com/esphome/esphome.git synced 2025-02-01 10:40:56 +00:00

add option to modify the wifi_channel per peer

This commit is contained in:
NP v/d Spek 2024-11-24 17:54:32 +01:00
parent f9e86cf93b
commit 4ed30edf3a
4 changed files with 59 additions and 16 deletions

View File

@ -88,6 +88,7 @@ DEFINE_PEER_CONFIG = cv.maybe_simple_value(
{
cv.Optional(CONF_PEER_ID): cv.declare_id(ESPNowPeer),
cv.Required(CONF_MAC_ADDRESS): cv.mac_address,
cv.Optional(CONF_WIFI_CHANNEL): cv.int_range(0, 14),
},
key=CONF_MAC_ADDRESS,
)
@ -96,7 +97,7 @@ DEFINE_PEER_CONFIG = cv.maybe_simple_value(
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(): cv.declare_id(ESPNowComponent),
cv.Optional(CONF_WIFI_CHANNEL, default=0): cv.int_range(0, 14),
cv.Optional(CONF_WIFI_CHANNEL): 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(
@ -141,8 +142,9 @@ async def to_code(config):
cg.add_library("WiFi", None)
cg.add_define("USE_ESPNOW")
if CONF_WIFI_CHANNEL in config:
cg.add(var.set_wifi_channel(config[CONF_WIFI_CHANNEL]))
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_conformation_timeout(config[CONF_CONFORMATION_TIMEOUT]))
@ -152,7 +154,11 @@ async def to_code(config):
mac = espnow_hex(conf.get(CONF_MAC_ADDRESS))
if CONF_PEER_ID in conf:
cg.new_variable(conf[CONF_PEER_ID], mac)
cg.add(var.add_peer(mac))
if CONF_WIFI_CHANNEL in conf:
cg.add(var.add_peer(mac, conf[CONF_WIFI_CHANNEL]))
else:
cg.add(var.add_peer(mac))
for conf in config.get(CONF_ON_SENT, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
@ -276,6 +282,7 @@ async def send_action(config, action_id, template_arg, args):
{
cv.GenerateID(): cv.use_id(ESPNowComponent),
cv.Required(CONF_MAC_ADDRESS): validate_peer,
cv.Optional(CONF_WIFI_CHANNEL): cv.int_range(0, 14),
},
key=CONF_MAC_ADDRESS,
),
@ -308,6 +315,8 @@ async def peer_action(config, action_id, template_arg, args):
if peer_id := config.get(CONF_PEER_ID):
peer = await cg.get_variable(peer_id)
cg.add(var.set_peer_id(peer))
if CONF_WIFI_CHANNEL in config:
cg.add(var.set_wifi_channel(config[CONF_WIFI_CHANNEL]))
await register_peer(var, config, args)

View File

@ -125,7 +125,7 @@ void ESPNowComponent::setup() {
esp_wifi_get_mac(WIFI_IF_STA, (uint8_t *) &this->own_peer_address_);
for (auto id : this->peers_) {
this->add_peer(id);
this->add_peer(id & 0x00FFFFFFFFFFFF, (int8_t) id >> (64 - 8));
}
this->send_queue_ = xQueueCreate(SEND_BUFFER_SIZE, sizeof(ESPNowPacket));
@ -184,7 +184,12 @@ void ESPNowComponent::espnow_task(void *param) {
packet.retry();
packet.timestamp = millis();
esp_err_t err = esp_now_send(packet.get_peer(), packet.get_content(), packet.content_size());
esp_err_t err;
if (packet.get_peer() == 0) {
err = esp_now_send(nullptr, packet.get_content(), packet.content_size());
} else {
err = esp_now_send(packet.get_peer(), packet.get_content(), packet.content_size());
}
if (err == ESP_OK) {
ESP_LOGD(TAG, "Sended '%s' (%d.%d) from buffer. Wait for conformation.", packet.get_peer_code().c_str(),
@ -200,21 +205,32 @@ void ESPNowComponent::espnow_task(void *param) {
}
}
esp_err_t ESPNowComponent::add_peer(uint64_t peer) {
void ESPNowComponent::set_wifi_channel(uint8_t channel) {
if (this->is_ready() && (this->wifi_channel_ == channel)) {
ESPNowPacket packet(ESPNOW_MASS_SEND_ADDR, &channel, 1, ESPNOW_MAIN_PROTOCOL_ID, 251);
}
this->wifi_channel_ = channel;
}
esp_err_t ESPNowComponent::add_peer(uint64_t peer, int8_t channel) {
esp_err_t result = ESP_OK;
int8_t old_channel = this->wifi_channel_;
esp_now_peer_info_t peer_info = {};
if (!this->is_ready()) {
this->peers_.push_back(peer);
this->peers_.push_back((peer & 0x00FFFFFFFFFFFF) + (channel << (64 - 8)));
return result;
} else {
if (esp_now_is_peer_exist((uint8_t *) &peer)) {
esp_now_get_peer((const uint8_t *) &peer, &peer_info);
old_channel = peer_info.channel;
result = esp_now_del_peer((uint8_t *) &peer);
if (result != ESP_OK)
return result;
}
esp_now_peer_info_t peer_info = {};
memset(&peer_info, 0, sizeof(esp_now_peer_info_t));
peer_info.channel = this->wifi_channel_;
peer_info.channel = (channel = -1) ? old_channel : channel;
peer_info.encrypt = false;
memcpy((void *) peer_info.peer_addr, (void *) &peer, 6);
esp_err_t result = esp_now_add_peer(&peer_info);
@ -297,7 +313,12 @@ void ESPNowComponent::call_on_del_peer_(uint64_t peer) {
bool ESPNowComponent::is_paired(uint64_t peer) {
bool result = false;
if (this->pairing_protocol_ != nullptr) {
if (peer == ESPNOW_MASS_SEND_ADDR) {
return true;
} else if (peer == ESPNOW_BROADCAST_ADDR) {
this->add_peer(ESPNOW_BROADCAST_ADDR);
return true;
} else if (this->pairing_protocol_ != nullptr) {
result = this->pairing_protocol_->is_paired(peer);
} else {
result = (esp_now_is_peer_exist((uint8_t *) &peer));
@ -368,7 +389,12 @@ bool ESPNowComponent::send(ESPNowPacket packet) {
xQueueSendToBack(this->send_queue_, (void *) &packet, 10);
return true;
} else {
esp_err_t err = esp_now_send(packet.get_peer(), packet.get_content(), packet.content_size());
esp_err_t err;
if (packet.get_peer() == 0) {
err = esp_now_send(nullptr, packet.get_content(), packet.content_size());
} else {
err = esp_now_send(packet.get_peer(), packet.get_content(), packet.content_size());
}
ESP_LOGV(TAG, "Sending to %s (%d.%d) directly%s.", packet.get_peer_code().c_str(), packet.get_sequents(),
packet.attempts, (err == ESP_OK) ? "" : " FAILED");

View File

@ -23,6 +23,7 @@ namespace esphome {
namespace espnow {
static const uint64_t ESPNOW_BROADCAST_ADDR = 0xFFFFFFFFFFFF;
static const uint64_t ESPNOW_MASS_SEND_ADDR = 0xFFFFFFFFFFFE;
static const uint8_t MAX_ESPNOW_DATA_SIZE = 240;
@ -68,7 +69,7 @@ struct ESPNowPacket {
uint8_t command = 0) ESPHOME_ALWAYS_INLINE {
if (size > MAX_ESPNOW_DATA_SIZE) {
ESP_LOGE("ESPNowPacket", "Payload size is to large. It should be less then %d instead it is %d",
MAX_ESPNOW_DATA_SIZE, size);
MAX_ESPNOW_DATA_SIZE, size); // nolint
return;
}
if (peer == 0ull) {
@ -90,7 +91,7 @@ struct ESPNowPacket {
inline ESPNowPacket(const uint8_t *peer, const uint8_t *data, uint8_t size) ESPHOME_ALWAYS_INLINE {
if (size > MAX_ESPNOW_DATA_SIZE + this->prefix_size()) {
ESP_LOGE("ESPNowPacket", "Received Payload size is to large. It should be less then %d instead it is %d",
MAX_ESPNOW_DATA_SIZE + this->prefix_size(), size);
MAX_ESPNOW_DATA_SIZE + this->prefix_size(), size); // nolint
return;
}
@ -256,7 +257,7 @@ class ESPNowComponent : public Component {
float get_setup_priority() const override { return -100; }
void set_wifi_channel(uint8_t channel) { this->wifi_channel_ = channel; }
void set_wifi_channel(uint8_t 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_conformation_timeout(uint32_t timeout) { this->conformation_timeout_ = timeout; }
@ -278,7 +279,7 @@ class ESPNowComponent : public Component {
protocol->init_protocol();
}
esp_err_t add_peer(uint64_t peer);
esp_err_t add_peer(uint64_t peer, int8_t channel = -1);
esp_err_t del_peer(uint64_t peer);
bool send_queue_empty() { return uxQueueMessagesWaiting(this->send_queue_) == 0; }
@ -343,9 +344,14 @@ template<typename... Ts> class SendAction : public Action<Ts...>, public Parente
template<typename... Ts> class NewPeerAction : public Action<Ts...>, public Parented<ESPNowComponent> {
public:
TEMPLATABLE_VALUE(uint64_t, mac_address);
TEMPLATABLE_VALUE(int8_t, wifi_channel);
void play(Ts... x) override {
uint64_t mac_address = this->mac_address_.value(x...);
parent_->add_peer(mac_address);
if (this->wifi_channel_.has_value()) {
parent_->add_peer(mac_address);
} else {
parent_->add_peer(mac_address, this->wifi_channel_.value(x...));
}
}
};

View File

@ -30,6 +30,8 @@ logger:
espnow:
auto_add_peer: true
predefined_peers:
- mac_address: 11:22:33:44:55:66
on_receive:
- logger.log:
format: "Received: '%s' from '%s' command: %d RSSI: %d"