mirror of
https://github.com/esphome/esphome.git
synced 2025-03-03 17:28:16 +00:00
you can now send multicast messages.
multicast is used for changing channels
This commit is contained in:
parent
3250125e21
commit
32b9be9548
@ -258,6 +258,20 @@ async def register_peer(var, config, args):
|
||||
cv.maybe_simple_value(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(ESPNowComponent),
|
||||
cv.Optional(CONF_MAC_ADDRESS, default=0xFFFFFFFFFFFF): cv.uint64_t,
|
||||
cv.Required(CONF_PAYLOAD): cv.templatable(validate_raw_data),
|
||||
cv.Optional(CONF_COMMAND): cv.templatable(validate_command),
|
||||
},
|
||||
key=CONF_PAYLOAD,
|
||||
),
|
||||
)
|
||||
@automation.register_action(
|
||||
"espnow.multicast",
|
||||
SendAction,
|
||||
cv.maybe_simple_value(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(ESPNowComponent),
|
||||
cv.Optional(CONF_MAC_ADDRESS, default=0xFFFFFFFFFFFE): cv.uint64_t,
|
||||
cv.Required(CONF_PAYLOAD): cv.templatable(validate_raw_data),
|
||||
cv.Optional(CONF_COMMAND): cv.templatable(validate_command),
|
||||
},
|
||||
|
@ -41,8 +41,8 @@ std::string peer_str(uint64_t peer) {
|
||||
return "[Not Set]";
|
||||
if (peer == ESPNOW_BROADCAST_ADDR)
|
||||
return "[Broadcast]";
|
||||
if (peer == ESPNOW_MASS_SEND_ADDR)
|
||||
return "[Mass Send]";
|
||||
if (peer == ESPNOW_MULTICAST_ADDR)
|
||||
return "[Multicast]";
|
||||
uint8_t *ppeer = (uint8_t *) &peer;
|
||||
snprintf(mac, sizeof(mac), "%02X:%02X:%02X:%02X:%02X:%02X", ppeer[0], ppeer[1], ppeer[2], ppeer[3], ppeer[4],
|
||||
ppeer[5]);
|
||||
@ -199,7 +199,7 @@ void ESPNowComponent::loop() {
|
||||
bool ESPNowComponent::can_proceed() {
|
||||
#ifdef USE_WIFI
|
||||
if (wifi::global_wifi_component != nullptr)
|
||||
return wifi::global_wifi_component->is_ready();
|
||||
return wifi::global_wifi_component->is_connected();
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
@ -225,14 +225,13 @@ void ESPNowComponent::espnow_task(void *param) {
|
||||
}
|
||||
if (xQueueReceive(this_espnow->send_queue_, (void *) &packet, (TickType_t) 1) == pdTRUE) {
|
||||
if (packet.attempts > this_espnow->retries_) {
|
||||
ESP_LOGE(TAG, "Dropped '%s' (%d.%d). To many retries.", packet.get_peer_code().c_str(), packet.get_sequents(),
|
||||
ESP_LOGE(TAG, "Dropped %s (%d.%d). To many retries.", packet.get_peer_code().c_str(), packet.get_sequents(),
|
||||
packet.attempts);
|
||||
this_espnow->unlock();
|
||||
continue;
|
||||
} else if (this_espnow->is_locked()) {
|
||||
if (packet.timestamp + this_espnow->conformation_timeout_ < millis()) {
|
||||
ESP_LOGW(TAG, "TimeOut '%s' (%d.%d).", packet.get_peer_code().c_str(), packet.get_sequents(),
|
||||
packet.attempts);
|
||||
ESP_LOGW(TAG, "TimeOut %s (%d.%d).", packet.get_peer_code().c_str(), packet.get_sequents(), packet.attempts);
|
||||
this_espnow->unlock();
|
||||
}
|
||||
} else {
|
||||
@ -241,17 +240,18 @@ void ESPNowComponent::espnow_task(void *param) {
|
||||
packet.timestamp = millis();
|
||||
|
||||
esp_err_t err;
|
||||
if (packet.peer == ESPNOW_MASS_SEND_ADDR) {
|
||||
if (packet.peer == ESPNOW_MULTICAST_ADDR) {
|
||||
this_espnow->start_multi_cast_();
|
||||
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(),
|
||||
ESP_LOGD(TAG, "Sended %s (%d.%d) from buffer. Wait for conformation.", packet.get_peer_code().c_str(),
|
||||
packet.get_sequents(), packet.attempts);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Sending '%s' (%d.%d) FAILED. B: %d.", packet.get_peer_code().c_str(), packet.get_sequents(),
|
||||
ESP_LOGE(TAG, "Sending %s (%d.%d) FAILED. B: %d.", packet.get_peer_code().c_str(), packet.get_sequents(),
|
||||
packet.attempts, this_espnow->send_queue_used());
|
||||
this_espnow->unlock();
|
||||
}
|
||||
@ -263,7 +263,7 @@ void ESPNowComponent::espnow_task(void *param) {
|
||||
|
||||
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);
|
||||
ESPNowPacket packet(ESPNOW_MULTICAST_ADDR, &channel, 1, ESPNOW_MAIN_PROTOCOL_ID, 251);
|
||||
this->send(packet);
|
||||
ESP_LOGD(TAG, "Wifi Channel is changed from %d to %d.", this->wifi_channel_, channel);
|
||||
}
|
||||
@ -380,7 +380,7 @@ void ESPNowComponent::call_on_del_peer_(uint64_t peer) {
|
||||
|
||||
bool ESPNowComponent::is_paired(uint64_t peer) {
|
||||
bool result = false;
|
||||
if (peer == ESPNOW_MASS_SEND_ADDR) {
|
||||
if (peer == ESPNOW_MULTICAST_ADDR) {
|
||||
return true;
|
||||
} else if (peer == ESPNOW_BROADCAST_ADDR) {
|
||||
this->add_peer(ESPNOW_BROADCAST_ADDR);
|
||||
@ -456,6 +456,11 @@ void ESPNowComponent::handle_internal_commands(ESPNowPacket packet) {
|
||||
}
|
||||
}
|
||||
|
||||
void ESPNowComponent::handle_internal_sent(ESPNowPacket packet, bool status) {
|
||||
ESP_LOGW(TAG, "Internal packet sent to %s (%d.%d) %sreceived.", packet.get_peer_code().c_str(), packet.get_sequents(),
|
||||
packet.attempts, status ? "" : "NOT ");
|
||||
}
|
||||
|
||||
bool ESPNowComponent::send(ESPNowPacket packet) {
|
||||
if (packet.peer == this->own_peer_address_) {
|
||||
ESP_LOGE(TAG, "Tried to peer your self.");
|
||||
@ -477,7 +482,7 @@ bool ESPNowComponent::send(ESPNowPacket packet) {
|
||||
return true;
|
||||
} else {
|
||||
esp_err_t err;
|
||||
if (packet.peer == ESPNOW_MASS_SEND_ADDR) {
|
||||
if (packet.peer == ESPNOW_MULTICAST_ADDR) {
|
||||
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());
|
||||
@ -493,11 +498,19 @@ bool ESPNowComponent::send(ESPNowPacket packet) {
|
||||
}
|
||||
|
||||
void ESPNowComponent::on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) {
|
||||
ESPNowComponent *that = ESPNowComponent::static_;
|
||||
bool unlock = true;
|
||||
ESPNowPacket packet; // NOLINT
|
||||
uint64_t peer = 0;
|
||||
memcpy((void *) &peer, mac_addr, 6);
|
||||
if (xQueuePeek(ESPNowComponent::static_->send_queue_, (void *) &packet, 10 / portTICK_PERIOD_MS) == pdTRUE) {
|
||||
if (packet.peer != peer) {
|
||||
if (xQueuePeek(that->send_queue_, (void *) &packet, 10 / portTICK_PERIOD_MS) == pdTRUE) {
|
||||
if (packet.peer == ESPNOW_MULTICAST_ADDR) {
|
||||
packet.peer = peer;
|
||||
auto it = std::find(that->multicast_.begin(), that->multicast_.end(), peer);
|
||||
that->multicast_.erase(it);
|
||||
unlock = that->multicast_.empty();
|
||||
|
||||
} else if (packet.peer != peer) {
|
||||
ESP_LOGE(TAG, " Invalid mac address. Expected: %s (%d.%d); got: %s", packet.get_peer_code().c_str(),
|
||||
packet.get_sequents(), packet.attempts, peer_str(peer).c_str());
|
||||
return;
|
||||
@ -507,10 +520,32 @@ void ESPNowComponent::on_data_sent(const uint8_t *mac_addr, esp_now_send_status_
|
||||
} else {
|
||||
ESP_LOGV(TAG, "Confirm packet sent %s (%d.%d)", packet.get_peer_code().c_str(), 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();
|
||||
if (packet.get_protocol() == ESPNOW_MAIN_PROTOCOL_ID && packet.get_command() > 250) {
|
||||
that->defer([that, packet, status]() { that->handle_internal_sent(packet, status == ESP_OK); });
|
||||
} else if (status == ESP_OK) {
|
||||
that->call_on_sent_(packet, true);
|
||||
}
|
||||
if (unlock) {
|
||||
if (status == ESP_OK) {
|
||||
xQueueReceive(that->send_queue_, (void *) &packet, 10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
that->unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ESPNowComponent::get_channel_for_(uint64_t peer) { return 0; }
|
||||
void ESPNowComponent::update_channel_scan_(ESPNowPacket &packet) {}
|
||||
|
||||
void ESPNowComponent::start_multi_cast_() {
|
||||
esp_now_peer_info_t peer;
|
||||
memset(&peer, 0, sizeof(esp_now_peer_info_t));
|
||||
multicast_.clear();
|
||||
for (esp_err_t e = esp_now_fetch_peer(true, &peer); e == ESP_OK; e = esp_now_fetch_peer(false, &peer)) {
|
||||
uint64_t mac = 0;
|
||||
memcpy((void *) &mac, peer.peer_addr, 6);
|
||||
multicast_.push_back(mac);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,7 +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 uint64_t ESPNOW_MULTICAST_ADDR = 0xFFFFFFFFFFFE;
|
||||
|
||||
static const uint8_t MAX_ESPNOW_DATA_SIZE = 240;
|
||||
|
||||
@ -55,6 +55,8 @@ struct ESPNowPacket {
|
||||
uint8_t rssi{0};
|
||||
int8_t attempts{0};
|
||||
bool is_broadcast{false};
|
||||
bool is_multicast{false};
|
||||
uint8_t scan_start{0};
|
||||
uint32_t timestamp{0};
|
||||
uint8_t size{0};
|
||||
struct {
|
||||
@ -232,6 +234,8 @@ class ESPNowComponent : public Component {
|
||||
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_auto_channel_scan(bool value) { this->auto_channel_scan_ = value; }
|
||||
|
||||
void set_conformation_timeout(uint32_t timeout) { this->conformation_timeout_ = timeout; }
|
||||
void set_retries(uint8_t value) { this->retries_ = value; }
|
||||
void set_pairing_protocol(ESPNowProtocol *pairing_protocol) { this->pairing_protocol_ = pairing_protocol; }
|
||||
@ -269,11 +273,14 @@ class ESPNowComponent : public Component {
|
||||
static void espnow_task(void *params);
|
||||
|
||||
void handle_internal_commands(ESPNowPacket packet);
|
||||
void handle_internal_sent(ESPNowPacket packet, bool status);
|
||||
|
||||
protected:
|
||||
bool validate_channel_(uint8_t channel);
|
||||
|
||||
ESPNowProtocol *get_protocol_(uint32_t protocol);
|
||||
ESPNowProtocol *pairing_protocol_{nullptr};
|
||||
|
||||
uint64_t own_peer_address_{0};
|
||||
uint8_t wifi_channel_{0};
|
||||
uint32_t conformation_timeout_{5000};
|
||||
@ -281,6 +288,7 @@ class ESPNowComponent : public Component {
|
||||
|
||||
bool auto_add_peer_{false};
|
||||
bool use_sent_check_{true};
|
||||
bool auto_channel_scan_{false};
|
||||
|
||||
bool lock_{false};
|
||||
|
||||
@ -292,11 +300,16 @@ class ESPNowComponent : public Component {
|
||||
void call_on_add_peer_(uint64_t peer);
|
||||
void call_on_del_peer_(uint64_t peer);
|
||||
|
||||
uint8_t get_channel_for_(uint64_t peer);
|
||||
void update_channel_scan_(ESPNowPacket &packet);
|
||||
void start_multi_cast_();
|
||||
|
||||
QueueHandle_t receive_queue_{};
|
||||
QueueHandle_t send_queue_{};
|
||||
|
||||
std::map<uint32_t, ESPNowProtocol *> protocols_{};
|
||||
std::map<uint64_t, ESPNowPeer> peers_{};
|
||||
std::vector<uint64_t> multicast_{};
|
||||
|
||||
bool task_running_{false};
|
||||
static ESPNowComponent *static_; // NOLINT
|
||||
|
@ -17,11 +17,18 @@ esphome:
|
||||
logger:
|
||||
level: debug
|
||||
|
||||
#wifi:
|
||||
# fast_connect: true
|
||||
# networks:
|
||||
# - ssid: !secret wifi_ssid
|
||||
# password: !secret wifi_password
|
||||
|
||||
espnow:
|
||||
auto_add_peer: true
|
||||
wifi_channel: 1
|
||||
predefined_peers:
|
||||
- mac_address: E8:6B:EA:23:CD:98
|
||||
wifi_channel: 2
|
||||
on_receive:
|
||||
- logger.log:
|
||||
format: "Received from: %s = '%s' cmd: %d RSSI: %d"
|
||||
@ -34,7 +41,7 @@ espnow:
|
||||
]
|
||||
|
||||
interval:
|
||||
- interval: 10sec
|
||||
- interval: 30sec
|
||||
startup_delay: 20sec
|
||||
then:
|
||||
- espnow.send:
|
||||
|
@ -26,19 +26,26 @@ esphome:
|
||||
|
||||
# To be able to get logs from the device via serial and api.
|
||||
logger:
|
||||
level: debug
|
||||
level: verbose
|
||||
|
||||
globals:
|
||||
- id: hub_address
|
||||
type: uint64_t
|
||||
initial_value: "0x0"
|
||||
restore_value: yes
|
||||
- id: channel
|
||||
type: uint8_t
|
||||
initial_value: "3"
|
||||
restore_value: false
|
||||
|
||||
espnow:
|
||||
auto_add_peer: true
|
||||
wifi_channel: 1
|
||||
wifi_channel: 2
|
||||
predefined_peers:
|
||||
- mac_address: e8:6b:ea:24:22:04
|
||||
wifi_channel: 1
|
||||
- mac_address: e8:6b:ea:24:22:03
|
||||
- mac_address: e8:6b:ea:24:22:02
|
||||
on_receive:
|
||||
- logger.log:
|
||||
format: "Received from: %s = '%s' cmd: %d RSSI: %d"
|
||||
@ -52,13 +59,10 @@ espnow:
|
||||
|
||||
interval:
|
||||
- interval: 30sec
|
||||
startup_delay: 10sec
|
||||
then:
|
||||
- espnow.channel.set: 5
|
||||
- interval: 5sec
|
||||
startup_delay: 10sec
|
||||
then:
|
||||
- espnow.send:
|
||||
mac_address: e8:6b:ea:24:22:04
|
||||
payload: "Test 2."
|
||||
command: 123
|
||||
- espnow.channel.set: !lambda return id(channel);
|
||||
- lambda: |-
|
||||
id(channel) = id(channel)+1;
|
||||
if (id(channel) > 10) {
|
||||
id(channel) = 1;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user