Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
af7fa204e1 | |||
f4ecd08e45 | |||
7608ba0abf | |||
83cebd5677 | |||
d066c326e3 | |||
39fdb2eb49 | |||
742c807c41 | |||
cd12861e36 | |||
a5117e1485 | |||
10a5837c8f |
22
README.md
22
README.md
@ -3,23 +3,24 @@
|
|||||||
## Tested on
|
## Tested on
|
||||||
|
|
||||||
1. ESP8266 RTOS_SDK v3.4
|
1. ESP8266 RTOS_SDK v3.4
|
||||||
2. ESP32 ESP-IDF v5.2
|
2. ESP32 ESP-IDF v5.4
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
1. The maximum size of transmitted data is up to 250 bytes.
|
1. The maximum size of the transmitted data is up to 250 / 1490 bytes. Please see attention for details.
|
||||||
2. Support of any data types.
|
2. Support of any data types.
|
||||||
3. All nodes are not visible to the network scanner.
|
3. All nodes are not visible to the network scanner.
|
||||||
4. Not required a pre-pairings for data transfer.
|
4. Not required a pre-pairings for data transfer.
|
||||||
5. Broadcast or unicast data transmissions.
|
5. Broadcast or unicast data transmissions.
|
||||||
6. Possibility uses WiFi AP or STA modes at the same time with ESP-NOW.
|
6. Possibility uses WiFi AP or STA modes at the same time with ESP-NOW. Please see attention for details.
|
||||||
|
|
||||||
## Attention
|
## Attention
|
||||||
|
|
||||||
1. For correct operation in ESP-NOW + STA mode, your WiFi router must be set to the same channel as ESP-NOW.
|
1. For correct operation ESP-NOW interface must be the same as the WiFi interface (except in the case of APSTA mode - the ESP-NOW interface can be anything).
|
||||||
2. All devices on the network must have the same WiFi channel.
|
2. For correct operation in ESP-NOW + STA mode, your WiFi router must be set to the same channel as ESP-NOW.
|
||||||
|
3. All devices on the network must have the same WiFi channel.
|
||||||
## [Function description](http://zh-espnow.zh.com.ru)
|
4. For use encrypted messages, use the application layer.
|
||||||
|
5. ESP-NOW supports two versions: v1.0 (RTOS_SDK and ESP-IDF v5.3 and below) and v2.0 (ESP-IDF v5.4 and highter). The maximum packet length supported by v2.0 devices is 1490 bytes, while the maximum packet length supported by v1.0 devices is 250 bytes. The v2.0 devices are capable of receiving packets from both v2.0 and v1.0 devices. In contrast, v1.0 devices can only receive packets from other v1.0 devices. However, v1.0 devices can receive v2.0 packets if the packet length is less than or equal to 250 bytes. For packets exceeding this length, the v1.0 devices will either truncate the data to the first 250 bytes or discard the packet entirely.
|
||||||
|
|
||||||
## Using
|
## Using
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ Sending and receiving messages:
|
|||||||
|
|
||||||
void zh_espnow_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
|
void zh_espnow_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
|
||||||
|
|
||||||
uint8_t target[6] = {0x34, 0x94, 0x54, 0x24, 0xA3, 0x41};
|
uint8_t target[6] = {0xEC, 0x94, 0xCB, 0x87, 0xEC, 0xFC};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -74,8 +75,8 @@ void app_main(void)
|
|||||||
esp_wifi_init(&wifi_init_config);
|
esp_wifi_init(&wifi_init_config);
|
||||||
esp_wifi_set_mode(WIFI_MODE_STA);
|
esp_wifi_set_mode(WIFI_MODE_STA);
|
||||||
esp_wifi_start();
|
esp_wifi_start();
|
||||||
zh_espnow_init_config_t zh_espnow_init_config = ZH_ESPNOW_INIT_CONFIG_DEFAULT();
|
zh_espnow_init_config_t espnow_init_config = ZH_ESPNOW_INIT_CONFIG_DEFAULT();
|
||||||
zh_espnow_init(&zh_espnow_init_config);
|
zh_espnow_init(&espnow_init_config);
|
||||||
#ifdef CONFIG_IDF_TARGET_ESP8266
|
#ifdef CONFIG_IDF_TARGET_ESP8266
|
||||||
esp_event_handler_register(ZH_ESPNOW, ESP_EVENT_ANY_ID, &zh_espnow_event_handler, NULL);
|
esp_event_handler_register(ZH_ESPNOW, ESP_EVENT_ANY_ID, &zh_espnow_event_handler, NULL);
|
||||||
#else
|
#else
|
||||||
@ -85,6 +86,7 @@ void app_main(void)
|
|||||||
strcpy(send_message.char_value, "THIS IS A CHAR");
|
strcpy(send_message.char_value, "THIS IS A CHAR");
|
||||||
send_message.float_value = 1.234;
|
send_message.float_value = 1.234;
|
||||||
send_message.bool_value = false;
|
send_message.bool_value = false;
|
||||||
|
printf("Used ESP-NOW version %d.\n", zh_espnow_get_version());
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
send_message.int_value = esp_random();
|
send_message.int_value = esp_random();
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
/**
|
|
||||||
* @file
|
|
||||||
* Header file for the zh_espnow component.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
@ -15,93 +9,57 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Unique identifier of ESP-NOW interface events base. Used when registering the event handler.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define ESP_EVENT_BASE ZH_ESPNOW
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Default values for zh_espnow_init_config_t structure for initial initialization of ESP-NOW interface.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define ZH_ESPNOW_INIT_CONFIG_DEFAULT() \
|
#define ZH_ESPNOW_INIT_CONFIG_DEFAULT() \
|
||||||
{ \
|
{ \
|
||||||
.task_priority = 4, \
|
.task_priority = 10, \
|
||||||
.stack_size = 2048, \
|
.stack_size = 3072, \
|
||||||
.queue_size = 32, \
|
.queue_size = 64, \
|
||||||
.wifi_interface = WIFI_IF_STA, \
|
.wifi_interface = WIFI_IF_STA, \
|
||||||
.wifi_channel = 1, \
|
.wifi_channel = 1, \
|
||||||
.attempts = 3 \
|
.attempts = 3, \
|
||||||
}
|
.battery_mode = false}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
typedef struct // Structure for initial initialization of ESP-NOW interface.
|
||||||
* @brief Structure for initial initialization of ESP-NOW interface.
|
|
||||||
*
|
|
||||||
* @note Before initialize ESP-NOW interface recommend initialize zh_espnow_init_config_t structure with default values.
|
|
||||||
*
|
|
||||||
* @code zh_espnow_init_config_t config = ZH_ESPNOW_INIT_CONFIG_DEFAULT() @endcode
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
{
|
||||||
uint8_t task_priority; ///< Task priority for the ESP-NOW messages processing. @note It is not recommended to set a value less than 4.
|
uint8_t task_priority; // Task priority for the ESP-NOW messages processing. @note It is not recommended to set a value less than 5.
|
||||||
uint16_t stack_size; ///< Stack size for task for the ESP-NOW messages processing. @note The minimum size is 2048 bytes.
|
uint16_t stack_size; // Stack size for task for the ESP-NOW messages processing. @note The minimum size is 2048 bytes.
|
||||||
uint8_t queue_size; ///< Queue size for task for the ESP-NOW messages processing. @note The size depends on the number of messages to be processed. It is not recommended to set the value less than 16.
|
uint8_t queue_size; // Queue size for task for the ESP-NOW messages processing. @note The size depends on the number of messages to be processed. It is not recommended to set the value less than 16.
|
||||||
wifi_interface_t wifi_interface; ///< WiFi interface (STA or AP) used for ESP-NOW operation. @note The MAC address of the device depends on the selected WiFi interface.
|
wifi_interface_t wifi_interface; // WiFi interface (STA or AP) used for ESP-NOW operation. @note The MAC address of the device depends on the selected WiFi interface.
|
||||||
uint8_t wifi_channel; ///< Wi-Fi channel uses to send/receive ESP-NOW data. @note Values from 1 to 14.
|
uint8_t wifi_channel; // Wi-Fi channel uses to send/receive ESP-NOW data. @note Values from 1 to 14.
|
||||||
uint8_t attempts; ///< Maximum number of attempts to send a message. @note It is not recommended to set a value greater than 5.
|
uint8_t attempts; // Maximum number of attempts to send a message. @note It is not recommended to set a value greater than 5.
|
||||||
|
bool battery_mode; // Battery operation mode. If true, the node does not receive messages.
|
||||||
} zh_espnow_init_config_t;
|
} zh_espnow_init_config_t;
|
||||||
|
|
||||||
/// \cond
|
ESP_EVENT_DECLARE_BASE(ZH_ESPNOW);
|
||||||
ESP_EVENT_DECLARE_BASE(ESP_EVENT_BASE);
|
|
||||||
/// \endcond
|
|
||||||
|
|
||||||
/**
|
typedef enum // Enumeration of possible ESP-NOW events.
|
||||||
* @brief Enumeration of possible ESP-NOW events.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
{
|
||||||
ZH_ESPNOW_ON_RECV_EVENT, ///< The event when the ESP-NOW message was received.
|
ZH_ESPNOW_ON_RECV_EVENT, // The event when the ESP-NOW message was received.
|
||||||
ZH_ESPNOW_ON_SEND_EVENT ///< The event when the ESP-NOW message was sent.
|
ZH_ESPNOW_ON_SEND_EVENT // The event when the ESP-NOW message was sent.
|
||||||
} zh_espnow_event_type_t;
|
} zh_espnow_event_type_t;
|
||||||
|
|
||||||
/**
|
typedef enum // Enumeration of possible status of sent ESP-NOW message.
|
||||||
* @brief Enumeration of possible status of sent ESP-NOW message.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
{
|
||||||
ZH_ESPNOW_SEND_SUCCESS, ///< If ESP-NOW message was sent success.
|
ZH_ESPNOW_SEND_SUCCESS, // If ESP-NOW message was sent success.
|
||||||
ZH_ESPNOW_SEND_FAIL ///< If ESP-NOW message was sent fail.
|
ZH_ESPNOW_SEND_FAIL // If ESP-NOW message was sent fail.
|
||||||
} zh_espnow_on_send_event_type_t;
|
} zh_espnow_on_send_event_type_t;
|
||||||
|
|
||||||
/**
|
typedef struct // Structure for sending data to the event handler when an ESP-NOW message was sent. @note Should be used with ZH_ESPNOW event base and ZH_ESPNOW_ON_SEND_EVENT event.
|
||||||
* @brief Structure for sending data to the event handler when an ESP-NOW message was sent.
|
|
||||||
*
|
|
||||||
* @note Should be used with ZH_ESPNOW event base and ZH_ESPNOW_ON_SEND_EVENT event.
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
{
|
||||||
uint8_t mac_addr[6]; ///< MAC address of the device to which the ESP-NOW message was sent. @note
|
uint8_t mac_addr[ESP_NOW_ETH_ALEN]; // MAC address of the device to which the ESP-NOW message was sent.
|
||||||
zh_espnow_on_send_event_type_t status; ///< Status of sent ESP-NOW message. @note
|
zh_espnow_on_send_event_type_t status; // Status of sent ESP-NOW message.
|
||||||
} zh_espnow_event_on_send_t;
|
} zh_espnow_event_on_send_t;
|
||||||
|
|
||||||
/**
|
typedef struct // Structure for sending data to the event handler when an ESP-NOW message was received. @note Should be used with ZH_ESPNOW event base and ZH_ESPNOW_ON_RECV_EVENT event.
|
||||||
* @brief Structure for sending data to the event handler when an ESP-NOW message was received.
|
|
||||||
*
|
|
||||||
* @note Should be used with ZH_ESPNOW event base and ZH_ESPNOW_ON_RECV_EVENT event.
|
|
||||||
*/
|
|
||||||
typedef struct
|
|
||||||
{
|
{
|
||||||
uint8_t mac_addr[6]; ///< MAC address of the sender ESP-NOW message. @note
|
uint8_t mac_addr[ESP_NOW_ETH_ALEN]; // MAC address of the sender ESP-NOW message.
|
||||||
uint8_t *data; ///< Pointer to the data of the received ESP-NOW message. @note
|
uint8_t *data; // Pointer to the data of the received ESP-NOW message.
|
||||||
uint8_t data_len; ///< Size of the received ESP-NOW message. @note
|
uint16_t data_len; // Size of the received ESP-NOW message.
|
||||||
} zh_espnow_event_on_recv_t;
|
} zh_espnow_event_on_recv_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -148,6 +106,14 @@ extern "C"
|
|||||||
*/
|
*/
|
||||||
esp_err_t zh_espnow_send(const uint8_t *target, const uint8_t *data, const uint8_t data_len);
|
esp_err_t zh_espnow_send(const uint8_t *target, const uint8_t *data, const uint8_t data_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get ESP-NOW version.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP-NOW version
|
||||||
|
*/
|
||||||
|
uint8_t zh_espnow_get_version(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -1 +1 @@
|
|||||||
1.0.2
|
1.3.1
|
157
zh_espnow.c
Normal file → Executable file
157
zh_espnow.c
Normal file → Executable file
@ -1,16 +1,8 @@
|
|||||||
/**
|
|
||||||
* @file
|
|
||||||
* The main code of the zh_espnow component.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "zh_espnow.h"
|
#include "zh_espnow.h"
|
||||||
|
|
||||||
/// \cond
|
|
||||||
#define DATA_SEND_SUCCESS BIT0
|
#define DATA_SEND_SUCCESS BIT0
|
||||||
#define DATA_SEND_FAIL BIT1
|
#define DATA_SEND_FAIL BIT1
|
||||||
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
|
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
|
||||||
/// \endcond
|
|
||||||
|
|
||||||
static void _send_cb(const uint8_t *mac_addr, esp_now_send_status_t status);
|
static void _send_cb(const uint8_t *mac_addr, esp_now_send_status_t status);
|
||||||
#if defined CONFIG_IDF_TARGET_ESP8266 || ESP_IDF_VERSION_MAJOR == 4
|
#if defined CONFIG_IDF_TARGET_ESP8266 || ESP_IDF_VERSION_MAJOR == 4
|
||||||
@ -28,8 +20,12 @@ static TaskHandle_t _processing_task_handle = {0};
|
|||||||
static zh_espnow_init_config_t _init_config = {0};
|
static zh_espnow_init_config_t _init_config = {0};
|
||||||
static bool _is_initialized = false;
|
static bool _is_initialized = false;
|
||||||
static uint8_t _attempts = 0;
|
static uint8_t _attempts = 0;
|
||||||
|
#if defined ESP_NOW_MAX_DATA_LEN_V2
|
||||||
|
static uint16_t _max_message_size = ESP_NOW_MAX_DATA_LEN_V2;
|
||||||
|
#else
|
||||||
|
static uint16_t _max_message_size = ESP_NOW_MAX_DATA_LEN;
|
||||||
|
#endif
|
||||||
|
|
||||||
/// \cond
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
enum
|
enum
|
||||||
@ -39,14 +35,13 @@ typedef struct
|
|||||||
} id;
|
} id;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint8_t mac_addr[6];
|
uint8_t mac_addr[ESP_NOW_ETH_ALEN];
|
||||||
uint8_t *payload;
|
uint8_t *payload;
|
||||||
uint8_t payload_len;
|
uint16_t payload_len;
|
||||||
} data;
|
} data;
|
||||||
} _queue_t;
|
} _queue_t;
|
||||||
|
|
||||||
ESP_EVENT_DEFINE_BASE(ZH_ESPNOW);
|
ESP_EVENT_DEFINE_BASE(ZH_ESPNOW);
|
||||||
/// \endcond
|
|
||||||
|
|
||||||
esp_err_t zh_espnow_init(const zh_espnow_init_config_t *config)
|
esp_err_t zh_espnow_init(const zh_espnow_init_config_t *config)
|
||||||
{
|
{
|
||||||
@ -59,24 +54,51 @@ esp_err_t zh_espnow_init(const zh_espnow_init_config_t *config)
|
|||||||
_init_config = *config;
|
_init_config = *config;
|
||||||
if (_init_config.wifi_channel < 1 || _init_config.wifi_channel > 14)
|
if (_init_config.wifi_channel < 1 || _init_config.wifi_channel > 14)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "ESP-NOW initialization fail. WiFi channel.");
|
ESP_LOGE(TAG, "ESP-NOW initialization fail. WiFi channel incorrect.");
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
if (esp_wifi_set_channel(_init_config.wifi_channel, WIFI_SECOND_CHAN_NONE) != ESP_OK)
|
esp_err_t err = esp_wifi_set_channel(_init_config.wifi_channel, WIFI_SECOND_CHAN_NONE);
|
||||||
|
if (err == ESP_ERR_WIFI_NOT_INIT || err == ESP_ERR_WIFI_NOT_STARTED)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "ESP-NOW initialization fail. WiFi not initialized.");
|
ESP_LOGE(TAG, "ESP-NOW initialization fail. WiFi not initialized.");
|
||||||
return ESP_ERR_WIFI_NOT_INIT;
|
return ESP_ERR_WIFI_NOT_INIT;
|
||||||
}
|
}
|
||||||
|
else if (err == ESP_FAIL)
|
||||||
|
{
|
||||||
|
uint8_t prim = 0;
|
||||||
|
wifi_second_chan_t sec = WIFI_SECOND_CHAN_NONE;
|
||||||
|
esp_wifi_get_channel(&prim, &sec);
|
||||||
|
if (prim != _init_config.wifi_channel)
|
||||||
|
{
|
||||||
|
ESP_LOGW(TAG, "ESP-NOW initialization warning. The device is connected to the router. Channel %d will be used for ESP-NOW.", prim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined CONFIG_IDF_TARGET_ESP8266 || CONFIG_IDF_TARGET_ESP32C2
|
||||||
|
esp_wifi_set_protocol(_init_config.wifi_interface, WIFI_PROTOCOL_11B);
|
||||||
|
#else
|
||||||
|
esp_wifi_set_protocol(_init_config.wifi_interface, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_LR);
|
||||||
|
#endif
|
||||||
_event_group_handle = xEventGroupCreate();
|
_event_group_handle = xEventGroupCreate();
|
||||||
_queue_handle = xQueueCreate(_init_config.queue_size, sizeof(_queue_t));
|
_queue_handle = xQueueCreate(_init_config.queue_size, sizeof(_queue_t));
|
||||||
if (esp_now_init() != ESP_OK || esp_now_register_send_cb(_send_cb) != ESP_OK || esp_now_register_recv_cb(_recv_cb) != ESP_OK)
|
if (_init_config.battery_mode == false)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "ESP-NOW initialization fail. Internal error.");
|
if (esp_now_init() != ESP_OK || esp_now_register_send_cb(_send_cb) != ESP_OK || esp_now_register_recv_cb(_recv_cb) != ESP_OK)
|
||||||
return ESP_FAIL;
|
{
|
||||||
|
ESP_LOGE(TAG, "ESP-NOW initialization fail. Internal error at line %d.", __LINE__);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (xTaskCreatePinnedToCore(&_processing, "NULL", _init_config.stack_size, NULL, _init_config.task_priority, &_processing_task_handle, tskNO_AFFINITY) != pdPASS)
|
else
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "ESP-NOW initialization fail. Internal error.");
|
if (esp_now_init() != ESP_OK || esp_now_register_send_cb(_send_cb) != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "ESP-NOW initialization fail. Internal error at line %d.", __LINE__);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xTaskCreatePinnedToCore(&_processing, "zh_espnow_processing", _init_config.stack_size, NULL, _init_config.task_priority, &_processing_task_handle, tskNO_AFFINITY) != pdPASS)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "ESP-NOW initialization fail. Internal error at line %d.", __LINE__);
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
_is_initialized = true;
|
_is_initialized = true;
|
||||||
@ -95,7 +117,10 @@ esp_err_t zh_espnow_deinit(void)
|
|||||||
vEventGroupDelete(_event_group_handle);
|
vEventGroupDelete(_event_group_handle);
|
||||||
vQueueDelete(_queue_handle);
|
vQueueDelete(_queue_handle);
|
||||||
esp_now_unregister_send_cb();
|
esp_now_unregister_send_cb();
|
||||||
esp_now_unregister_recv_cb();
|
if (_init_config.battery_mode == false)
|
||||||
|
{
|
||||||
|
esp_now_unregister_recv_cb();
|
||||||
|
}
|
||||||
esp_now_deinit();
|
esp_now_deinit();
|
||||||
vTaskDelete(_processing_task_handle);
|
vTaskDelete(_processing_task_handle);
|
||||||
_is_initialized = false;
|
_is_initialized = false;
|
||||||
@ -118,7 +143,7 @@ esp_err_t zh_espnow_send(const uint8_t *target, const uint8_t *data, const uint8
|
|||||||
ESP_LOGE(TAG, "Adding outgoing ESP-NOW data to queue fail. ESP-NOW not initialized.");
|
ESP_LOGE(TAG, "Adding outgoing ESP-NOW data to queue fail. ESP-NOW not initialized.");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
if (data == NULL || data_len == 0 || data_len > ESP_NOW_MAX_DATA_LEN)
|
if (data == NULL || data_len == 0 || data_len > _max_message_size)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "Adding outgoing ESP-NOW data to queue fail. Invalid argument.");
|
ESP_LOGE(TAG, "Adding outgoing ESP-NOW data to queue fail. Invalid argument.");
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
@ -128,33 +153,30 @@ esp_err_t zh_espnow_send(const uint8_t *target, const uint8_t *data, const uint8
|
|||||||
ESP_LOGW(TAG, "Adding outgoing ESP-NOW data to queue fail. Queue is almost full.");
|
ESP_LOGW(TAG, "Adding outgoing ESP-NOW data to queue fail. Queue is almost full.");
|
||||||
return ESP_ERR_INVALID_STATE;
|
return ESP_ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
uint8_t broadcast[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
uint8_t broadcast[ESP_NOW_ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||||
_queue_t queue = {0};
|
_queue_t queue = {0};
|
||||||
queue.id = TO_SEND;
|
queue.id = TO_SEND;
|
||||||
if (target == NULL)
|
if (target == NULL)
|
||||||
{
|
{
|
||||||
memcpy(queue.data.mac_addr, broadcast, 6);
|
memcpy(queue.data.mac_addr, broadcast, ESP_NOW_ETH_ALEN);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(queue.data.mac_addr, target, 6);
|
memcpy(queue.data.mac_addr, target, ESP_NOW_ETH_ALEN);
|
||||||
}
|
|
||||||
if (data_len / sizeof(void *) == 0)
|
|
||||||
{
|
|
||||||
queue.data.payload = heap_caps_malloc(data_len, MALLOC_CAP_32BIT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
queue.data.payload = heap_caps_malloc(data_len, MALLOC_CAP_8BIT);
|
|
||||||
}
|
}
|
||||||
|
queue.data.payload = heap_caps_calloc(1, data_len, MALLOC_CAP_8BIT);
|
||||||
if (queue.data.payload == NULL)
|
if (queue.data.payload == NULL)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "Adding outgoing ESP-NOW data to queue fail. Memory allocation fail or no free memory in the heap.");
|
ESP_LOGE(TAG, "Adding outgoing ESP-NOW data to queue fail. Memory allocation fail or no free memory in the heap.");
|
||||||
return ESP_ERR_NO_MEM;
|
return ESP_ERR_NO_MEM;
|
||||||
}
|
}
|
||||||
memset(queue.data.payload, 0, data_len);
|
|
||||||
memcpy(queue.data.payload, data, data_len);
|
memcpy(queue.data.payload, data, data_len);
|
||||||
queue.data.payload_len = data_len;
|
queue.data.payload_len = data_len;
|
||||||
|
if (xQueueSend(_queue_handle, &queue, portTICK_PERIOD_MS) != pdTRUE)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "ESP-NOW message processing task internal error at line %d.", __LINE__);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
if (target == NULL)
|
if (target == NULL)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Adding outgoing ESP-NOW data to MAC FF:FF:FF:FF:FF:FF to queue success.");
|
ESP_LOGI(TAG, "Adding outgoing ESP-NOW data to MAC FF:FF:FF:FF:FF:FF to queue success.");
|
||||||
@ -163,15 +185,10 @@ esp_err_t zh_espnow_send(const uint8_t *target, const uint8_t *data, const uint8
|
|||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Adding outgoing ESP-NOW data to MAC %02X:%02X:%02X:%02X:%02X:%02X to queue success.", MAC2STR(target));
|
ESP_LOGI(TAG, "Adding outgoing ESP-NOW data to MAC %02X:%02X:%02X:%02X:%02X:%02X to queue success.", MAC2STR(target));
|
||||||
}
|
}
|
||||||
if (xQueueSend(_queue_handle, &queue, portTICK_PERIOD_MS) != pdTRUE)
|
|
||||||
{
|
|
||||||
ESP_LOGE(TAG, "ESP-NOW message processing task internal error at line %d.", __LINE__);
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _send_cb(const uint8_t *mac_addr, esp_now_send_status_t status)
|
static void IRAM_ATTR _send_cb(const uint8_t *mac_addr, esp_now_send_status_t status)
|
||||||
{
|
{
|
||||||
if (status == ESP_NOW_SEND_SUCCESS)
|
if (status == ESP_NOW_SEND_SUCCESS)
|
||||||
{
|
{
|
||||||
@ -184,9 +201,9 @@ static void _send_cb(const uint8_t *mac_addr, esp_now_send_status_t status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined CONFIG_IDF_TARGET_ESP8266 || ESP_IDF_VERSION_MAJOR == 4
|
#if defined CONFIG_IDF_TARGET_ESP8266 || ESP_IDF_VERSION_MAJOR == 4
|
||||||
static void _recv_cb(const uint8_t *mac_addr, const uint8_t *data, int data_len)
|
static void IRAM_ATTR _recv_cb(const uint8_t *mac_addr, const uint8_t *data, int data_len)
|
||||||
#else
|
#else
|
||||||
static void _recv_cb(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len)
|
static void IRAM_ATTR _recv_cb(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#if defined CONFIG_IDF_TARGET_ESP8266 || ESP_IDF_VERSION_MAJOR == 4
|
#if defined CONFIG_IDF_TARGET_ESP8266 || ESP_IDF_VERSION_MAJOR == 4
|
||||||
@ -202,38 +219,31 @@ static void _recv_cb(const esp_now_recv_info_t *esp_now_info, const uint8_t *dat
|
|||||||
_queue_t queue = {0};
|
_queue_t queue = {0};
|
||||||
queue.id = ON_RECV;
|
queue.id = ON_RECV;
|
||||||
#if defined CONFIG_IDF_TARGET_ESP8266 || ESP_IDF_VERSION_MAJOR == 4
|
#if defined CONFIG_IDF_TARGET_ESP8266 || ESP_IDF_VERSION_MAJOR == 4
|
||||||
memcpy(queue.data.mac_addr, mac_addr, 6);
|
memcpy(queue.data.mac_addr, mac_addr, ESP_NOW_ETH_ALEN);
|
||||||
#else
|
#else
|
||||||
memcpy(queue.data.mac_addr, esp_now_info->src_addr, 6);
|
memcpy(queue.data.mac_addr, esp_now_info->src_addr, ESP_NOW_ETH_ALEN);
|
||||||
#endif
|
#endif
|
||||||
if (data_len / sizeof(void *) == 0)
|
queue.data.payload = heap_caps_calloc(1, data_len, MALLOC_CAP_8BIT);
|
||||||
{
|
|
||||||
queue.data.payload = heap_caps_malloc(data_len, MALLOC_CAP_32BIT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
queue.data.payload = heap_caps_malloc(data_len, MALLOC_CAP_8BIT);
|
|
||||||
}
|
|
||||||
if (queue.data.payload == NULL)
|
if (queue.data.payload == NULL)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "Adding incoming ESP-NOW data to queue fail. Memory allocation fail or no free memory in the heap.");
|
ESP_LOGE(TAG, "Adding incoming ESP-NOW data to queue fail. Memory allocation fail or no free memory in the heap.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memset(queue.data.payload, 0, data_len);
|
|
||||||
memcpy(queue.data.payload, data, data_len);
|
memcpy(queue.data.payload, data, data_len);
|
||||||
queue.data.payload_len = data_len;
|
queue.data.payload_len = data_len;
|
||||||
|
if (xQueueSend(_queue_handle, &queue, portTICK_PERIOD_MS) != pdTRUE)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "ESP-NOW message processing task internal error at line %d.", __LINE__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
#if defined CONFIG_IDF_TARGET_ESP8266 || ESP_IDF_VERSION_MAJOR == 4
|
#if defined CONFIG_IDF_TARGET_ESP8266 || ESP_IDF_VERSION_MAJOR == 4
|
||||||
ESP_LOGI(TAG, "Adding incoming ESP-NOW data from MAC %02X:%02X:%02X:%02X:%02X:%02X to queue success.", MAC2STR(mac_addr));
|
ESP_LOGI(TAG, "Adding incoming ESP-NOW data from MAC %02X:%02X:%02X:%02X:%02X:%02X to queue success.", MAC2STR(mac_addr));
|
||||||
#else
|
#else
|
||||||
ESP_LOGI(TAG, "Adding incoming ESP-NOW data from MAC %02X:%02X:%02X:%02X:%02X:%02X to queue success.", MAC2STR(esp_now_info->src_addr));
|
ESP_LOGI(TAG, "Adding incoming ESP-NOW data from MAC %02X:%02X:%02X:%02X:%02X:%02X to queue success.", MAC2STR(esp_now_info->src_addr));
|
||||||
#endif
|
#endif
|
||||||
if (xQueueSend(_queue_handle, &queue, portTICK_PERIOD_MS) != pdTRUE)
|
|
||||||
{
|
|
||||||
ESP_LOGE(TAG, "ESP-NOW message processing task internal error at line %d.", __LINE__);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _processing(void *pvParameter)
|
static void IRAM_ATTR _processing(void *pvParameter)
|
||||||
{
|
{
|
||||||
_queue_t queue = {0};
|
_queue_t queue = {0};
|
||||||
while (xQueueReceive(_queue_handle, &queue, portMAX_DELAY) == pdTRUE)
|
while (xQueueReceive(_queue_handle, &queue, portMAX_DELAY) == pdTRUE)
|
||||||
@ -243,16 +253,15 @@ static void _processing(void *pvParameter)
|
|||||||
{
|
{
|
||||||
case TO_SEND:
|
case TO_SEND:
|
||||||
ESP_LOGI(TAG, "Outgoing ESP-NOW data to MAC %02X:%02X:%02X:%02X:%02X:%02X processing begin.", MAC2STR(queue.data.mac_addr));
|
ESP_LOGI(TAG, "Outgoing ESP-NOW data to MAC %02X:%02X:%02X:%02X:%02X:%02X processing begin.", MAC2STR(queue.data.mac_addr));
|
||||||
esp_now_peer_info_t *peer = heap_caps_malloc(sizeof(esp_now_peer_info_t), MALLOC_CAP_8BIT);
|
esp_now_peer_info_t *peer = heap_caps_calloc(1, sizeof(esp_now_peer_info_t), MALLOC_CAP_8BIT);
|
||||||
if (peer == NULL)
|
if (peer == NULL)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "Outgoing ESP-NOW data processing fail. Memory allocation fail or no free memory in the heap.");
|
ESP_LOGE(TAG, "Outgoing ESP-NOW data processing fail. Memory allocation fail or no free memory in the heap.");
|
||||||
heap_caps_free(queue.data.payload);
|
heap_caps_free(queue.data.payload);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memset(peer, 0, sizeof(esp_now_peer_info_t));
|
|
||||||
peer->ifidx = _init_config.wifi_interface;
|
peer->ifidx = _init_config.wifi_interface;
|
||||||
memcpy(peer->peer_addr, queue.data.mac_addr, 6);
|
memcpy(peer->peer_addr, queue.data.mac_addr, ESP_NOW_ETH_ALEN);
|
||||||
err = esp_now_add_peer(peer);
|
err = esp_now_add_peer(peer);
|
||||||
if (err == ESP_ERR_ESPNOW_NO_MEM)
|
if (err == ESP_ERR_ESPNOW_NO_MEM)
|
||||||
{
|
{
|
||||||
@ -268,7 +277,7 @@ static void _processing(void *pvParameter)
|
|||||||
heap_caps_free(peer);
|
heap_caps_free(peer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
zh_espnow_event_on_send_t *on_send = heap_caps_malloc(sizeof(zh_espnow_event_on_send_t), MALLOC_CAP_8BIT);
|
zh_espnow_event_on_send_t *on_send = heap_caps_calloc(1, sizeof(zh_espnow_event_on_send_t), MALLOC_CAP_8BIT);
|
||||||
if (on_send == NULL)
|
if (on_send == NULL)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "Outgoing ESP-NOW data processing fail. Memory allocation fail or no free memory in the heap.");
|
ESP_LOGE(TAG, "Outgoing ESP-NOW data processing fail. Memory allocation fail or no free memory in the heap.");
|
||||||
@ -276,8 +285,7 @@ static void _processing(void *pvParameter)
|
|||||||
heap_caps_free(peer);
|
heap_caps_free(peer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memset(on_send, 0, sizeof(zh_espnow_event_on_send_t));
|
memcpy(on_send->mac_addr, queue.data.mac_addr, ESP_NOW_ETH_ALEN);
|
||||||
memcpy(on_send->mac_addr, queue.data.mac_addr, 6);
|
|
||||||
SEND:
|
SEND:
|
||||||
++_attempts;
|
++_attempts;
|
||||||
err = esp_now_send(queue.data.mac_addr, queue.data.payload, queue.data.payload_len);
|
err = esp_now_send(queue.data.mac_addr, queue.data.payload, queue.data.payload_len);
|
||||||
@ -292,7 +300,7 @@ static void _processing(void *pvParameter)
|
|||||||
}
|
}
|
||||||
else if (err != ESP_OK)
|
else if (err != ESP_OK)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "Sending ESP-NOW data fail. Internal error.");
|
ESP_LOGE(TAG, "Sending ESP-NOW data fail. Internal error at line %d.", __LINE__);
|
||||||
heap_caps_free(queue.data.payload);
|
heap_caps_free(queue.data.payload);
|
||||||
heap_caps_free(peer);
|
heap_caps_free(peer);
|
||||||
heap_caps_free(on_send);
|
heap_caps_free(on_send);
|
||||||
@ -306,7 +314,7 @@ static void _processing(void *pvParameter)
|
|||||||
EventBits_t bit = xEventGroupWaitBits(_event_group_handle, DATA_SEND_SUCCESS | DATA_SEND_FAIL, pdTRUE, pdFALSE, 50 / portTICK_PERIOD_MS);
|
EventBits_t bit = xEventGroupWaitBits(_event_group_handle, DATA_SEND_SUCCESS | DATA_SEND_FAIL, pdTRUE, pdFALSE, 50 / portTICK_PERIOD_MS);
|
||||||
if ((bit & DATA_SEND_SUCCESS) != 0)
|
if ((bit & DATA_SEND_SUCCESS) != 0)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Confirmation message received. ESP-NOW message to MAC %02X:%02X:%02X:%02X:%02X:%02X sent success.", MAC2STR(queue.data.mac_addr));
|
ESP_LOGI(TAG, "Confirmation message received. ESP-NOW message to MAC %02X:%02X:%02X:%02X:%02X:%02X sent success after %d attempts.", MAC2STR(queue.data.mac_addr), _attempts);
|
||||||
on_send->status = ZH_ESPNOW_SEND_SUCCESS;
|
on_send->status = ZH_ESPNOW_SEND_SUCCESS;
|
||||||
_attempts = 0;
|
_attempts = 0;
|
||||||
}
|
}
|
||||||
@ -320,11 +328,14 @@ static void _processing(void *pvParameter)
|
|||||||
on_send->status = ZH_ESPNOW_SEND_FAIL;
|
on_send->status = ZH_ESPNOW_SEND_FAIL;
|
||||||
_attempts = 0;
|
_attempts = 0;
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "Outgoing ESP-NOW data to MAC %02X:%02X:%02X:%02X:%02X:%02X processed success.", MAC2STR(queue.data.mac_addr));
|
|
||||||
if (esp_event_post(ZH_ESPNOW, ZH_ESPNOW_ON_SEND_EVENT, on_send, sizeof(zh_espnow_event_on_send_t), portTICK_PERIOD_MS) != ESP_OK)
|
if (esp_event_post(ZH_ESPNOW, ZH_ESPNOW_ON_SEND_EVENT, on_send, sizeof(zh_espnow_event_on_send_t), portTICK_PERIOD_MS) != ESP_OK)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "ESP-NOW message processing task internal error at line %d.", __LINE__);
|
ESP_LOGE(TAG, "ESP-NOW message processing task internal error at line %d.", __LINE__);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Outgoing ESP-NOW data to MAC %02X:%02X:%02X:%02X:%02X:%02X processed success.", MAC2STR(queue.data.mac_addr));
|
||||||
|
}
|
||||||
heap_caps_free(queue.data.payload);
|
heap_caps_free(queue.data.payload);
|
||||||
esp_now_del_peer(peer->peer_addr);
|
esp_now_del_peer(peer->peer_addr);
|
||||||
heap_caps_free(peer);
|
heap_caps_free(peer);
|
||||||
@ -333,15 +344,25 @@ static void _processing(void *pvParameter)
|
|||||||
case ON_RECV:
|
case ON_RECV:
|
||||||
ESP_LOGI(TAG, "Incoming ESP-NOW data from MAC %02X:%02X:%02X:%02X:%02X:%02X processing begin.", MAC2STR(queue.data.mac_addr));
|
ESP_LOGI(TAG, "Incoming ESP-NOW data from MAC %02X:%02X:%02X:%02X:%02X:%02X processing begin.", MAC2STR(queue.data.mac_addr));
|
||||||
zh_espnow_event_on_recv_t *recv_data = (zh_espnow_event_on_recv_t *)&queue.data;
|
zh_espnow_event_on_recv_t *recv_data = (zh_espnow_event_on_recv_t *)&queue.data;
|
||||||
ESP_LOGI(TAG, "Incoming ESP-NOW data from MAC %02X:%02X:%02X:%02X:%02X:%02X processed success.", MAC2STR(queue.data.mac_addr));
|
if (esp_event_post(ZH_ESPNOW, ZH_ESPNOW_ON_RECV_EVENT, recv_data, recv_data->data_len + sizeof(recv_data->mac_addr) + sizeof(uint8_t), portTICK_PERIOD_MS) != ESP_OK)
|
||||||
if (esp_event_post(ZH_ESPNOW, ZH_ESPNOW_ON_RECV_EVENT, recv_data, recv_data->data_len + 7, portTICK_PERIOD_MS) != ESP_OK)
|
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "ESP-NOW message processing task internal error at line %d.", __LINE__);
|
ESP_LOGE(TAG, "ESP-NOW message processing task internal error at line %d.", __LINE__);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Incoming ESP-NOW data from MAC %02X:%02X:%02X:%02X:%02X:%02X processed success.", MAC2STR(queue.data.mac_addr));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t zh_espnow_get_version(void)
|
||||||
|
{
|
||||||
|
uint32_t version = 0;
|
||||||
|
esp_now_get_version(&version);
|
||||||
|
return version;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user