1 /*
2  * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef __ESP_NOW_H__
8 #define __ESP_NOW_H__
9 
10 #include <stdbool.h>
11 #include "esp_err.h"
12 #include "esp_wifi_types.h"
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 /** \defgroup WiFi_APIs WiFi Related APIs
19   * @brief WiFi APIs
20   */
21 
22 /** @addtogroup WiFi_APIs
23   * @{
24   */
25 
26 /** \defgroup ESPNOW_APIs  ESPNOW APIs
27   * @brief ESP32 ESPNOW APIs
28   *
29   */
30 
31 /** @addtogroup ESPNOW_APIs
32   * @{
33   */
34 
35 #define ESP_ERR_ESPNOW_BASE         (ESP_ERR_WIFI_BASE + 100) /*!< ESPNOW error number base. */
36 #define ESP_ERR_ESPNOW_NOT_INIT     (ESP_ERR_ESPNOW_BASE + 1) /*!< ESPNOW is not initialized. */
37 #define ESP_ERR_ESPNOW_ARG          (ESP_ERR_ESPNOW_BASE + 2) /*!< Invalid argument */
38 #define ESP_ERR_ESPNOW_NO_MEM       (ESP_ERR_ESPNOW_BASE + 3) /*!< Out of memory */
39 #define ESP_ERR_ESPNOW_FULL         (ESP_ERR_ESPNOW_BASE + 4) /*!< ESPNOW peer list is full */
40 #define ESP_ERR_ESPNOW_NOT_FOUND    (ESP_ERR_ESPNOW_BASE + 5) /*!< ESPNOW peer is not found */
41 #define ESP_ERR_ESPNOW_INTERNAL     (ESP_ERR_ESPNOW_BASE + 6) /*!< Internal error */
42 #define ESP_ERR_ESPNOW_EXIST        (ESP_ERR_ESPNOW_BASE + 7) /*!< ESPNOW peer has existed */
43 #define ESP_ERR_ESPNOW_IF           (ESP_ERR_ESPNOW_BASE + 8) /*!< Interface error */
44 
45 #define ESP_NOW_ETH_ALEN             6         /*!< Length of ESPNOW peer MAC address */
46 #define ESP_NOW_KEY_LEN              16        /*!< Length of ESPNOW peer local master key */
47 
48 #define ESP_NOW_MAX_TOTAL_PEER_NUM   20        /*!< Maximum number of ESPNOW total peers */
49 #define ESP_NOW_MAX_ENCRYPT_PEER_NUM 6         /*!< Maximum number of ESPNOW encrypted peers */
50 
51 #define ESP_NOW_MAX_IE_DATA_LEN      250       /**< Maximum data length in a vendor-specific element */
52 #define ESP_NOW_MAX_DATA_LEN  ESP_NOW_MAX_IE_DATA_LEN   /**< Maximum length of data sent in each ESPNOW transmission for v1.0 */
53 
54 /**
55  * @brief Status of sending ESPNOW data .
56  */
57 typedef enum {
58     ESP_NOW_SEND_SUCCESS = 0,       /**< Send ESPNOW data successfully */
59     ESP_NOW_SEND_FAIL,              /**< Send ESPNOW data fail */
60 } esp_now_send_status_t;
61 
62 /**
63  * @brief ESPNOW peer information parameters.
64  */
65 typedef struct esp_now_peer_info {
66     uint8_t peer_addr[ESP_NOW_ETH_ALEN];    /**< ESPNOW peer MAC address that is also the MAC address of station or softap */
67     uint8_t lmk[ESP_NOW_KEY_LEN];           /**< ESPNOW peer local master key that is used to encrypt data */
68     uint8_t channel;                        /**< Wi-Fi channel that peer uses to send/receive ESPNOW data. If the value is 0,
69                                                  use the current channel which station or softap is on. Otherwise, it must be
70                                                  set as the channel that station or softap is on. */
71     wifi_interface_t ifidx;                 /**< Wi-Fi interface that peer uses to send/receive ESPNOW data */
72     bool encrypt;                           /**< ESPNOW data that this peer sends/receives is encrypted or not */
73     void *priv;                             /**< ESPNOW peer private data */
74 } esp_now_peer_info_t;
75 
76 /**
77  * @brief Number of ESPNOW peers which exist currently.
78  */
79 typedef struct esp_now_peer_num {
80     int total_num;                           /**< Total number of ESPNOW peers, maximum value is ESP_NOW_MAX_TOTAL_PEER_NUM */
81     int encrypt_num;                         /**< Number of encrypted ESPNOW peers, maximum value is ESP_NOW_MAX_ENCRYPT_PEER_NUM */
82 } esp_now_peer_num_t;
83 
84 /**
85  * @brief ESPNOW packet information
86  */
87 typedef struct esp_now_recv_info {
88     uint8_t * src_addr;                      /**< Source address of ESPNOW packet */
89     uint8_t * des_addr;                      /**< Destination address of ESPNOW packet */
90     wifi_pkt_rx_ctrl_t * rx_ctrl;            /**< Rx control info of ESPNOW packet */
91 } esp_now_recv_info_t;
92 
93 /**
94  * @brief ESPNOW rate config
95  */
96 typedef wifi_tx_rate_config_t esp_now_rate_config_t;
97 
98 /**
99   * @brief     Callback function of receiving ESPNOW data
100   * @param     esp_now_info received ESPNOW packet information
101   * @param     data received data
102   * @param     data_len length of received data
103   * @attention esp_now_info is a local variable,it can only be used in the callback.
104   */
105 typedef void (*esp_now_recv_cb_t)(const esp_now_recv_info_t * esp_now_info, const uint8_t *data, int data_len);
106 
107 /**
108   * @brief     Callback function of sending ESPNOW data
109   * @param     mac_addr peer MAC address
110   * @param     status status of sending ESPNOW data (succeed or fail)
111   */
112 typedef void (*esp_now_send_cb_t)(const uint8_t *mac_addr, esp_now_send_status_t status);
113 
114 /**
115   * @brief     Initialize ESPNOW function
116   *
117   * @return
118   *          - ESP_OK : succeed
119   *          - ESP_ERR_ESPNOW_INTERNAL : Internal error
120   */
121 esp_err_t esp_now_init(void);
122 
123 /**
124   * @brief     De-initialize ESPNOW function
125   *
126   * @return
127   *          - ESP_OK : succeed
128   */
129 esp_err_t esp_now_deinit(void);
130 
131 /**
132   * @brief     Get the version of ESPNOW. Currently, ESPNOW supports one version: v1.0.
133   *
134   *            The v1.0 devices can receive packets if the packet length is less than or equal to ESP_NOW_MAX_IE_DATA_LEN.
135   *            For packets exceeding this length, the v1.0 devices will discard the packet entirely.
136   *
137   * @param     version  ESPNOW version
138   *
139   * @return
140   *          - ESP_OK : succeed
141   *          - ESP_ERR_ESPNOW_ARG : invalid argument
142   */
143 esp_err_t esp_now_get_version(uint32_t *version);
144 
145 /**
146   * @brief     Register callback function of receiving ESPNOW data
147   *
148   * @param     cb  callback function of receiving ESPNOW data
149   *
150   * @return
151   *          - ESP_OK : succeed
152   *          - ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
153   *          - ESP_ERR_ESPNOW_INTERNAL : internal error
154   */
155 esp_err_t esp_now_register_recv_cb(esp_now_recv_cb_t cb);
156 
157 /**
158   * @brief     Unregister callback function of receiving ESPNOW data
159   *
160   * @return
161   *          - ESP_OK : succeed
162   *          - ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
163   */
164 esp_err_t esp_now_unregister_recv_cb(void);
165 
166 /**
167   * @brief     Register callback function of sending ESPNOW data
168   *
169   * @param     cb  callback function of sending ESPNOW data
170   *
171   * @return
172   *          - ESP_OK : succeed
173   *          - ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
174   *          - ESP_ERR_ESPNOW_INTERNAL : internal error
175   */
176 esp_err_t esp_now_register_send_cb(esp_now_send_cb_t cb);
177 
178 /**
179   * @brief     Unregister callback function of sending ESPNOW data
180   *
181   * @return
182   *          - ESP_OK : succeed
183   *          - ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
184   */
185 esp_err_t esp_now_unregister_send_cb(void);
186 
187 /**
188   * @brief     Send ESPNOW data
189   *
190   * @attention 1. If peer_addr is not NULL, send data to the peer whose MAC address matches peer_addr
191   * @attention 2. If peer_addr is NULL, send data to all of the peers that are added to the peer list
192   * @attention 3. The maximum length of data must be less than ESP_NOW_MAX_DATA_LEN
193   * @attention 4. The buffer pointed to by data argument does not need to be valid after esp_now_send returns
194   *
195   * @param     peer_addr  peer MAC address
196   * @param     data  data to send
197   * @param     len  length of data
198   *
199   * @return
200   *          - ESP_OK : succeed
201   *          - ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
202   *          - ESP_ERR_ESPNOW_ARG : invalid argument
203   *          - ESP_ERR_ESPNOW_INTERNAL : internal error
204   *          - ESP_ERR_ESPNOW_NO_MEM : out of memory, when this happens, you can delay a while before sending the next data
205   *          - ESP_ERR_ESPNOW_NOT_FOUND : peer is not found
206   *          - ESP_ERR_ESPNOW_IF : current WiFi interface doesn't match that of peer
207   */
208 esp_err_t esp_now_send(const uint8_t *peer_addr, const uint8_t *data, size_t len);
209 
210 /**
211   * @brief     Add a peer to peer list
212   *
213   * @param     peer  peer information
214   *
215   * @return
216   *          - ESP_OK : succeed
217   *          - ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
218   *          - ESP_ERR_ESPNOW_ARG : invalid argument
219   *          - ESP_ERR_ESPNOW_FULL : peer list is full
220   *          - ESP_ERR_ESPNOW_NO_MEM : out of memory
221   *          - ESP_ERR_ESPNOW_EXIST : peer has existed
222   */
223 esp_err_t esp_now_add_peer(const esp_now_peer_info_t *peer);
224 
225 /**
226   * @brief     Delete a peer from peer list
227   *
228   * @param     peer_addr  peer MAC address
229   *
230   * @return
231   *          - ESP_OK : succeed
232   *          - ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
233   *          - ESP_ERR_ESPNOW_ARG : invalid argument
234   *          - ESP_ERR_ESPNOW_NOT_FOUND : peer is not found
235   */
236 esp_err_t esp_now_del_peer(const uint8_t *peer_addr);
237 
238 /**
239   * @brief     Modify a peer
240   *
241   * @param     peer  peer information
242   *
243   * @return
244   *          - ESP_OK : succeed
245   *          - ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
246   *          - ESP_ERR_ESPNOW_ARG : invalid argument
247   *          - ESP_ERR_ESPNOW_FULL : peer list is full
248   */
249 esp_err_t esp_now_mod_peer(const esp_now_peer_info_t *peer);
250 
251 /**
252   * @brief      Config ESPNOW rate of specified interface
253   *
254   * @deprecated please use esp_now_set_peer_rate_config() instead.
255   *
256   * @attention  1. This API should be called after esp_wifi_start().
257   * @attention  2. This API only work when not use Wi-Fi 6 and esp_now_set_peer_rate_config() not called.
258   *
259   * @param      ifx  Interface to be configured.
260   * @param      rate Phy rate to be configured.
261   *
262   * @return
263   *    - ESP_OK: succeed
264   *    - others: failed
265   */
266 esp_err_t esp_wifi_config_espnow_rate(wifi_interface_t ifx, wifi_phy_rate_t rate)
267       __attribute__((deprecated("This API can be only used when rate is non-HE rate, \
268                                 please use esp_now_set_peer_rate_config if you want full support of the rate.")));
269 
270 /**
271   * @brief      Set ESPNOW rate config for each peer
272   *
273   * @attention  1. This API should be called after esp_wifi_start() and esp_now_init().
274   *
275   * @param      peer_addr  peer MAC address
276   * @param      config rate config to be configured.
277   *
278   * @return
279   *          - ESP_OK : succeed
280   *          - ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
281   *          - ESP_ERR_ESPNOW_ARG : invalid argument
282   *          - ESP_ERR_ESPNOW_INTERNAL : internal error
283   */
284 esp_err_t esp_now_set_peer_rate_config(const uint8_t *peer_addr, esp_now_rate_config_t *config);
285 
286 /**
287   * @brief     Get a peer whose MAC address matches peer_addr from peer list
288   *
289   * @param     peer_addr  peer MAC address
290   * @param     peer  peer information
291   *
292   * @return
293   *          - ESP_OK : succeed
294   *          - ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
295   *          - ESP_ERR_ESPNOW_ARG : invalid argument
296   *          - ESP_ERR_ESPNOW_NOT_FOUND : peer is not found
297   */
298 esp_err_t esp_now_get_peer(const uint8_t *peer_addr, esp_now_peer_info_t *peer);
299 
300 /**
301   * @brief     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.
302   *
303   * @param     from_head  fetch from head of list or not
304   * @param     peer  peer information
305   *
306   * @return
307   *          - ESP_OK : succeed
308   *          - ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
309   *          - ESP_ERR_ESPNOW_ARG : invalid argument
310   *          - ESP_ERR_ESPNOW_NOT_FOUND : peer is not found
311   */
312 esp_err_t esp_now_fetch_peer(bool from_head, esp_now_peer_info_t *peer);
313 
314 /**
315   * @brief     Peer exists or not
316   *
317   * @param     peer_addr  peer MAC address
318   *
319   * @return
320   *          - true : peer exists
321   *          - false : peer not exists
322   */
323 bool esp_now_is_peer_exist(const uint8_t *peer_addr);
324 
325 /**
326   * @brief     Get the number of peers
327   *
328   * @param     num  number of peers
329   *
330   * @return
331   *          - ESP_OK : succeed
332   *          - ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
333   *          - ESP_ERR_ESPNOW_ARG : invalid argument
334   */
335 esp_err_t esp_now_get_peer_num(esp_now_peer_num_t *num);
336 
337 /**
338   * @brief     Set the primary master key
339   *
340   * @param     pmk  primary master key
341   *
342   * @attention 1. primary master key is used to encrypt local master key
343   *
344   * @return
345   *          - ESP_OK : succeed
346   *          - ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
347   *          - ESP_ERR_ESPNOW_ARG : invalid argument
348   */
349 esp_err_t esp_now_set_pmk(const uint8_t *pmk);
350 
351 /**
352   * @brief     Set wake window for esp_now to wake up in interval unit
353   *
354   * @param     window  Milliseconds would the chip keep waked each interval, from 0 to 65535.
355   *
356   * @attention 1. This configuration could work at connected status.
357   *               When ESP_WIFI_STA_DISCONNECTED_PM_ENABLE is enabled, this configuration could work at disconnected status.
358   * @attention 2. Default value is the maximum.
359   *
360   * @return
361   *          - ESP_OK : succeed
362   *          - ESP_ERR_ESPNOW_NOT_INIT : ESPNOW is not initialized
363   */
364 esp_err_t esp_now_set_wake_window(uint16_t window);
365 
366 /**
367   * @}
368   */
369 
370 /**
371   * @}
372   */
373 
374 #ifdef __cplusplus
375 }
376 #endif
377 
378 #endif /* __ESP_NOW_H__ */
379