ESP32(十一) ESPNOW
传输距离(外置天线/笔直的公路)
稳定距离:100 米
极限距离:370 米
广播
本案例同时作为发送端和接受端
发送端:广播数据hello espnow
接收端:接收所有的espnow广播数据
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "espnow.h"
#include "espnow_storage.h"
#include "espnow_utils.h"
#include "esp_mac.h"
#include "event_bus.h"
static const char *TAG = "module_espnow_multi_hop";
#define ESPNOW_TX 1
static void espnow_send_task(void *arg) {
const char *data = "hello espnow";
size_t size = strlen((const char *) data);
espnow_frame_head_t frame_head = {
.retransmit_count = 5,
.broadcast = true,
};
for (;;) {
espnow_send(ESPNOW_DATA_TYPE_DATA, ESPNOW_ADDR_BROADCAST, data, size, &frame_head, pdTICKS_TO_MS(500));
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
static esp_err_t espnow_recv_handle(uint8_t *src_addr, void *data,
size_t size, wifi_pkt_rx_ctrl_t *rx_ctrl) {
ESP_PARAM_CHECK(src_addr);
ESP_PARAM_CHECK(data);
ESP_PARAM_CHECK(size);
ESP_PARAM_CHECK(rx_ctrl);
static uint32_t count = 0;
ESP_LOGI(TAG, "espnow_recv, <%" PRIu32 "> [" MACSTR "][%d][%d][%u]: %.*s",
count++, MAC2STR(src_addr), rx_ctrl->channel, rx_ctrl->rssi, size, size, (char *) data);
uint8_t rssi[1] = {0};
rssi[0] = (uint8_t)(rx_ctrl->rssi*(-1));
ESP_LOGI(TAG, "rx_ctrl->rssi: %d", rx_ctrl->rssi);
ESP_LOGI(TAG, "rssi: %d", rssi[0]);
event_bus_publish(EVENT_ESPNOW_NOTIFY, rssi, 1, 0);
return ESP_OK;
}
void module_espnow_multi_hop_init() {
espnow_config_t espnow_config = ESPNOW_INIT_CONFIG_DEFAULT();
espnow_init(&espnow_config);
#if ESPNOW_TX
xTaskCreate(espnow_send_task, "espnow_send_task", 4096, NULL, 10, NULL);
#endif
espnow_set_config_for_data_type(ESPNOW_DATA_TYPE_DATA, true, espnow_recv_handle);
}
最小Mesh 方案
- 发起者(Leader)广播 Mesh 消息
- 接收者保存发起者 ID 即可入网
- 接收者执行:
- 校验消息发起者 ID 是否属于自己的网络(1. 引入 随机转发延时 (5~50ms),避免节点同时转发导致冲突,在延迟期间如果听到了相同 seq 被其他节点转发,则自己取消转发 2. 当自己经常收到2条以上消息的时候,自己就不执行转发功能)
- 校验 Seq 是否已处理过,避免重复处理(维护一个Seq队列)
- 校验 TTL,限制网络深度
- 符合条件则转发,实现多跳
License:
CC BY 4.0