ESP-NOW¶
Overview¶
ESP-NOW is a kind of connectionless WiFi communication protocol which is defined by Espressif. In ESP-NOW, application data is encapsulated in vendor-specific action frame and then transmitted from one WiFi device to another without connection. CTR with CBC-MAC Protocol(CCMP) is used to protect the action frame for security. ESP-NOW is widely used in smart light, remote controlling, sensor, etc.
Frame Format¶
ESP-NOW uses vendor-specific action frame to transmit ESP-NOW data. The format of vendor-specific action frame is as follows:
----------------------------------------------------------------------------------------
| MAC Header | Category Code | Organization Identifier | Vendor Specific Content | FCS |
----------------------------------------------------------------------------------------
1 byte 3 bytes 7~255 bytes
Category Code: The Category field is set to the value(127) indicating the vendor-specific category.
- Organization Identifier: The Organization Identifier contains a unique identifier(0x18fe34) which is the first three bytes
of MAC address applied by Espressif.
Vendor Specific Content: The Vendor Specific Content contains vendor-specific field as follows:
-------------------------------------------------------------------------------
| Element ID | Length | Organization Identifier | Type | Version | Body |
-------------------------------------------------------------------------------
1 byte 1 byte 3 bytes 1 byte 1 byte 0~250 bytes
Element ID: The Element ID field is set to the value(221) indicating the vendor-specific element.
Length: The length is the total length of Organization Identifier, Type, Version and Body.
- Organization Identifier: The Organization Identifier contains a unique identifier(0x18fe34) which is the first three bytes
of MAC address applied by Espressif.
Type: The Type field is set to the value(4) indicating ESP-NOW.
Version: The Version field is set to the version of ESP-NOW.
Body: The Body contains the ESP-NOW data.
As ESP-NOW is connectionless, the MAC header is a little different from that of standard frames. The FromDS and ToDS bits of FrameControl field are both 0. The first address field is set to the destination address. The second address field is set to the source address. The third address field is set to broadcast address(0xff:0xff:0xff:0xff:0xff:0xff).
Security¶
ESP-NOW use CCMP method which can be referenced in IEEE Std. 802.11-2012 to protect the vendor-specific action frame. The WiFi
device maintains a Primary Master Key(PMK) and several Local Master Keys(LMK). The lengths of them are 16 bytes. PMK is used
to encrypt LMK with AES-128 algorithm. Call esp_now_set_pmk()
to set PMK. If PMK is not set, a default PMK will be used.
If LMK of the paired device is set, it will be used to encrypt the vendor-specific action frame with CCMP method. The maximum
number of different LMKs is six. Do not support encrypting multicast vendor-specific action frame.
Initialization and De-initialization¶
Call esp_now_init()
to initialize ESP-NOW and esp_now_deinit()
to de-initialize ESP-NOW. ESP-NOW data must be transmitted
after WiFi is started, so it is recommended to start WiFi before initializing ESP-NOW and stop WiFi after de-initializing ESP-NOW.
When esp_now_deinit()
is called, all of the information of paired devices will be deleted.
Add Paired Device¶
Before sending data to other device, call esp_now_add_peer()
to add it to the paired device list first. The maximum number of
paired devices is twenty. If security is enabled, the LMK must be set. ESP-NOW data can be sent from station or softap interface.
Make sure that the interface is enabled before sending ESP-NOW data. A device with broadcast MAC address must be added before
sending broadcast data. The range of the channel of paired device is from 0 to 14. If the channel is set to 0, data will be sent
on the current channel. Otherwise, the channel must be set as the channel that the local device is on.
Send ESP-NOW Data¶
Call esp_now_send()
to send ESP-NOW data and esp_now_register_send_cb
to register sending callback function. It will return
ESP_NOW_SEND_SUCCESS in sending callback function if the data is received successfully on MAC layer. Otherwise, it will return
ESP_NOW_SEND_FAIL. There are several reasons failing to send ESP-NOW data, for example, the destination device doesn’t exist, the
channels of the devices are not the same, the action frame is lost when transmiting on the air, etc. It is not guaranteed that
application layer can receive the data. If necessary, send back ack data when receiving ESP-NOW data. If receiving ack data timeout
happens, retransmit the ESP-NOW data. A sequence number can also be assigned to ESP-NOW data to drop the duplicated data.
If there is a lot of ESP-NOW data to send, call esp_now_send()
to send less than or equal to 250 bytes of data once a time.
Note that too short interval between sending two ESP-NOW datas may lead to disorder of sending callback function. So, it is
recommended that sending the next ESP-NOW data after the sending callback function of previous sending has returned. The sending
callback function runs from a high-priority WiFi task. So, do not do lengthy operations in the callback function. Instead, post
necessary data to a queue and handle it from a lower priority task.
Receiving ESP-NOW Data¶
Call esp_now_register_recv_cb
to register receiving callback function. When receiving ESP-NOW data, receiving callback function
is called. The receiving callback function also runs from WiFi task. So, do not do lengthy operations in the callback function.
Instead, post necessary data to a queue and handle it from a lower priority task.
API Reference¶
Header File¶
Functions¶
-
esp_err_t
esp_now_init
(void)¶ Initialize ESPNOW function.
- Return
ESP_OK : succeed
ESP_ERR_ESPNOW_INTERNAL : Internal error
-
esp_err_t
esp_now_get_version
(uint32_t *version)¶ Get the version of ESPNOW.
- Return
ESP_OK : succeed
ESP_ERR_ESPNOW_ARG : invalid argument
- Parameters
version
: ESPNOW version
-
esp_err_t
esp_now_register_recv_cb
(esp_now_recv_cb_t cb)¶ Register callback function of receiving ESPNOW data.
- Return
ESP_OK : succeed
ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
ESP_ERR_ESPNOW_INTERNAL : internal error
- Parameters
cb
: callback function of receiving ESPNOW data
-
esp_err_t
esp_now_unregister_recv_cb
(void)¶ Unregister callback function of receiving ESPNOW data.
- Return
ESP_OK : succeed
ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
-
esp_err_t
esp_now_register_send_cb
(esp_now_send_cb_t cb)¶ Register callback function of sending ESPNOW data.
- Return
ESP_OK : succeed
ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
ESP_ERR_ESPNOW_INTERNAL : internal error
- Parameters
cb
: callback function of sending ESPNOW data
-
esp_err_t
esp_now_unregister_send_cb
(void)¶ Unregister callback function of sending ESPNOW data.
- Return
ESP_OK : succeed
ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
-
esp_err_t
esp_now_send
(const uint8_t *peer_addr, const uint8_t *data, size_t len)¶ Send ESPNOW data.
- Attention
1. If peer_addr is not NULL, send data to the peer whose MAC address matches peer_addr
- Attention
2. If peer_addr is NULL, send data to all of the peers that are added to the peer list
- Attention
3. The maximum length of data must be less than ESP_NOW_MAX_DATA_LEN
- Attention
4. The buffer pointed to by data argument does not need to be valid after esp_now_send returns
- Return
ESP_OK : succeed
ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
ESP_ERR_ESPNOW_ARG : invalid argument
ESP_ERR_ESPNOW_INTERNAL : internal error
ESP_ERR_ESPNOW_NO_MEM : out of memory
ESP_ERR_ESPNOW_NOT_FOUND : peer is not found
ESP_ERR_ESPNOW_IF : current WiFi interface doesn’t match that of peer
- Parameters
peer_addr
: peer MAC addressdata
: data to sendlen
: length of data
-
esp_err_t
esp_now_add_peer
(const esp_now_peer_info_t *peer)¶ Add a peer to peer list.
- Return
ESP_OK : succeed
ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
ESP_ERR_ESPNOW_ARG : invalid argument
ESP_ERR_ESPNOW_FULL : peer list is full
ESP_ERR_ESPNOW_NO_MEM : out of memory
ESP_ERR_ESPNOW_EXIST : peer has existed
- Parameters
peer
: peer information
-
esp_err_t
esp_now_del_peer
(const uint8_t *peer_addr)¶ Delete a peer from peer list.
- Return
ESP_OK : succeed
ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
ESP_ERR_ESPNOW_ARG : invalid argument
ESP_ERR_ESPNOW_NOT_FOUND : peer is not found
- Parameters
peer_addr
: peer MAC address
-
esp_err_t
esp_now_mod_peer
(const esp_now_peer_info_t *peer)¶ Modify a peer.
- Return
ESP_OK : succeed
ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
ESP_ERR_ESPNOW_ARG : invalid argument
ESP_ERR_ESPNOW_FULL : peer list is full
- Parameters
peer
: peer information
-
esp_err_t
esp_now_get_peer
(const uint8_t *peer_addr, esp_now_peer_info_t *peer)¶ Get a peer whose MAC address matches peer_addr from peer list.
- Return
ESP_OK : succeed
ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
ESP_ERR_ESPNOW_ARG : invalid argument
ESP_ERR_ESPNOW_NOT_FOUND : peer is not found
- Parameters
peer_addr
: peer MAC addresspeer
: peer information
-
esp_err_t
esp_now_fetch_peer
(bool from_head, esp_now_peer_info_t *peer)¶ Fetch a peer from peer list. Only return the peer which address is unicast, for the multicast/broadcast address, the function will ignore and try to find the next in the peer list.
- Return
ESP_OK : succeed
ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
ESP_ERR_ESPNOW_ARG : invalid argument
ESP_ERR_ESPNOW_NOT_FOUND : peer is not found
- Parameters
from_head
: fetch from head of list or notpeer
: peer information
-
bool
esp_now_is_peer_exist
(const uint8_t *peer_addr)¶ Peer exists or not.
- Return
true : peer exists
false : peer not exists
- Parameters
peer_addr
: peer MAC address
-
esp_err_t
esp_now_get_peer_num
(esp_now_peer_num_t *num)¶ Get the number of peers.
- Return
ESP_OK : succeed
ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
ESP_ERR_ESPNOW_ARG : invalid argument
- Parameters
num
: number of peers
Structures¶
-
struct
esp_now_peer_info
¶ ESPNOW peer information parameters.
Public Members
-
uint8_t
peer_addr
[ESP_NOW_ETH_ALEN
]¶ ESPNOW peer MAC address that is also the MAC address of station or softap
-
uint8_t
lmk
[ESP_NOW_KEY_LEN
]¶ ESPNOW peer local master key that is used to encrypt data
-
uint8_t
channel
¶ Wi-Fi channel that peer uses to send/receive ESPNOW data. If the value is 0, use the current channel which station or softap is on. Otherwise, it must be set as the channel that station or softap is on.
-
wifi_interface_t
ifidx
¶ Wi-Fi interface that peer uses to send/receive ESPNOW data
-
bool
encrypt
¶ ESPNOW data that this peer sends/receives is encrypted or not
-
void *
priv
¶ ESPNOW peer private data
-
uint8_t
-
struct
esp_now_peer_num
¶ Number of ESPNOW peers which exist currently.
Macros¶
-
ESP_ERR_ESPNOW_BASE
¶ ESPNOW error number base.
-
ESP_ERR_ESPNOW_NOT_INIT
¶ ESPNOW is not initialized.
-
ESP_ERR_ESPNOW_ARG
¶ Invalid argument
-
ESP_ERR_ESPNOW_NO_MEM
¶ Out of memory
-
ESP_ERR_ESPNOW_FULL
¶ ESPNOW peer list is full
-
ESP_ERR_ESPNOW_NOT_FOUND
¶ ESPNOW peer is not found
-
ESP_ERR_ESPNOW_INTERNAL
¶ Internal error
-
ESP_ERR_ESPNOW_EXIST
¶ ESPNOW peer has existed
-
ESP_ERR_ESPNOW_IF
¶ Interface error
-
ESP_NOW_ETH_ALEN
¶ Length of ESPNOW peer MAC address
-
ESP_NOW_KEY_LEN
¶ Length of ESPNOW peer local master key
-
ESP_NOW_MAX_TOTAL_PEER_NUM
¶ Maximum number of ESPNOW total peers
-
ESP_NOW_MAX_ENCRYPT_PEER_NUM
¶ Maximum number of ESPNOW encrypted peers
-
ESP_NOW_MAX_DATA_LEN
¶ Maximum length of ESPNOW data which is sent very time
Type Definitions¶
-
typedef struct esp_now_peer_info
esp_now_peer_info_t
¶ ESPNOW peer information parameters.
-
typedef struct esp_now_peer_num
esp_now_peer_num_t
¶ Number of ESPNOW peers which exist currently.
-
typedef void (*
esp_now_recv_cb_t
)(const uint8_t *mac_addr, const uint8_t *data, int data_len)¶ Callback function of receiving ESPNOW data.
- Parameters
mac_addr
: peer MAC addressdata
: received datadata_len
: length of received data
-
typedef void (*
esp_now_send_cb_t
)(const uint8_t *mac_addr, esp_now_send_status_t status)¶ Callback function of sending ESPNOW data.
- Parameters
mac_addr
: peer MAC addressstatus
: status of sending ESPNOW data (succeed or fail)