Added ECHO cmd and fixed some timing issues

This commit is contained in:
2026-06-06 17:44:40 +02:00
parent 35ce1476d8
commit ac223ada72
29 changed files with 1182 additions and 152 deletions
+123 -13
View File
@@ -21,7 +21,18 @@ static app_config_t s_config;
static uint8_t s_wifi_channel;
static uint8_t s_own_mac[ESP_NOW_ETH_ALEN];
static SemaphoreHandle_t s_send_done;
static SemaphoreHandle_t s_send_lock;
static bool s_send_cb_ready;
static volatile esp_now_send_status_t s_last_send_status;
static volatile bool s_last_send_ok;
#define ESPNOW_SEND_DONE_TIMEOUT_MS 500u
#define ESPNOW_SEND_MAX_ATTEMPTS 8u
#define ESPNOW_SEND_RETRY_DELAY_MS 10u
#define ESPNOW_NOMEM_RETRY_DELAY_MS 50u
#define ESPNOW_RELIABLE_MAX_ATTEMPTS 24u
#define ESPNOW_RELIABLE_NOMEM_DELAY_MS 50u
static uint8_t network_to_channel(uint8_t network) {
if (network < 1 || network > 13) {
@@ -33,7 +44,8 @@ static uint8_t network_to_channel(uint8_t network) {
static void espnow_send_done_cb(const esp_now_send_info_t *tx_info,
esp_now_send_status_t status) {
(void)tx_info;
(void)status;
s_last_send_status = status;
s_last_send_ok = (status == ESP_NOW_SEND_SUCCESS);
if (s_send_done != NULL) {
xSemaphoreGive(s_send_done);
}
@@ -93,43 +105,140 @@ esp_err_t esp_now_core_ensure_broadcast_peer(void) {
return esp_now_core_ensure_peer(ESPNOW_BCAST);
}
static esp_err_t send_with_backpressure(const uint8_t *dest_mac,
const alox_EspNowMessage *msg,
uint32_t max_attempts,
uint32_t nomem_delay_ms,
uint32_t retry_delay_ms,
bool quiet_retries) {
if (s_send_lock == NULL ||
xSemaphoreTake(s_send_lock, pdMS_TO_TICKS(5000)) != pdTRUE) {
return ESP_ERR_TIMEOUT;
}
uint8_t buf[ESPNOW_PB_MAX_SIZE];
size_t len = 0;
esp_err_t result = ESP_FAIL;
esp_err_t err = esp_now_proto_encode(msg, buf, sizeof(buf), &len);
if (err != ESP_OK) {
ESP_LOGW(TAG, "encode failed");
result = err;
goto out;
}
if (len > ESP_NOW_MAX_DATA_LEN) {
ESP_LOGW(TAG, "encoded len %u > ESP-NOW max %u", (unsigned)len,
(unsigned)ESP_NOW_MAX_DATA_LEN);
result = ESP_ERR_INVALID_SIZE;
goto out;
}
if (esp_now_core_ensure_peer(dest_mac) != ESP_OK) {
result = ESP_FAIL;
goto out;
}
for (uint32_t attempt = 0; attempt < max_attempts; attempt++) {
if (s_send_cb_ready && s_send_done != NULL) {
xSemaphoreTake(s_send_done, 0);
}
s_last_send_ok = false;
err = esp_now_send(dest_mac, buf, len);
if (err != ESP_OK) {
const bool last = (attempt + 1 >= max_attempts);
if (!quiet_retries || last) {
ESP_LOGW(TAG, "send type=%u failed (attempt %lu/%lu): %s",
(unsigned)msg->type, (unsigned long)(attempt + 1),
(unsigned long)max_attempts, esp_err_to_name(err));
}
vTaskDelay(pdMS_TO_TICKS(err == ESP_ERR_ESPNOW_NO_MEM ? nomem_delay_ms
: retry_delay_ms));
continue;
}
if (s_send_cb_ready && s_send_done != NULL) {
if (xSemaphoreTake(s_send_done, pdMS_TO_TICKS(ESPNOW_SEND_DONE_TIMEOUT_MS)) !=
pdTRUE) {
const bool last = (attempt + 1 >= max_attempts);
if (!quiet_retries || last) {
ESP_LOGW(TAG, "send type=%u done timeout (attempt %lu/%lu)",
(unsigned)msg->type, (unsigned long)(attempt + 1),
(unsigned long)max_attempts);
}
vTaskDelay(pdMS_TO_TICKS(retry_delay_ms));
continue;
}
if (!s_last_send_ok) {
const bool last = (attempt + 1 >= max_attempts);
if (!quiet_retries || last) {
ESP_LOGW(TAG, "send type=%u peer status=%d (attempt %lu/%lu)",
(unsigned)msg->type, (int)s_last_send_status,
(unsigned long)(attempt + 1), (unsigned long)max_attempts);
}
vTaskDelay(pdMS_TO_TICKS(retry_delay_ms));
continue;
}
}
result = ESP_OK;
goto out;
}
out:
xSemaphoreGive(s_send_lock);
return result;
}
esp_err_t esp_now_core_send_wait(const uint8_t *dest_mac,
const alox_EspNowMessage *msg) {
return send_with_backpressure(dest_mac, msg, ESPNOW_SEND_MAX_ATTEMPTS,
ESPNOW_NOMEM_RETRY_DELAY_MS,
ESPNOW_SEND_RETRY_DELAY_MS, false);
}
esp_err_t esp_now_core_send_reliable(const uint8_t *dest_mac,
const alox_EspNowMessage *msg) {
return send_with_backpressure(dest_mac, msg, ESPNOW_RELIABLE_MAX_ATTEMPTS,
ESPNOW_RELIABLE_NOMEM_DELAY_MS,
ESPNOW_SEND_RETRY_DELAY_MS, true);
}
esp_err_t esp_now_core_send_fast(const uint8_t *dest_mac,
const alox_EspNowMessage *msg) {
if (s_send_lock == NULL ||
xSemaphoreTake(s_send_lock, pdMS_TO_TICKS(5000)) != pdTRUE) {
return ESP_ERR_TIMEOUT;
}
uint8_t buf[ESPNOW_PB_MAX_SIZE];
size_t len = 0;
esp_err_t err = esp_now_proto_encode(msg, buf, sizeof(buf), &len);
if (err != ESP_OK) {
ESP_LOGW(TAG, "encode failed");
xSemaphoreGive(s_send_lock);
return err;
}
if (len > ESP_NOW_MAX_DATA_LEN) {
ESP_LOGW(TAG, "encoded len %u > ESP-NOW max %u", (unsigned)len,
(unsigned)ESP_NOW_MAX_DATA_LEN);
xSemaphoreGive(s_send_lock);
return ESP_ERR_INVALID_SIZE;
}
if (esp_now_core_ensure_peer(dest_mac) != ESP_OK) {
xSemaphoreGive(s_send_lock);
return ESP_FAIL;
}
if (s_send_cb_ready && s_send_done != NULL) {
xSemaphoreTake(s_send_done, 0);
}
err = esp_now_send(dest_mac, buf, len);
if (err != ESP_OK) {
ESP_LOGW(TAG, "send type=%u failed: %s", (unsigned)msg->type,
esp_err_to_name(err));
return err;
}
if (s_send_cb_ready && s_send_done != NULL) {
if (xSemaphoreTake(s_send_done, pdMS_TO_TICKS(50)) != pdTRUE) {
ESP_LOGW(TAG, "send type=%u done timeout", (unsigned)msg->type);
}
}
xSemaphoreGive(s_send_lock);
return err;
}
@@ -163,7 +272,8 @@ esp_err_t esp_now_core_init_radio(uint8_t channel) {
void esp_now_core_init_send_done(void) {
s_send_done = xSemaphoreCreateBinary();
if (s_send_done != NULL &&
s_send_lock = xSemaphoreCreateMutex();
if (s_send_done != NULL && s_send_lock != NULL &&
esp_now_register_send_cb(espnow_send_done_cb) == ESP_OK) {
s_send_cb_ready = true;
} else {