esp_wifi: Add support for NAN Discovery and Datapath

Update wifi lib with below -
1. Create NAN Discovery SM for beaconing & cluster formation
2. Create NAN interface for Tx/Rx of beacons & action frames
3. Add commands & events for NAN Services Publish/Subscribe/Followup
4. Add NAN Datapath definitions, Events, Peer structures
5. Support for forming and parsing of Datapath related attributes
6. Modules for NDP Req, Resp, Confirm, Term, Peer management
7. NAN Interface related additions in Datapath, Data Tx Q's

In addition include below changes -
1. Add netif and driver support for NAN Interface
2. Add simple examples for Publisher-Subscriber usecases
3. Add an advanced console example that supports commands
   for NAN Discovery, Services & Datapath
4. Add wifi_apps for providing better NAN API's and Peer management

Co-authored-by: Shyamal Khachane <shyamal.khachane@espressif.com>
pull/10982/head
Nachiket Kukade 2023-02-14 10:06:40 +05:30
rodzic cec892d355
commit 4c76af3f68
53 zmienionych plików z 3302 dodań i 43 usunięć

Wyświetl plik

@ -15,9 +15,10 @@ extern "C" {
#endif
typedef enum {
ESP_IF_WIFI_STA = 0, /**< ESP32 station interface */
ESP_IF_WIFI_AP, /**< ESP32 soft-AP interface */
ESP_IF_ETH, /**< ESP32 ethernet interface */
ESP_IF_WIFI_STA = 0, /**< Station interface */
ESP_IF_WIFI_AP, /**< Soft-AP interface */
ESP_IF_WIFI_NAN, /**< NAN interface */
ESP_IF_ETH, /**< Ethernet interface */
ESP_IF_MAX
} esp_interface_t;

Wyświetl plik

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -28,6 +28,10 @@ const esp_netif_ip_info_t _g_esp_netif_soft_ap_ip = {
const esp_netif_inherent_config_t _g_esp_netif_inherent_ap_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_AP();
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
const esp_netif_inherent_config_t _g_esp_netif_inherent_nan_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_NAN();
#endif
const esp_netif_inherent_config_t _g_esp_netif_inherent_eth_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
#ifdef CONFIG_PPP_SUPPORT

Wyświetl plik

@ -64,6 +64,18 @@ extern "C" {
}
#endif
#define ESP_NETIF_INHERENT_DEFAULT_WIFI_NAN() \
{ \
.flags = 0, \
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(mac) \
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(ip_info) \
.get_ip_event = 0, \
.lost_ip_event = 0, \
.if_key = "WIFI_NAN_DEF", \
.if_desc = "nan", \
.route_prio = 10 \
};
#define ESP_NETIF_INHERENT_DEFAULT_ETH() \
{ \
.flags = (esp_netif_flags_t)(ESP_NETIF_IPV4_ONLY_FLAGS(ESP_NETIF_DHCP_CLIENT) | ESP_NETIF_DEFAULT_ARP_FLAGS | ESP_NETIF_FLAG_EVENT_IP_MODIFIED), \
@ -130,6 +142,18 @@ extern "C" {
}
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
/**
* @brief Default configuration reference of WIFI NAN
*/
#define ESP_NETIF_DEFAULT_WIFI_NAN() \
{ \
.base = ESP_NETIF_BASE_DEFAULT_WIFI_NAN, \
.driver = NULL, \
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_NAN, \
}
#endif
/**
* @brief Default configuration reference of WIFI STA
*/
@ -164,6 +188,13 @@ extern "C" {
#define ESP_NETIF_BASE_DEFAULT_WIFI_AP &_g_esp_netif_inherent_ap_config
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
/**
* @brief Default base config (esp-netif inherent) of WIFI NAN
*/
#define ESP_NETIF_BASE_DEFAULT_WIFI_NAN &_g_esp_netif_inherent_nan_config
#endif
/**
* @brief Default base config (esp-netif inherent) of ethernet interface
*/
@ -183,6 +214,9 @@ extern "C" {
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
#define ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP _g_esp_netif_netstack_default_wifi_ap
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#define ESP_NETIF_NETSTACK_DEFAULT_WIFI_NAN _g_esp_netif_netstack_default_wifi_nan
#endif
#ifdef CONFIG_PPP_SUPPORT
#define ESP_NETIF_NETSTACK_DEFAULT_PPP _g_esp_netif_netstack_default_ppp
#endif
@ -199,6 +233,9 @@ extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_sta
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_ap;
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_nan;
#endif
#ifdef CONFIG_PPP_SUPPORT
extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_ppp;
#endif
@ -211,6 +248,9 @@ extern const esp_netif_inherent_config_t _g_esp_netif_inherent_sta_config;
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
extern const esp_netif_inherent_config_t _g_esp_netif_inherent_ap_config;
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
extern const esp_netif_inherent_config_t _g_esp_netif_inherent_nan_config;
#endif
extern const esp_netif_inherent_config_t _g_esp_netif_inherent_eth_config;
#ifdef CONFIG_PPP_SUPPORT
extern const esp_netif_inherent_config_t _g_esp_netif_inherent_ppp_config;

Wyświetl plik

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -65,6 +65,13 @@ err_t wlanif_init_ap(struct netif *netif);
*/
err_t wlanif_init_sta(struct netif *netif);
/**
* @brief LWIP's network stack init function for WiFi Aware interface (NAN)
* @param netif LWIP's network interface handle
* @return ERR_OK on success
*/
err_t wlanif_init_nan(struct netif *netif);
/**
* @brief LWIP's network stack input packet function for WiFi (both STA/AP)
* @param h LWIP's network interface handle

Wyświetl plik

@ -48,6 +48,12 @@ static const struct esp_netif_netstack_config s_wifi_netif_config_sta = {
.input_fn = wlanif_input
}
};
static const struct esp_netif_netstack_config s_wifi_netif_config_nan = {
.lwip = {
.init_fn = wlanif_init_nan,
.input_fn = wlanif_input
}
};
#if defined(CONFIG_PPP_SUPPORT)
static const struct esp_netif_netstack_config s_netif_config_ppp = {
@ -64,6 +70,7 @@ const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_ppp = &s_n
const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_eth = &s_eth_netif_config;
const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_sta = &s_wifi_netif_config_sta;
const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_nan = &s_wifi_netif_config_nan;
const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_ap = &s_wifi_netif_config_ap;
#endif /*CONFIG_ESP_NETIF_TCPIP_LWIP*/

Wyświetl plik

@ -230,3 +230,9 @@ err_t wlanif_init_ap(struct netif *netif) {
netif->name[1] = 'p';
return wlanif_init(netif);
}
err_t wlanif_init_nan(struct netif *netif) {
netif->name[0] = 'n';
netif->name[1] = 'a';
return wlanif_init(netif);
}

Wyświetl plik

@ -29,10 +29,15 @@ if(CONFIG_ESP_WIFI_ENABLED)
list(APPEND srcs
"src/smartconfig_ack.c")
endif()
if(CONFIG_ESP_WIFI_NAN_ENABLE)
list(APPEND srcs "wifi_apps/src/nan_app.c")
endif()
endif()
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "include"
INCLUDE_DIRS "include" "wifi_apps/include"
REQUIRES esp_event esp_phy esp_netif
PRIV_REQUIRES driver esptool_py esp_pm esp_timer nvs_flash
wpa_supplicant hal lwip esp_coex ${extra_priv_requires}

Wyświetl plik

@ -397,9 +397,15 @@ menu "Wi-Fi"
The number of hardware keys for encryption is fixed. And the espnow and SoftAP share the same
hardware keys. So this configuration will affect the maximum connection number of SoftAP.
Maximum espnow encrypted peers number + maximum number of connections of SoftAP = Max hardware keys number.
When using ESP mesh, this value should be set to a maximum of 6.
config ESP_WIFI_NAN_ENABLE
bool "WiFi Aware"
default n
depends on SOC_WIFI_NAN_SUPPORT
help
Enable WiFi Aware (NAN) feature.
config ESP_WIFI_ENABLE_WIFI_TX_STATS
bool "Enable Wi-Fi transmission statistics"
depends on SOC_WIFI_HE_SUPPORT

Wyświetl plik

@ -639,6 +639,90 @@ void esp_wifi_beacon_monitor_configure(wifi_beacon_monitor_config_t *config);
*/
void esp_wifi_internal_mac_sleep_configure(bool light_sleep_enable, bool modem_state_enable);
/**
* @brief Start Publishing a service in the NAN cluster
*
* @attention This API should be called after esp_wifi_start() in NAN Mode.
*
* @param publish_cfg Configuration parameters for publishing a service.
* @param id Identifier for the Publish service.
* @param cancel Cancel the service identified by the id.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_nan_internal_publish_service(const wifi_nan_publish_cfg_t *publish_cfg,
uint8_t *id, bool cancel);
/**
* @brief Subscribe for a service within the NAN cluster
*
* @attention This API should be called after esp_wifi_start() in NAN Mode.
*
* @param subscribe_cfg Configuration parameters for subscribing for a service.
* @param id Identifier for the Subscribe service.
* @param cancel Cancel the service identified by the id.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_nan_internal_subscribe_service(const wifi_nan_subscribe_cfg_t *subscribe_cfg,
uint8_t *id, bool cancel);
/**
* @brief Send Follow-up to the Publisher with matching service
*
* @attention This API should be called after WIFI_EVENT_NAN_SVC_MATCH event is received.
*
* @param fup_params Configuration parameters for sending a Follow-up to the Peer.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_nan_internal_send_followup(const wifi_nan_followup_params_t *fup_params);
/**
* @brief Send Datapath Request to the Publisher with matching service
*
* @attention This API should be called after WIFI_EVENT_NAN_SVC_MATCH event is received.
*
* @param req NAN Datapath Request parameters.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_nan_internal_datapath_req(wifi_nan_datapath_req_t *req, uint8_t *ndp_id);
/**
* @brief Send Datapath Response to accept or reject the received request
*
* @attention This API should be called on the Publisher after receiving WIFI_EVENT_NDP_INDICATION event.
*
* @param resp NAN Datapath Response parameters.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_nan_internal_datapath_resp(wifi_nan_datapath_resp_t *resp);
/**
* @brief End NAN Datapath that is active
*
* @attention This API should be called after receiving WIFI_EVENT_NDP_CONFIRM event.
*
* @param req NAN Datapath end request parameters.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_nan_internal_datapath_end(wifi_nan_datapath_end_req_t *req);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -268,7 +268,7 @@ esp_err_t esp_wifi_deinit(void);
/**
* @brief Set the WiFi operating mode
*
* Set the WiFi operating mode as station, soft-AP or station+soft-AP,
* Set the WiFi operating mode as station, soft-AP, station+soft-AP or NAN.
* The default mode is station mode.
*
* @param mode WiFi operating mode
@ -295,9 +295,10 @@ esp_err_t esp_wifi_get_mode(wifi_mode_t *mode);
/**
* @brief Start WiFi according to current configuration
* If mode is WIFI_MODE_STA, it create station control block and start station
* If mode is WIFI_MODE_AP, it create soft-AP control block and start soft-AP
* If mode is WIFI_MODE_APSTA, it create soft-AP and station control block and start soft-AP and station
* If mode is WIFI_MODE_STA, it creates station control block and starts station
* If mode is WIFI_MODE_AP, it creates soft-AP control block and starts soft-AP
* If mode is WIFI_MODE_APSTA, it creates soft-AP and station control block and starts soft-AP and station
* If mode is WIFI_MODE_NAN, it creates NAN control block and starts NAN
*
* @return
* - ESP_OK: succeed
@ -311,9 +312,10 @@ esp_err_t esp_wifi_start(void);
/**
* @brief Stop WiFi
* If mode is WIFI_MODE_STA, it stop station and free station control block
* If mode is WIFI_MODE_AP, it stop soft-AP and free soft-AP control block
* If mode is WIFI_MODE_APSTA, it stop station/soft-AP and free station/soft-AP control block
* If mode is WIFI_MODE_STA, it stops station and frees station control block
* If mode is WIFI_MODE_AP, it stops soft-AP and frees soft-AP control block
* If mode is WIFI_MODE_APSTA, it stops station/soft-AP and frees station/soft-AP control block
* If mode is WIFI_MODE_NAN, it stops NAN and frees NAN control block
*
* @return
* - ESP_OK: succeed
@ -790,16 +792,16 @@ esp_err_t esp_wifi_set_promiscuous_ctrl_filter(const wifi_promiscuous_filter_t *
esp_err_t esp_wifi_get_promiscuous_ctrl_filter(wifi_promiscuous_filter_t *filter);
/**
* @brief Set the configuration of the STA or AP
* @brief Set the configuration of the STA, AP or NAN
*
* @attention 1. This API can be called only when specified interface is enabled, otherwise, API fail
* @attention 2. For station configuration, bssid_set needs to be 0; and it needs to be 1 only when users need to check the MAC address of the AP.
* @attention 3. ESP devices are limited to only one channel, so when in the soft-AP+station mode, the soft-AP will adjust its channel automatically to be the same as
* the channel of the station.
* @attention 4. The configuration will be stored in NVS
* @attention 4. The configuration will be stored in NVS for station and soft-AP
*
* @param interface interface
* @param conf station or soft-AP configuration
* @param conf station, soft-AP or NAN configuration
*
* @return
* - ESP_OK: succeed
@ -1345,6 +1347,7 @@ esp_err_t esp_wifi_sta_get_aid(uint16_t *aid);
* - ESP_OK: succeed
*/
esp_err_t esp_wifi_sta_get_negotiated_phymode(wifi_phy_mode_t *phymode);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -365,6 +365,26 @@ typedef uint8_t * (*esp_ccmp_encrypt_t)(const uint8_t *tk, uint8_t *frame, size_
typedef int (*esp_aes_gmac_t)(const uint8_t *key, size_t keylen, const uint8_t *iv, size_t iv_len,
const uint8_t *aad, size_t aad_len, uint8_t *mic);
/**
* @brief SHA256 hash for data vector
* @num_elem: Number of elements in the data vector
* @addr: Pointers to the data areas
* @len: Lengths of the data blocks
* @mac: Buffer for the hash
* Returns: 0 on success, -1 on failure
*/
typedef int (*esp_sha256_vector_t)(size_t num_elem, const uint8_t *addr[], const size_t *len, uint8_t *buf);
/**
* @brief CRC32 value in little endian.
*
* @param crc: Initial CRC value (result of last calculation or 0 for the first time)
* @param buf: Data buffer that used to calculate the CRC value
* @param len: Length of the data buffer
* @return CRC32 value
*/
typedef uint32_t (*esp_crc32_le_t)(uint32_t crc, uint8_t const *buf, uint32_t len);
/**
* @brief The crypto callback function structure used when do station security connect.
* The structure can be set as software crypto or the crypto optimized by device's
@ -398,6 +418,8 @@ typedef struct {
esp_ccmp_decrypt_t ccmp_decrypt;
esp_ccmp_encrypt_t ccmp_encrypt;
esp_aes_gmac_t aes_gmac;
esp_sha256_vector_t sha256_vector;
esp_crc32_le_t crc32;
}wpa_crypto_funcs_t;
/**

Wyświetl plik

@ -51,6 +51,14 @@ esp_err_t esp_wifi_set_default_wifi_sta_handlers(void);
*/
esp_err_t esp_wifi_set_default_wifi_ap_handlers(void);
/**
* @brief Sets default wifi event handlers for NAN interface
*
* @return
* - ESP_OK on success, error returned from esp_event_handler_register if failed
*/
esp_err_t esp_wifi_set_default_wifi_nan_handlers(void);
/**
* @brief Clears default wifi event handlers for supplied network interface
*
@ -81,6 +89,16 @@ esp_netif_t* esp_netif_create_default_wifi_ap(void);
*/
esp_netif_t* esp_netif_create_default_wifi_sta(void);
/**
* @brief Creates default WIFI NAN. In case of any init error this API aborts.
*
* @note The API creates esp_netif object with default WiFi station config,
* attaches the netif to wifi and registers default wifi handlers.
*
* @return pointer to esp-netif instance
*/
esp_netif_t* esp_netif_create_default_wifi_nan(void);
/**
* @brief Destroys default WIFI netif created with esp_netif_create_default_wifi_...() API.
*

Wyświetl plik

@ -13,7 +13,7 @@ extern "C" {
/**
* @brief Number of WiFi interfaces used by wifi-netif abstraction
*/
#define MAX_WIFI_IFS (2)
#define MAX_WIFI_IFS WIFI_IF_MAX
/**
* @brief Forward declaration of WiFi interface handle

Wyświetl plik

@ -22,12 +22,17 @@ typedef enum {
WIFI_MODE_STA, /**< WiFi station mode */
WIFI_MODE_AP, /**< WiFi soft-AP mode */
WIFI_MODE_APSTA, /**< WiFi station + soft-AP mode */
WIFI_MODE_NAN, /**< WiFi NAN mode */
WIFI_MODE_MAX
} wifi_mode_t;
typedef enum {
WIFI_IF_STA = ESP_IF_WIFI_STA,
WIFI_IF_AP = ESP_IF_WIFI_AP,
#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2)
WIFI_IF_NAN = ESP_IF_WIFI_NAN,
#endif
WIFI_IF_MAX
} wifi_interface_t;
#define WIFI_OFFCHAN_TX_REQ 1
@ -326,15 +331,27 @@ typedef struct {
uint8_t sae_h2e_identifier[SAE_H2E_IDENTIFIER_LEN];/**< Password identifier for H2E. this needs to be null terminated string */
} wifi_sta_config_t;
/** @brief Configuration data for device's AP or STA.
/**
* @brief NAN Discovery start configuration
*
*/
typedef struct {
uint8_t op_channel; /**< NAN Discovery operating channel */
uint8_t master_pref; /**< Device's preference value to serve as NAN Master */
uint8_t scan_time; /**< Scan time in seconds while searching for a NAN cluster */
uint16_t warm_up_sec; /**< Warm up time before assuming NAN Anchor Master role */
} wifi_nan_config_t;
/** @brief Configuration data for device's AP or STA or NAN.
*
* The usage of this union (for ap or sta configuration) is determined by the accompanying
* The usage of this union (for ap, sta or nan configuration) is determined by the accompanying
* interface argument passed to esp_wifi_set_config() or esp_wifi_get_config()
*
*/
typedef union {
wifi_ap_config_t ap; /**< configuration of AP */
wifi_sta_config_t sta; /**< configuration of STA */
wifi_nan_config_t nan; /**< configuration of NAN */
} wifi_config_t;
/** @brief Description of STA associated with AP */
@ -632,6 +649,115 @@ typedef struct {
uint16_t burst_period; /**< Requested time period between consecutive FTM bursts in 100's of milliseconds (0 - No pref) */
} wifi_ftm_initiator_cfg_t;
/**
* @brief WiFi beacon monitor parameter configuration
*
*/
typedef struct {
bool enable; /**< Enable or disable beacon monitor */
uint8_t loss_timeout; /**< Beacon lost timeout */
uint8_t loss_threshold; /**< Maximum number of consecutive lost beacons allowed */
uint8_t delta_intr_early; /**< Delta early time for RF PHY on */
uint8_t delta_loss_timeout; /**< Delta timeout time for RF PHY off */
#if MAC_SUPPORT_PMU_MODEM_STATE
uint8_t beacon_abort: 1, /**< Enable or disable beacon abort */
broadcast_wakeup: 1, /**< Enable or disable TIM element multicast wakeup */
reserved: 6; /**< Reserved */
uint8_t tsf_time_sync_deviation; /**< Deviation range to sync with AP TSF timestamp */
uint16_t modem_state_consecutive; /**< PMU MODEM state consecutive count limit */
uint16_t rf_ctrl_wait_cycle; /**< RF on wait time (unit: Modem APB clock cycle) */
#endif
} wifi_beacon_monitor_config_t;
#define ESP_WIFI_NAN_MAX_SVC_SUPPORTED 2
#define ESP_WIFI_NAN_DATAPATH_MAX_PEERS 2
#define ESP_WIFI_NDP_ROLE_INITIATOR 1
#define ESP_WIFI_NDP_ROLE_RESPONDER 2
#define ESP_WIFI_MAX_SVC_NAME_LEN 256
#define ESP_WIFI_MAX_FILTER_LEN 256
#define ESP_WIFI_MAX_SVC_INFO_LEN 64
/**
* @brief NAN Services types
*
*/
typedef enum {
NAN_PUBLISH_SOLICITED, /**< Send unicast Publish frame to Subscribers that match the requirement */
NAN_PUBLISH_UNSOLICITED,/**< Send broadcast Publish frames in every Discovery Window(DW) */
NAN_SUBSCRIBE_ACTIVE, /**< Send broadcast Subscribe frames in every DW */
NAN_SUBSCRIBE_PASSIVE, /**< Passively listens to Publish frames */
} wifi_nan_service_type_t;
/**
* @brief NAN Publish service configuration parameters
*
*/
typedef struct {
char service_name[ESP_WIFI_MAX_SVC_NAME_LEN]; /**< Service name identifier */
wifi_nan_service_type_t type; /**< Service type */
char matching_filter[ESP_WIFI_MAX_FILTER_LEN]; /**< Comma separated filters for filtering services */
char svc_info[ESP_WIFI_MAX_SVC_INFO_LEN]; /**< Service info shared in Publish frame */
uint8_t single_replied_event:1; /**< Give single Replied event or every time */
uint8_t datapath_reqd:1; /**< NAN Datapath required for the service */
uint8_t fsd_reqd:1; /**< Further Service Discovery required */
uint8_t reserved:5; /**< Reserved */
} wifi_nan_publish_cfg_t;
/**
* @brief NAN Subscribe service configuration parameters
*
*/
typedef struct {
char service_name[ESP_WIFI_MAX_SVC_NAME_LEN]; /**< Service name identifier */
wifi_nan_service_type_t type; /**< Service type */
char matching_filter[ESP_WIFI_MAX_FILTER_LEN]; /**< Comma separated filters for filtering services */
char svc_info[ESP_WIFI_MAX_SVC_INFO_LEN]; /**< Service info shared in Subscribe frame */
uint8_t single_match_event:1; /**< Give single Match event or every time */
uint8_t reserved:7; /**< Reserved */
} wifi_nan_subscribe_cfg_t;
/**
* @brief NAN Follow-up parameters
*
*/
typedef struct {
uint8_t inst_id; /**< Own service instance id */
uint8_t peer_inst_id; /**< Peer's service instance id */
uint8_t peer_mac[6]; /**< Peer's MAC address */
char svc_info[ESP_WIFI_MAX_SVC_INFO_LEN];/**< Service info(or message) to be shared */
} wifi_nan_followup_params_t;
/**
* @brief NAN Datapath Request parameters
*
*/
typedef struct {
uint8_t pub_id; /**< Publisher's service instance id */
uint8_t peer_mac[6]; /**< Peer's MAC address */
bool confirm_required; /**< NDP Confirm frame required */
} wifi_nan_datapath_req_t;
/**
* @brief NAN Datapath Response parameters
*
*/
typedef struct {
bool accept; /**< True - Accept incoming NDP, False - Reject it */
uint8_t ndp_id; /**< NAN Datapath Identifier */
uint8_t peer_mac[6]; /**< Peer's MAC address */
} wifi_nan_datapath_resp_t;
/**
* @brief NAN Datapath End parameters
*
*/
typedef struct {
uint8_t ndp_id; /**< NAN Datapath Identifier */
uint8_t peer_mac[6]; /**< Peer's MAC address */
} wifi_nan_datapath_end_req_t;
/**
* @brief WiFi PHY rate encodings
*
@ -726,6 +852,15 @@ typedef enum {
WIFI_EVENT_ITWT_PROBE, /**< iTWT probe */
WIFI_EVENT_ITWT_SUSPEND, /**< iTWT suspend */
WIFI_EVENT_NAN_STARTED, /**< NAN Discovery has started */
WIFI_EVENT_NAN_STOPPED, /**< NAN Discovery has stopped */
WIFI_EVENT_NAN_SVC_MATCH, /**< NAN Service Discovery match found */
WIFI_EVENT_NAN_REPLIED, /**< Replied to a NAN peer with Service Discovery match */
WIFI_EVENT_NAN_RECEIVE, /**< Received a Follow-up message */
WIFI_EVENT_NDP_INDICATION, /**< Received NDP Request from a NAN Peer */
WIFI_EVENT_NDP_CONFIRM, /**< NDP Confirm Indication */
WIFI_EVENT_NDP_TERMINATED, /**< NAN Datapath terminated indication */
WIFI_EVENT_MAX, /**< Invalid WiFi event ID */
} wifi_event_t;
@ -893,22 +1028,53 @@ typedef struct {
uint8_t peer_macaddr[6]; /**< Enrollee mac address */
} wifi_event_ap_wps_rg_success_t;
/** WiFi beacon monitor parameter configuration */
/** Argument structure for WIFI_EVENT_NAN_SVC_MATCH event */
typedef struct {
bool enable; /**< Enable or disable beacon monitor */
uint8_t loss_timeout; /**< Beacon lost timeout */
uint8_t loss_threshold; /**< Maximum number of consecutive lost beacons allowed */
uint8_t delta_intr_early; /**< Delta early time for RF PHY on */
uint8_t delta_loss_timeout; /**< Delta timeout time for RF PHY off */
#if MAC_SUPPORT_PMU_MODEM_STATE
uint8_t beacon_abort: 1, /**< Enable or disable beacon abort */
broadcast_wakeup: 1, /**< Enable or disable TIM element multicast wakeup */
reserved: 6; /**< Reserved */
uint8_t tsf_time_sync_deviation; /**< Deviation range to sync with AP TSF timestamp */
uint16_t modem_state_consecutive; /**< PMU MODEM state consecutive count limit */
uint16_t rf_ctrl_wait_cycle; /**< RF on wait time (unit: Modem APB clock cycle) */
#endif
} wifi_beacon_monitor_config_t;
uint8_t subscribe_id; /**< Subscribe Service Identifier */
uint8_t publish_id; /**< Publish Service Identifier */
uint8_t pub_if_mac[6]; /**< NAN Interface MAC of the Publisher */
} wifi_event_nan_svc_match_t;
/** Argument structure for WIFI_EVENT_NAN_REPLIED event */
typedef struct {
uint8_t publish_id; /**< Publish Service Identifier */
uint8_t subscribe_id; /**< Subscribe Service Identifier */
uint8_t sub_if_mac[6]; /**< NAN Interface MAC of the Subscriber */
} wifi_event_nan_replied_t;
/** Argument structure for WIFI_EVENT_NAN_RECEIVE event */
typedef struct {
uint8_t inst_id; /**< Our Service Identifier */
uint8_t peer_inst_id; /**< Peer's Service Identifier */
uint8_t peer_if_mac[6]; /**< Peer's NAN Interface MAC */
uint8_t peer_svc_info[ESP_WIFI_MAX_SVC_INFO_LEN];/**< Peer Service Info */
} wifi_event_nan_receive_t;
/** Argument structure for WIFI_EVENT_NDP_INDICATION event */
typedef struct {
uint8_t publish_id; /**< Publish Id for NAN Service */
uint8_t ndp_id; /**< NDP instance id */
uint8_t peer_nmi[6]; /**< Peer's NAN Management Interface MAC */
uint8_t peer_ndi[6]; /**< Peer's NAN Data Interface MAC */
uint8_t svc_info[ESP_WIFI_MAX_SVC_INFO_LEN];/**< Service Specific Info */
} wifi_event_ndp_indication_t;
/** Argument structure for WIFI_EVENT_NDP_CONFIRM event */
typedef struct {
uint8_t status; /**< NDP status code */
uint8_t ndp_id; /**< NDP instance id */
uint8_t peer_nmi[6]; /**< Peer's NAN Management Interface MAC */
uint8_t peer_ndi[6]; /**< Peer's NAN Data Interface MAC */
uint8_t own_ndi[6]; /**< Own NAN Data Interface MAC */
uint8_t svc_info[ESP_WIFI_MAX_SVC_INFO_LEN];/**< Service Specific Info */
} wifi_event_ndp_confirm_t;
/** Argument structure for WIFI_EVENT_NDP_TERMINATED event */
typedef struct {
uint8_t reason; /**< Termination reason code */
uint8_t ndp_id; /**< NDP instance id */
uint8_t init_ndi[6]; /**< Initiator's NAN Data Interface MAC */
} wifi_event_ndp_terminated_t;
#ifdef __cplusplus
}

@ -1 +1 @@
Subproject commit 5ec56cf3775998a69b7946a5b2318d22f6650a95
Subproject commit a821d6aef8e9ba26b1003a0fa3276774a2113433

Wyświetl plik

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -10,6 +10,9 @@
#include "esp_private/wifi.h"
#include "esp_wifi_netif.h"
#include <string.h>
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#include "apps_private/wifi_apps_private.h"
#endif
//
// Purpose of this module is to provide basic wifi initialization setup for
@ -131,6 +134,24 @@ static void wifi_default_action_sta_got_ip(void *arg, esp_event_base_t base, int
}
}
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
static void wifi_default_action_nan_started(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
if (s_wifi_netifs[WIFI_IF_NAN] != NULL) {
wifi_start(s_wifi_netifs[WIFI_IF_NAN], base, event_id, data);
esp_nan_action_start(s_wifi_netifs[WIFI_IF_NAN]);
}
}
static void wifi_default_action_nan_stopped(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
if (s_wifi_netifs[WIFI_IF_NAN] != NULL) {
esp_netif_action_stop(s_wifi_netifs[WIFI_IF_NAN], base, event_id, data);
esp_nan_action_stop();
}
}
#endif
/**
* @brief Clear default handlers
*/
@ -145,6 +166,10 @@ static esp_err_t clear_default_wifi_handlers(void)
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_AP_STOP, wifi_default_action_ap_stop);
#endif
esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_default_action_sta_got_ip);
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_NAN_STARTED, wifi_default_action_nan_started);
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_NAN_STOPPED, wifi_default_action_nan_stopped);
#endif
esp_unregister_shutdown_handler((shutdown_handler_t)esp_wifi_stop);
wifi_default_handlers_set = false;
return ESP_OK;
@ -197,6 +222,18 @@ static esp_err_t set_default_wifi_handlers(void)
goto fail;
}
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_NAN_STARTED, wifi_default_action_nan_started, NULL);
if (err != ESP_OK) {
goto fail;
}
err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_NAN_STOPPED, wifi_default_action_nan_stopped, NULL);
if (err != ESP_OK) {
goto fail;
}
#endif
err = esp_register_shutdown_handler((shutdown_handler_t)esp_wifi_stop);
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
goto fail;
@ -225,6 +262,14 @@ esp_err_t esp_wifi_set_default_wifi_ap_handlers(void)
return set_default_wifi_handlers();
}
/**
* @brief Set default handlers for NAN (official API)
*/
esp_err_t esp_wifi_set_default_wifi_nan_handlers(void)
{
return set_default_wifi_handlers();
}
/**
* @brief Clear default handlers and destroy appropriate objects (official API)
*/
@ -283,6 +328,9 @@ static inline esp_err_t esp_netif_attach_wifi(esp_netif_t *esp_netif, wifi_inter
if (esp_netif == NULL || (wifi_if != WIFI_IF_STA
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
&& wifi_if != WIFI_IF_AP
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
&& wifi_if != WIFI_IF_NAN
#endif
)) {
return ESP_ERR_INVALID_ARG;
@ -303,6 +351,13 @@ esp_err_t esp_netif_attach_wifi_ap(esp_netif_t *esp_netif)
}
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
esp_err_t esp_netif_attach_wifi_nan(esp_netif_t *esp_netif)
{
return esp_netif_attach_wifi(esp_netif, WIFI_IF_NAN);
}
#endif
//
// Default WiFi creation from user code
@ -336,6 +391,21 @@ esp_netif_t* esp_netif_create_default_wifi_sta(void)
return netif;
}
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
/**
* @brief User init default NAN (official API)
*/
esp_netif_t* esp_netif_create_default_wifi_nan(void)
{
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_WIFI_NAN();
esp_netif_t *netif = esp_netif_new(&cfg);
assert(netif);
esp_netif_attach_wifi_nan(netif);
esp_wifi_set_default_wifi_nan_handlers();
return netif;
}
#endif
/**
* @brief User init default wifi esp_netif object (official API)
*/
@ -357,13 +427,15 @@ esp_netif_t* esp_netif_create_wifi(wifi_interface_t wifi_if, const esp_netif_inh
};
if (wifi_if == WIFI_IF_STA) {
cfg.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA;
} else
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
if (wifi_if == WIFI_IF_AP) {
} else if (wifi_if == WIFI_IF_AP) {
cfg.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP;
} else
#endif
{
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
} else if (wifi_if == WIFI_IF_NAN) {
cfg.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_NAN;
#endif
} else {
return NULL;
}

Wyświetl plik

@ -19,6 +19,9 @@
#include "esp_coexist_internal.h"
#include "esp_phy_init.h"
#include "esp_private/phy.h"
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#include "apps_private/wifi_apps_private.h"
#endif
#if (CONFIG_ESP_WIFI_RX_BA_WIN > CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM)
#error "WiFi configuration check: WARNING, WIFI_RX_BA_WIN should not be larger than WIFI_DYNAMIC_RX_BUFFER_NUM!"
@ -127,6 +130,10 @@ esp_err_t esp_wifi_deinit(void)
ESP_LOGW(TAG, "Failed to unregister Rx callbacks");
}
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
esp_nan_app_deinit();
#endif
esp_supplicant_deinit();
err = esp_wifi_deinit_internal();
if (err != ESP_OK) {
@ -305,6 +312,11 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
adc2_cal_include(); //This enables the ADC2 calibration constructor at start up.
esp_wifi_config_info();
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
esp_nan_app_init();
#endif
return result;
}
@ -337,3 +349,30 @@ void net80211_softap_funcs_init(void)
{
}
#endif
#ifndef CONFIG_ESP_WIFI_NAN_ENABLE
esp_err_t nan_start(void)
{
/* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
return ESP_OK;
}
esp_err_t nan_stop(void)
{
/* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
return ESP_OK;
}
int nan_input(void *p1, int p2, int p3)
{
/* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
return 0;
}
void nan_sm_handle_event(void *p1, int p2)
{
/* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
}
#endif

Wyświetl plik

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -46,6 +46,13 @@ static esp_err_t wifi_ap_receive(void *buffer, uint16_t len, void *eb)
}
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
static esp_err_t wifi_nan_receive(void *buffer, uint16_t len, void *eb)
{
return s_wifi_rxcbs[WIFI_IF_NAN](s_wifi_netifs[WIFI_IF_NAN], buffer, len, eb);
}
#endif
static void wifi_free(void *h, void* buffer)
{
if (buffer) {
@ -146,6 +153,12 @@ esp_err_t esp_wifi_register_if_rxcb(wifi_netif_driver_t ifx, esp_netif_receive_t
break;
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
case WIFI_IF_NAN:
rxcb = wifi_nan_receive;
break;
#endif
default:
break;
}

Wyświetl plik

@ -0,0 +1,56 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_log.h"
#include "esp_err.h"
#include "esp_wifi_types.h"
#include "esp_netif.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
/**
* @brief Initialize the NAN App and required Data Structures
*
* @attention This API should be called in esp_wifi_init()
*/
void esp_nan_app_init(void);
/**
* @brief De-initialize the NAN App and complete the cleanup
*
* @attention This API should be called in esp_wifi_deinit()
*/
void esp_nan_app_deinit(void);
/**
* @brief NAN App action handler for NAN Started event. Sets up other event handlers and
* initializes NAN App context
*
* @attention This API should be called in WIFI_EVENT_NAN_STARTED event handler
*
* @param nan_netif Netif handle corresponding to NAN interface.
*/
void esp_nan_action_start(esp_netif_t *nan_netif);
/**
* @brief NAN App action handler for NAN Stopped event. Clears other event handlers and
* resets NAN App context
*
* @attention This API should be called in WIFI_EVENT_NAN_STOPPED event handler
*/
void esp_nan_action_stop(void);
#endif /* CONFIG_ESP_WIFI_NAN_ENABLE */
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -0,0 +1,202 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_log.h"
#include "esp_err.h"
#include "lwip/inet.h"
#include "esp_wifi_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define WIFI_NAN_CONFIG_DEFAULT() { \
.op_channel = 6, \
.master_pref = 2, \
.scan_time = 3, \
.warm_up_sec = 5, \
};
#define NDP_STATUS_ACCEPTED 1
#define NDP_STATUS_REJECTED 2
#define NAN_MAX_PEERS_RECORD 15
#define ESP_NAN_PUBLISH 1
#define ESP_NAN_SUBSCRIBE 2
/** Parameters of a peer service record */
struct nan_peer_record {
uint8_t peer_svc_id; /**< Identifier of Peer's service */
uint8_t own_svc_id; /**< Identifier of own service associated with Peer */
uint8_t peer_nmi[6]; /**< Peer's NAN Management Interface address */
uint8_t peer_svc_type; /**< Peer's service type (Publish/Subscribe) */
uint8_t ndp_id; /**< Specifies if the peer has any active datapath */
uint8_t peer_ndi[6]; /**< Peer's NAN Data Interface address, only valid when ndp_id is non-zero */
};
/**
* @brief Start NAN Discovery with provided configuration
*
* @attention This API should be called after esp_wifi_init().
*
* @param nan_cfg NAN related parameters to be configured.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_nan_start(const wifi_nan_config_t *nan_cfg);
/**
* @brief Stop NAN Discovery, end NAN Services and Datapaths
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_nan_stop(void);
/**
* @brief Start Publishing a service to the NAN Peers in vicinity
*
* @attention This API should be called after esp_wifi_nan_start().
*
* @param publish_cfg Configuration parameters for publishing a service.
* @param ndp_resp_needed Setting this true will require user response for every NDP Req using esp_wifi_nan_datapath_resp API.
*
* @return
* - non-zero: Publish service identifier
* - zero: failed
*/
uint8_t esp_wifi_nan_publish_service(const wifi_nan_publish_cfg_t *publish_cfg, bool ndp_resp_needed);
/**
* @brief Subscribe for a service within the NAN cluster
*
* @attention This API should be called after esp_wifi_nan_start().
*
* @param subscribe_cfg Configuration parameters for subscribing for a service.
*
* @return
* - non-zero: Subscribe service identifier
* - zero: failed
*/
uint8_t esp_wifi_nan_subscribe_service(const wifi_nan_subscribe_cfg_t *subscribe_cfg);
/**
* @brief Send a follow-up message to the NAN Peer with matched service
*
* @attention This API should be called after a NAN service is discovered due to a match.
*
* @param fup_params Configuration parameters for sending a Follow-up message.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_nan_send_message(wifi_nan_followup_params_t *fup_params);
/**
* @brief Cancel a NAN service
*
* @param service_id Publish/Subscribe service id to be cancelled.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_nan_cancel_service(uint8_t service_id);
/**
* @brief Send NAN Datapath Request to a NAN Publisher with matched service
*
* @attention This API should be called by the Subscriber after a match occurs with a Publisher.
*
* @param req NAN Datapath Request parameters.
*
* @return
* - non-zero: NAN Datapath Identifier
* - zero: failed
*/
uint8_t esp_wifi_nan_datapath_req(wifi_nan_datapath_req_t *req);
/**
* @brief Respond to a NAN Datapath request with Accept or Reject
*
* @attention This API should be called if ndp_auto_accept is not set True by the Publisher and
* a WIFI_EVENT_NDP_INDICATION event is received due to an incoming NDP request.
*
* @param resp NAN Datapath Response parameters.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_nan_datapath_resp(wifi_nan_datapath_resp_t *resp);
/**
* @brief Terminate a NAN Datapath
*
* @param req NAN Datapath end request parameters.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_nan_datapath_end(wifi_nan_datapath_end_req_t *req);
/**
* @brief Get IPv6 Link Local address using MAC address
*
* @param[out] ip6 Derived IPv6 Link Local address.
* @param[in] mac_addr Input MAC Address.
*/
void esp_wifi_nan_get_ipv6_linklocal_from_mac(ip6_addr_t *ip6, uint8_t *mac_addr);
/**
* brief Get own Service information from Service ID OR Name.
*
* @param[inout] own_svc_id As input, it indicates Service ID to search for.
* As output, it indicates Service ID of the service found using Service Name.
* @param[inout] svc_name As input, it indicates Service Name to search for.
* As output, it indicates Service Name of the service found using Service ID.
* @param[out] num_peer_records Number of peers discovered by corresponding service.
* @return
* - ESP_OK: succeed
* - ESP_FAIL: failed
*/
esp_err_t esp_wifi_nan_get_own_svc_info(uint8_t *own_svc_id, char *svc_name, int *num_peer_records);
/**
* brief Get a list of Peers discovered by the given Service.
*
* @param[inout] num_peer_records As input param, it stores max peers peer_record can hold.
* As output param, it specifies the actual number of peers this API returns.
* @param own_svc_id Service ID of own service.
* @param[out] peer_record Pointer to first peer record.
* @return
* - ESP_OK: succeed
* - ESP_FAIL: failed
*/
esp_err_t esp_wifi_nan_get_peer_records(int *num_peer_records, uint8_t own_svc_id, struct nan_peer_record *peer_record);
/**
* brief Find Peer's Service information using Peer MAC and optionally Service Name.
*
* @param svc_name Service Name of the published/subscribed service.
* @param peer_mac Peer's NAN Management Interface MAC address.
* @param[out] peer_info Peer's service information structure.
* @return
* - ESP_OK: succeed
* - ESP_FAIL: failed
*/
esp_err_t esp_wifi_nan_get_peer_info(char *svc_name, uint8_t *peer_mac, struct nan_peer_record *peer_info);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -823,6 +823,10 @@ config SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW
bool
default y
config SOC_WIFI_NAN_SUPPORT
bool
default y
config SOC_BLE_SUPPORTED
bool
default y

Wyświetl plik

@ -406,6 +406,7 @@
#define SOC_WIFI_CSI_SUPPORT (1) /*!< Support CSI */
#define SOC_WIFI_MESH_SUPPORT (1) /*!< Support WIFI MESH */
#define SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW (1) /*!< Support delta early time for rf phy on/off */
#define SOC_WIFI_NAN_SUPPORT (1) /*!< Support WIFI Aware (NAN) */
/*---------------------------------- Bluetooth CAPS ----------------------------------*/
#define SOC_BLE_SUPPORTED (1) /*!< Support Bluetooth Low Energy hardware */

Wyświetl plik

@ -1070,3 +1070,7 @@ config SOC_WIFI_MESH_SUPPORT
config SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW
bool
default y
config SOC_WIFI_NAN_SUPPORT
bool
default y

Wyświetl plik

@ -459,3 +459,4 @@
#define SOC_WIFI_CSI_SUPPORT (1) /*!< Support CSI */
#define SOC_WIFI_MESH_SUPPORT (1) /*!< Support WIFI MESH */
#define SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW (1) /*!< Support delta early time for rf phy on/off */
#define SOC_WIFI_NAN_SUPPORT (1) /*!< Support WIFI Aware (NAN) */

Wyświetl plik

@ -0,0 +1,31 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Convert user input colon separated MAC Address into 6 byte MAC Address
*
* @param[in] str User input colon separated MAC Address.
* @param[out] dest Output 6 byte MAC Address.
*
* @return
* - ESP_OK: Succeed
* - ESP_FAIL: Invalid input format
*/
esp_err_t esp_supplicant_str_to_mac(const char *str, uint8_t dest[6]);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -23,6 +23,16 @@
#include "rsn_supp/wpa_i.h"
#include "rsn_supp/wpa.h"
/* Utility Functions */
esp_err_t esp_supplicant_str_to_mac(const char *str, uint8_t dest[6])
{
if (hwaddr_aton2(str, dest) < 0) {
return ESP_FAIL;
}
return ESP_OK;
}
struct wpa_supplicant g_wpa_supp;
#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) || defined(CONFIG_SAE_PK)

Wyświetl plik

@ -368,6 +368,12 @@ extern const wifi_osi_funcs_t *wifi_funcs;
#define os_task_ms_to_tick(a) wifi_funcs->_task_ms_to_tick((a))
#define os_timer_get_time(void) wifi_funcs->_esp_timer_get_time(void)
#define os_event_group_create(void) wifi_funcs->_event_group_create(void)
#define os_event_group_delete(void) wifi_funcs->_event_group_delete(void)
#define os_event_group_wait_bits(a, b, c, d, e) wifi_funcs->_event_group_wait_bits((a), (b), (c), (d), (e))
#define os_event_group_clear_bits(a, b) wifi_funcs->_event_group_clear_bits((a), (b))
#define os_event_group_set_bits(a, b) wifi_funcs->_event_group_set_bits((a), (b))
static inline void os_timer_setfn(void *ptimer, void *pfunction, void *parg)
{
return wifi_funcs->_timer_setfn(ptimer, pfunction, parg);

Wyświetl plik

@ -13,6 +13,7 @@
#include "aes.h"
#include "esp_wpa.h"
#include "ccmp.h"
#include "esp_rom_crc.h"
#define DEFAULT_KEK_LEN 16
@ -46,6 +47,11 @@ static int esp_aes_gmac(const u8 *key, size_t key_len, const u8 *iv, size_t iv_l
#endif
}
static uint32_t esp_supp_crc32(uint32_t crc, uint8_t const *buf, uint32_t len)
{
return esp_rom_crc32_le(crc, buf, len);
}
/*
* This structure is used to set the cyrpto callback function for station to connect when in security mode.
* These functions either call MbedTLS API's if CONFIG_CRYPTO_MBEDTLS flag is set through Kconfig, or native
@ -80,6 +86,8 @@ const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs = {
.ccmp_decrypt = (esp_ccmp_decrypt_t)ccmp_decrypt,
.ccmp_encrypt = (esp_ccmp_encrypt_t)ccmp_encrypt,
.aes_gmac = (esp_aes_gmac_t)esp_aes_gmac,
.sha256_vector = (esp_sha256_vector_t)sha256_vector,
.crc32 = (esp_crc32_le_t)esp_supp_crc32,
};
const mesh_crypto_funcs_t g_wifi_default_mesh_crypto_funcs = {

Wyświetl plik

@ -178,6 +178,7 @@ INPUT = \
$(PROJECT_PATH)/components/esp_wifi/include/esp_wifi_default.h \
$(PROJECT_PATH)/components/esp_wifi/include/esp_wifi_types.h \
$(PROJECT_PATH)/components/esp_wifi/include/esp_wifi.h \
$(PROJECT_PATH)/components/esp_wifi/wifi_apps/include/esp_nan.h \
$(PROJECT_PATH)/components/esp-tls/esp_tls_errors.h \
$(PROJECT_PATH)/components/esp-tls/esp_tls.h \
$(PROJECT_PATH)/components/fatfs/diskio/diskio_impl.h \
@ -277,6 +278,7 @@ INPUT = \
$(PROJECT_PATH)/components/wifi_provisioning/include/wifi_provisioning/wifi_config.h \
$(PROJECT_PATH)/components/wifi_provisioning/include/wifi_provisioning/wifi_scan.h \
$(PROJECT_PATH)/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h \
$(PROJECT_PATH)/components/wpa_supplicant/esp_supplicant/include/esp_supplicant_utils.h \
## Target specific headers are in seperate Doxyfile files
@INCLUDE = $(PROJECT_PATH)/docs/doxygen/Doxyfile_$(IDF_TARGET)

Wyświetl plik

@ -0,0 +1,20 @@
Wi-Fi Aware\ :sup:`TM` (NAN)
===================================
Wi-Fi Aware\ :sup:`TM` or NAN (Neighbor Awareness Networking) is a protocol that allows Wi-Fi devices to discover services in their proximity. Typically, location-based services are based on querying servers for information about the environment and the location knowledge is based on GPS or other location reckoning techniques. However NAN does not require real-time connection to servers, GPS or other geo-location, but instead uses direct device-to-device Wi-Fi to discover and exchange information. NAN scales effectively in dense Wi-Fi environments and complements the connectivity of Wi-Fi by providing information about people and services in the proximity.
Multiple NAN devices which are in the vicinity will form a NAN cluster which allows them to communicate with each other. Devices within a NAN cluster can advertise (Publish method) or look for (Subscribe method) services using NAN Service Discovery protocols. Matching of services is done by service name, once a match is found a device can either send a message or establish an IPv6 datapath with the peer.
{IDF_TARGET_NAME} supports Wi-Fi Aware in standalone mode with support for both Service Discovery and Datapath. Wi-Fi Aware is still an evolving protocol. Please refer to Wi-Fi Alliance's official page on `Wi-Fi Aware <https://www.wi-fi.org/discover-wi-fi/wi-fi-aware>`_ for more information. Many Android smartphones with Android 8 or higher support Wi-Fi Aware. Refer to Android's developer guide on Wi-Fi Aware `Wi-Fi Aware <https://www.wi-fi.org/discover-wi-fi/wi-fi-aware>`_ for more information.
Application Example
-------------------
A pair of examples for a Publisher-Subscriber use case: :example:`wifi/wifi_aware/nan_publisher` and :example:`wifi/wifi_aware/nan_subscriber`.
A user interactive console example to explore full functionality of Wi-Fi Aware: :example:`wifi/wifi_aware/nan_console`.
Please check the `README` for more details in respective example directories.
API Reference
-------------
.. include-build-file:: inc/esp_nan.inc

Wyświetl plik

@ -14,6 +14,7 @@ Wi-Fi
esp_smartconfig
esp_wifi
esp_dpp
esp_nan
Code examples for the Wi-Fi API are provided in the :example:`wifi` directory of ESP-IDF examples.

Wyświetl plik

@ -0,0 +1 @@
.. include:: ../../../en/api-reference/network/esp_nan.rst

Wyświetl plik

@ -14,6 +14,7 @@ Wi-Fi
esp_smartconfig
esp_wifi
esp_dpp
esp_nan
本部分的 Wi-Fi API 示例代码存放在 ESP-IDF 示例项目的 :example:`wifi` 目录下。

Wyświetl plik

@ -29,3 +29,8 @@ examples/wifi/iperf:
examples/wifi/itwt:
disable:
- if: SOC_WIFI_HE_SUPPORT != 1
examples/wifi/wifi_aware:
disable:
- if: SOC_WIFI_NAN_SUPPORT != 1
reason: targets esp32c3, esp32s3, esp32c2 and esp32c6 are not supported

Wyświetl plik

@ -0,0 +1,8 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/system/console/advanced/components)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(nan_console)

Wyświetl plik

@ -0,0 +1,187 @@
| Supported Targets | ESP32 | ESP32-S2 |
| ----------------- | ----- | -------- |
# NAN Console Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
## Introduction
Neighbor Awareness Networking (NAN) is a protocol that allows Wi-Fi devices to discover services in their proximity. NAN uses direct device-to-device communication and does not require any Internet or AP connection.
Multiple NAN devices which are in the vicinity will form a NAN cluster which allows them to communicate with each other. Devices within a NAN cluster can advertise or look for services using NAN Service Discovery protocols.
A Publisher advertises a service and a Subscriber searches for a service. A subscriber either listens passively (Passive mode) or sends out broadcast Action frames (Active mode). Similarly a publisher either broadcasts its services (Unsolicited mode) or replies to Active subscribers (Solicited Mode). Matching of services is done by service name and optionally matching filters. Once a Subscriber gets a match to the service, it can either send Follow-up frames or negotiate using NDP frames to establish a datapath. After NDP is setup both devices will obtain a IPv6 address and can use it for further communication.
## How to use example
With the console users can configure NAN and its services on the fly. Flashing the example will first show a brief guide on the commands available on the console -
```bash
==================================================================
| Basic Steps to test NAN Discovery & Datapath |
| |
| Below are short commands that use defaults, use 'help' |
| to see detailed command parameters available |
| |
| # NAN Discovery - |
| 1. To start NAN issue 'nan -S', to stop it use 'nan -T' |
| 2. Publish OR Subscribe a service using 'publish' OR 'subscribe'|
| 4. After service match, send a text to Peer with service id 5 - |
| > send -p 5 -t Hello |
| 5. Cancel an ongoing service with id 5 - |
| > publish -C -i 5 |
| |
| # NAN Datapath - |
| 1. Subscriber can initiate datapath using 'ndp -I -p [pub_id]' |
| 2. After NDP setup, use 'ping [Peer's IPv6]' to test datapath |
| 3. Terminate the NDP using 'ndp -D' |
| |
====================================================================
nan>
```
Mode detailed information about command parameters is given below -
1. **Starting NAN**
>nan> nan -S
*OR*
>nan> nan -S -p 2 -c 6 -w 5
>p - Master Preference
>c - Operating channel
>w - Warmup time
2. **Stopping NAN**
> nan> nan -T
3. **Publish a service with name 'ESP_NAN-Service'**
>nan> publish
*OR*
>nan> publish -n test -t 0 -f GREEN
>n - Service name
>t - Type (0: Unsolicited, 1: Solicited)
>f - Matching filter
4. **Subscribe to a NAN service 'ESP_NAN-Service'**
>nan> subscribe
*OR*
>nan> subscribe -n test -t 0 -f GREEN
>n - Service name
>t - Type (0: passive, 1: active)
>f - Matching filter
5. **Cancel a NAN service**
> Cancel a Subscribe service with Inst Id 5
>nan> subscribe -C -i 5
> Cancel a Publish service with Inst Id 5
>nan> publish -C -i 5
6. **Send a Follow-up message**
*To send message to amatched Publish OR Subscribe service*
>nan> send -p 5 -t Hello
>p - Peers service instance id
>t - Message
7. **Send a Datapath request**
*To Initiate NDP Req to the last matched Publisher -*
>nan> ndp -I -p 5
>p - Publish Id
9. **Start a IPv6 Ping with Peer**
>nan> ping FE80::E2E2:E6FF:FE7B:C132
10. **Terminate the current NAN Datapath**
>nan> ndp -T -d 5
>d - NDP id
## NAN Datapath Example Output using defaults
Device 1 : Publish a service with default configuration -
```
nan> nan -S
I (28125) NAN: State Init => Scanning
I (31135) NAN: Start own Cluster, Id 50:6f:9a:01:0e:76
I (31135) NAN: State Scanning => AnchorMaster
I (31135) nan_app: NAN Discovery started.
nan>
nan> publish
I (77245) nan_console: Publishing service 'ESP_NAN-Service' [Publish id - 5]
nan>
I (21775) nan_app: NDP confirmed with NDP id 1 [Peer IPv6 - FE80::E2E2:E6FF:FE6A:7AFE]
I (23625) nan_app: NAN Data Interface ready [IPv6 - fe80:0000:0000:0000:e2e2:e6ff:fe7b:c132, type - LINK_LOCAL]
I (30265) nan_app: NDP id 1 with Peer e0:e2:e6:6a:7a:fe terminated (reason: 0)
```
Device 2 : Subscribe a service with default configuration and start a datapath with matched Publisher
```
nan> nan -S
I (142915) NAN: State Init => Scanning
I (145915) NAN: Join Cluster with Id 50:6f:9a:01:0e:76
I (145915) NAN: State Scanning => AnchorMaster
I (145915) nan_app: NAN Discovery started.
nan>
nan> subscribe
I (159685) nan_console: Subscribed to Service 'ESP_NAN-Service' [Subscribe id - 5]
nan> I (159845) nan_app: Service matched with e0:e2:e6:7b:c1:32 [Peer Publish id - 5]
nan>
nan> ndp -I -p 5
I (196125) nan_console: Initiated NDP with e0:e2:e6:7b:c1:32 [NDP id - 1]
nan> E (196425) wifi:Committed slots 0x7fff0000 for Peer e0:e2:e6:7b:c1:32 on Channel 6
I (196425) nan_app: NDP confirmed with NDP id 1 [Peer IPv6 - FE80::E2E2:E6FF:FE7B:C132]
I (197625) nan_app: NAN Data Interface ready [IPv6 - fe80:0000:0000:0000:e2e2:e6ff:fe6a:7afe, type - LINK_LOCAL]
nan> ping FE80::E2E2:E6FF:FE7B:C132
I (212975) nan_console: Pinging Peer with IPv6 addr FE80::E2E2:E6FF:FE7B:C132
nan> W (213495) wifi:<ba-add>idx:5 (ifx:2, e0:e2:e6:7b:c1:32), tid:0, ssn:0, winSize:64
I (213555) nan_console: 64 bytes from FE80::E2E2:E6FF:FE7B:C132 icmp_seq=1 ttl=0 time=577 ms
I (214015) nan_console: 64 bytes from FE80::E2E2:E6FF:FE7B:C132 icmp_seq=2 ttl=0 time=40 ms
I (215095) nan_console: 64 bytes from FE80::E2E2:E6FF:FE7B:C132 icmp_seq=3 ttl=0 time=121 ms
I (216165) nan_console: 64 bytes from FE80::E2E2:E6FF:FE7B:C132 icmp_seq=4 ttl=0 time=190 ms
I (217445) nan_console: 64 bytes from FE80::E2E2:E6FF:FE7B:C132 icmp_seq=5 ttl=0 time=475 ms
I (217975) nan_console:
--- FE80::E2E2:E6FF:FE7B:C132 ping statistics ---
I (217975) nan_console: 5 packets transmitted, 5 received, 0% packet loss, time 1403ms
nan>
nan> ndp -T -d 1
nan> I (28175) nan_app: NDP id 1 with Peer e0:e2:e6:7b:c1:32 terminated (reason: 0)
```
## NAN Follow-up example output using advanced commands
Device 1 : Publisher uses a filter and responds to a message from a Subscriber
```
nan> nan -S
I (142915) NAN: State Init => Scanning
I (145915) NAN: Join Cluster with Id 50:6f:9a:01:0e:76
I (145915) NAN: State Scanning => AnchorMaster
I (145915) nan_app: NAN Discovery started.
nan>
nan> publish -n TEST -f GREEN
I (61935) nan_console: Publishing service 'TEST' [Publish id - 5]
nan>
I (93635) nan_app: Received message 'Hello' from Peer e0:e2:e6:6a:7a:fe [Peer Service id - 5]
nan> send -p 5 -t Welcome
I (114605) nan_console: Sent message 'Welcome' to NAN Peer e0:e2:e6:6a:7a:fe.
```
Device 2 : Subscriber uses a filter and sends a message to the matched Publisher
```
nan> nan -S
I (142915) NAN: State Init => Scanning
I (145915) NAN: Join Cluster with Id 50:6f:9a:01:0e:76
I (145915) NAN: State Scanning => AnchorMaster
I (145915) nan_app: NAN Discovery started.
nan>
nan> subscribe -n TEST -f GREEN
I (159685) nan_console: Subscribed to Service 'TEST' [Subscribe id - 5]
nan> I (159845) nan_app: Service matched with e0:e2:e6:7b:c1:32 [Peer Publish id - 5]
nan> send -p 5 -t Hello
I (99445) nan_console: Sent message 'Hello' to NAN Peer e0:e2:e6:7b:c1:32.
nan>
I (120685) nan_app: Received message 'Welcome' from Peer e0:e2:e6:7b:c1:32 [Peer Service id - 5]
```

Wyświetl plik

@ -0,0 +1,2 @@
idf_component_register(SRCS "nan_main.c"
INCLUDE_DIRS ".")

Wyświetl plik

@ -0,0 +1,621 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* NAN Console Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <string.h>
#include "nvs_flash.h"
#include "cmd_system.h"
#include "argtable3/argtable3.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_err.h"
#include "esp_wifi.h"
#include "esp_nan.h"
#include "esp_mac.h"
#include "esp_console.h"
#include "esp_private/wifi.h"
#include "esp_netif.h"
#include "esp_supplicant_utils.h"
#include "ping/ping_sock.h"
#include "lwip/inet.h"
#include "lwip/netdb.h"
#include "lwip/sockets.h"
typedef struct {
/* NAN Discovery parameters */
struct arg_lit *init;
struct arg_int *master_pref;
struct arg_int *op_channel;
struct arg_int *warmup_time;
struct arg_lit *deinit;
struct arg_end *end;
} wifi_nan_args_t;
static wifi_nan_args_t nan_args;
typedef struct {
/* NAN Publish parameters */
struct arg_str *name;
struct arg_int *type;
struct arg_str *filter;
struct arg_lit *ndp_ask;
struct arg_lit *cancel;
struct arg_int *id;
struct arg_end *end;
} wifi_publish_args_t;
static wifi_publish_args_t pub_args;
typedef struct {
/* NAN Subscribe parameters */
struct arg_str *name;
struct arg_int *type;
struct arg_str *filter;
struct arg_lit *cancel;
struct arg_int *id;
struct arg_end *end;
} wifi_subscribe_args_t;
static wifi_subscribe_args_t sub_args;
typedef struct {
/* NAN Follow-up parameters */
struct arg_int *own_id;
struct arg_int *peer_id;
struct arg_str *mac_addr;
struct arg_str *text;
struct arg_end *end;
} wifi_followup_args_t;
static wifi_followup_args_t fup_args;
typedef struct {
/* NDP Init/Deinit parameters */
struct arg_lit *init;
struct arg_int *peer_pub_id;
struct arg_str *mac_addr;
/* NDP Accept/Reject parameters */
struct arg_lit *accept;
struct arg_lit *reject;
/* NDP Terminate parameters */
struct arg_lit *terminate;
struct arg_int *ndp_id;
struct arg_end *end;
} wifi_ndp_args_t;
static wifi_ndp_args_t ndp_args;
static struct {
struct arg_str *host;
struct arg_end *end;
} ping_args;
static const char *TAG = "nan_console";
static esp_netif_t *g_nan_netif;
#define NAN_EXAMPLE_SERVICE_NAME "ESP_NAN-Service"
static void cmd_ping_on_ping_success(esp_ping_handle_t hdl, void *args)
{
uint8_t ttl;
uint16_t seqno;
uint32_t elapsed_time, recv_len;
ip_addr_t target_addr;
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
esp_ping_get_profile(hdl, ESP_PING_PROF_TTL, &ttl, sizeof(ttl));
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len));
esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time));
ESP_LOGI(TAG, "%lu bytes from %s icmp_seq=%u ttl=%u time=%lu ms",
recv_len, ipaddr_ntoa((ip_addr_t *)&target_addr), seqno, ttl, elapsed_time);
}
static void cmd_ping_on_ping_timeout(esp_ping_handle_t hdl, void *args)
{
uint16_t seqno;
ip_addr_t target_addr;
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
ESP_LOGI(TAG, "From %s icmp_seq=%d timeout", ipaddr_ntoa((ip_addr_t *)&target_addr), seqno);
}
static void cmd_ping_on_ping_end(esp_ping_handle_t hdl, void *args)
{
ip_addr_t target_addr;
uint32_t transmitted;
uint32_t received;
uint32_t total_time_ms;
esp_ping_get_profile(hdl, ESP_PING_PROF_REQUEST, &transmitted, sizeof(transmitted));
esp_ping_get_profile(hdl, ESP_PING_PROF_REPLY, &received, sizeof(received));
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
esp_ping_get_profile(hdl, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms));
uint32_t loss = (uint32_t)((1 - ((float)received) / transmitted) * 100);
ESP_LOGI(TAG, "\n--- %s ping statistics ---", inet6_ntoa(*ip_2_ip6(&target_addr)));
ESP_LOGI(TAG, "%lu packets transmitted, %lu received, %lu%% packet loss, time %lums",
transmitted, received, loss, total_time_ms);
// delete the ping sessions, so that we clean up all resources and can create a new ping session
// we don't have to call delete function in the callback, instead we can call delete function from other tasks
esp_ping_delete_session(hdl);
}
static int do_ping_cmd(int argc, char **argv)
{
esp_ping_config_t config = ESP_PING_DEFAULT_CONFIG();
config.task_stack_size = 4096;
ip_addr_t target_addr = {0};
int nerrors = arg_parse(argc, argv, (void **)&ping_args);
if (nerrors != 0) {
arg_print_errors(stderr, ping_args.end, argv[0]);
return 1;
}
if (!g_nan_netif) {
ESP_LOGE(TAG, "NAN not started successfully");
return 1;
}
if (ping_args.host->count) {
/* convert ip6 string to ip6 address */
ipaddr_aton(ping_args.host->sval[0], &target_addr);
} else {
ESP_LOGE(TAG, "No Active datapath for ping");
return 1;
}
config.target_addr = target_addr;
config.interface = esp_netif_get_netif_impl_index(g_nan_netif);
/* set callback functions */
esp_ping_callbacks_t cbs = {
.on_ping_success = cmd_ping_on_ping_success,
.on_ping_timeout = cmd_ping_on_ping_timeout,
.on_ping_end = cmd_ping_on_ping_end,
.cb_args = NULL
};
esp_ping_handle_t ping;
if (esp_ping_new_session(&config, &cbs, &ping) == ESP_OK) {
ESP_LOGI(TAG, "Pinging Peer with IPv6 addr %s", ipaddr_ntoa((ip_addr_t *)&target_addr));
esp_ping_start(ping);
return 0;
} else {
ESP_LOGI(TAG, "Failed to ping Peer with IPv6 addr %s", ipaddr_ntoa((ip_addr_t *)&target_addr));
return 1;
}
}
void initialise_wifi(void)
{
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM) );
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
ESP_ERROR_CHECK(esp_wifi_start());
}
static int wifi_cmd_nan_disc(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &nan_args);
esp_err_t ret;
if (nerrors != 0) {
arg_print_errors(stderr, nan_args.end, argv[0]);
return 1;
}
if ((nan_args.init->count == 0) && (nan_args.deinit->count == 0)) {
ESP_LOGE(TAG, "Invalid NAN Discovery command");
return 1;
}
if (nan_args.init->count) {
wifi_nan_config_t nan_cfg = WIFI_NAN_CONFIG_DEFAULT();
if (nan_args.master_pref->count) {
nan_cfg.master_pref = nan_args.master_pref->ival[0];
}
if (nan_args.op_channel->count) {
nan_cfg.op_channel = nan_args.op_channel->ival[0];
}
if (nan_args.warmup_time->count) {
nan_cfg.warm_up_sec = nan_args.warmup_time->ival[0];
}
g_nan_netif = esp_netif_create_default_wifi_nan();
if ((esp_wifi_nan_start(&nan_cfg)) != ESP_OK) {
ESP_LOGI(TAG, "Failed to start NAN");
esp_netif_destroy_default_wifi(g_nan_netif);
return 1;
}
return 0;
}
if (nan_args.deinit->count) {
ret = esp_wifi_nan_stop();
if (ret != ESP_OK) {
ESP_LOGI(TAG, "Failed to stop NAN");
return 1;
}
esp_netif_destroy_default_wifi(g_nan_netif);
}
return 0;
}
static int wifi_cmd_nan_publish(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &pub_args);
uint32_t pub_id;
bool ndp_resp_needed = false;
if (nerrors != 0) {
arg_print_errors(stderr, pub_args.end, argv[0]);
return 1;
}
if (pub_args.cancel->count && pub_args.id->count) {
pub_id = pub_args.id->ival[0];
if (esp_wifi_nan_cancel_service(pub_id) != ESP_OK) {
ESP_LOGE(TAG, "Failed to cancel service");
return 1;
}
return 0;
}
wifi_nan_publish_cfg_t publish = {
.service_name = NAN_EXAMPLE_SERVICE_NAME,
.type = NAN_PUBLISH_UNSOLICITED,
.single_replied_event = 1,
};
if (pub_args.name->count) {
strlcpy(publish.service_name, pub_args.name->sval[0], ESP_WIFI_MAX_SVC_NAME_LEN);
}
if (pub_args.type->count && pub_args.type->ival[0] == 1) {
publish.type = NAN_PUBLISH_SOLICITED;
}
if (pub_args.filter->count) {
strlcpy(publish.matching_filter, pub_args.filter->sval[0], ESP_WIFI_MAX_SVC_NAME_LEN);
}
if (pub_args.ndp_ask->count) {
ndp_resp_needed = true;
ESP_LOGI(TAG, "Issue 'ndp -A -d [id]' to Accept OR 'ndp -R -d [id]' to Reject incoming NDP requests");
}
if (!esp_wifi_nan_publish_service(&publish, ndp_resp_needed)) {
return 1;
}
return 0;
}
static int wifi_cmd_nan_subscribe(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &sub_args);
uint32_t sub_id;
if (nerrors != 0) {
arg_print_errors(stderr, sub_args.end, argv[0]);
return 1;
}
if (sub_args.cancel->count && sub_args.id->count) {
sub_id = sub_args.id->ival[0];
if (esp_wifi_nan_cancel_service(sub_id) != ESP_OK) {
ESP_LOGE(TAG, "Failed to cancel service");
return 1;
}
return 0;
}
wifi_nan_subscribe_cfg_t subscribe = {
.service_name = NAN_EXAMPLE_SERVICE_NAME,
.type = NAN_SUBSCRIBE_PASSIVE,
.single_match_event = true,
};
if (sub_args.name->count) {
strlcpy(subscribe.service_name, sub_args.name->sval[0], ESP_WIFI_MAX_SVC_NAME_LEN);
}
if (sub_args.type->count && sub_args.type->ival[0] == 1) {
subscribe.type = NAN_SUBSCRIBE_ACTIVE;
}
if (sub_args.filter->count) {
strlcpy(subscribe.matching_filter, sub_args.filter->sval[0], ESP_WIFI_MAX_SVC_NAME_LEN);
}
if (!esp_wifi_nan_subscribe_service(&subscribe)) {
return 1;
}
return 0;
}
static int wifi_cmd_nan_followup(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &fup_args);
if (nerrors != 0) {
arg_print_errors(stderr, fup_args.end, argv[0]);
return 1;
}
wifi_nan_followup_params_t fup = {0};
if (fup_args.own_id->count) {
fup.inst_id = fup_args.own_id->ival[0];
}
if (!fup_args.peer_id->count && !fup_args.mac_addr->count) {
ESP_LOGE(TAG, "Missing peer's service instance id or peer's MAC.");
return 1;
}
if (fup_args.peer_id->count) {
fup.peer_inst_id = fup_args.peer_id->ival[0];
}
if (fup_args.mac_addr->count &&
esp_supplicant_str_to_mac((char *)fup_args.mac_addr->sval[0], fup.peer_mac) != ESP_OK) {
return 1;
}
if (fup_args.text->count) {
strlcpy(fup.svc_info, fup_args.text->sval[0], ESP_WIFI_MAX_SVC_INFO_LEN);
}
if (esp_wifi_nan_send_message(&fup) != ESP_OK) {
return 1;
}
return 0;
}
static int wifi_cmd_ndp(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &ndp_args);
if (nerrors != 0) {
arg_print_errors(stderr, ndp_args.end, argv[0]);
return 1;
}
if ((ndp_args.init->count == 0) && (ndp_args.terminate->count == 0) &&
(ndp_args.accept->count == 0) && (ndp_args.reject->count == 0)) {
ESP_LOGE(TAG, "Invalid NDP command");
return 1;
}
if (ndp_args.init->count) {
wifi_nan_datapath_req_t ndp_req = {0};
ndp_req.confirm_required = true;
if (!ndp_args.peer_pub_id->count && !ndp_args.mac_addr->count) {
ESP_LOGE(TAG, "Missing Peer's publish id or peer's MAC");
return 1;
}
if (ndp_args.peer_pub_id->count) {
ndp_req.pub_id = ndp_args.peer_pub_id->ival[0];
}
if (ndp_args.mac_addr->count &&
esp_supplicant_str_to_mac((char *)ndp_args.mac_addr->sval[0], ndp_req.peer_mac) != ESP_OK) {
return 1;
}
if (!esp_wifi_nan_datapath_req(&ndp_req)) {
return 1;
}
goto out;
}
if (ndp_args.accept->count || ndp_args.reject->count) {
wifi_nan_datapath_resp_t ndp_resp = {0};
ndp_resp.accept = ndp_args.accept->count ? true : false;
if (ndp_args.ndp_id->count) {
ndp_resp.ndp_id = ndp_args.ndp_id->ival[0];
} else {
ESP_LOGE(TAG, "Missing own NDP id, add using '-d' parameter");
return 1;
}
esp_wifi_nan_datapath_resp(&ndp_resp);
goto out;
}
if (ndp_args.terminate->count) {
wifi_nan_datapath_end_req_t ndp_end = {0};
if (ndp_args.ndp_id->count) {
ndp_end.ndp_id = ndp_args.ndp_id->ival[0];
} else {
ESP_LOGE(TAG, "Missing own NDP id, add using '-d' parameter");
return 1;
}
esp_wifi_nan_datapath_end(&ndp_end);
goto out;
}
out:
return 0;
}
void register_nan(void)
{
/* NAN Init/Deinit parameters */
nan_args.init = arg_lit0("S", "start", "NAN Start");
nan_args.deinit = arg_lit0("T", "stop", "NAN Stop");
nan_args.master_pref = arg_int0("p", "mast_pref", "<1-254>", "NAN Master Preference");
nan_args.op_channel = arg_int0("c", "op_chan", "<1-11>", "NAN Operating Channe");
nan_args.warmup_time = arg_int0("w", "warmup", "<5-120>", "NAN Warmup Time in Sec");
nan_args.end = arg_end(1);
const esp_console_cmd_t nan_cmd = {
.command = "nan",
.help = "NAN Discovery command",
.hint = NULL,
.func = &wifi_cmd_nan_disc,
.argtable = &nan_args
};
ESP_ERROR_CHECK( esp_console_cmd_register(&nan_cmd) );
/* NAN Publish parameters */
pub_args.name = arg_str0("n", "name", "<name>", "Name for the service");
pub_args.type = arg_int0("t", "type", "<0/1>", "0 - Unsolicited(Default), 1 - Solicited");
pub_args.filter = arg_str0("f", "filter", "<filter>", "Comma separated Matching Filter");
pub_args.ndp_ask = arg_lit0("a", "ndp_ask", "Explicitly Accept OR Reject incoming NDP Requests");
/* NAN Publish cancel parameters */
pub_args.cancel = arg_lit0("C", "cancel", "Cancel a service");
pub_args.id = arg_int0("i", "id", "<0-255>", "Publish service id");
pub_args.end = arg_end(1);
const esp_console_cmd_t pub_cmd = {
.command = "publish",
.help = "NAN Publish Service command",
.hint = NULL,
.func = &wifi_cmd_nan_publish,
.argtable = &pub_args
};
ESP_ERROR_CHECK( esp_console_cmd_register(&pub_cmd) );
/* NAN Subscribe parameters */
sub_args.name = arg_str0("n", "name", "<name>", "Name for the service");
sub_args.type = arg_int0("t", "type", "<0/1>", "0 - Passive(Default), 1 - Active");
sub_args.filter = arg_str0("f", "filter", "<filter>", "Comma separated Matching Filter");
/* NAN Subscribe cancel parameters */
sub_args.cancel = arg_lit0("C", "cancel", "Cancel a service");
sub_args.id = arg_int0("i", "id", "<0-255>", "Subscribe service id");
sub_args.end = arg_end(1);
const esp_console_cmd_t sub_cmd = {
.command = "subscribe",
.help = "NAN Subscribe to Service command",
.hint = NULL,
.func = &wifi_cmd_nan_subscribe,
.argtable = &sub_args
};
ESP_ERROR_CHECK( esp_console_cmd_register(&sub_cmd) );
/* NAN Follow-up parameters */
fup_args.own_id = arg_int0("i", "own_id", "<0-255>", "Own service id");
fup_args.peer_id = arg_int0("p", "peer_id", "<0-255>", "Peer's service id");
fup_args.mac_addr = arg_str0("m", "mac", "<mac>", "Peer's MAC Address");
fup_args.text = arg_str1("t", "text", "<info>", "Text to be shared as Service Info");
fup_args.end = arg_end(1);
const esp_console_cmd_t fup_cmd = {
.command = "send",
.help = "NAN Follow-up command",
.hint = NULL,
.func = &wifi_cmd_nan_followup,
.argtable = &fup_args
};
ESP_ERROR_CHECK( esp_console_cmd_register(&fup_cmd) );
/* NDP Init/Deinit parameters */
ndp_args.init = arg_lit0("I", "initiate", "NDP Initiate");
ndp_args.peer_pub_id = arg_int0("p", "peer_pub_id", "<1-254>", "Peer's Publish Id");
ndp_args.mac_addr = arg_str0("m", "mac", "<mac>", "Peer's MAC Address");
/* NDP Accept/Reject/Terminate parameters */
ndp_args.accept = arg_lit0("A", "accept", "Accept NDP Request");
ndp_args.reject = arg_lit0("R", "reject", "Reject NDP Request");
ndp_args.terminate = arg_lit0("T", "terminate", "NDP Terminate");
ndp_args.ndp_id = arg_int0("d", "ndp_id", "<1-254>", "NDP ID");
ndp_args.end = arg_end(1);
const esp_console_cmd_t ndp_cmd = {
.command = "ndp",
.help = "NDP command",
.hint = NULL,
.func = &wifi_cmd_ndp,
.argtable = &ndp_args
};
ESP_ERROR_CHECK( esp_console_cmd_register(&ndp_cmd) );
ping_args.host = arg_str1(NULL, NULL, "<host>", "Host address");
ping_args.end = arg_end(1);
const esp_console_cmd_t ping_cmd = {
.command = "ping",
.help = "send ICMP ECHO_REQUEST to network hosts",
.hint = NULL,
.func = &do_ping_cmd,
.argtable = &ping_args
};
ESP_ERROR_CHECK(esp_console_cmd_register(&ping_cmd));
}
void app_main(void)
{
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK( ret );
initialise_wifi();
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
repl_config.prompt = "nan>";
// init console REPL environment
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
/* Register commands */
register_system();
register_nan();
printf("\n ==================================================================\n");
printf(" | Basic Steps to test NAN Discovery & Datapath |\n");
printf(" | |\n");
printf(" | Below are short commands that use defaults, use 'help' |\n");
printf(" | to see detailed command parameters available |\n");
printf(" | |\n");
printf(" | # NAN Discovery - |\n");
printf(" | 1. To start NAN issue 'nan -S', to stop it use 'nan -T' |\n");
printf(" | 2. Publish OR Subscribe a service with name 'TEST' - |\n");
printf(" | > publish -n TEST |\n");
printf(" | > subscribe -n TEST |\n");
printf(" | 4. After service match, send a text to Peer with service id 5 - |\n");
printf(" | > send -p 5 -t Hello |\n");
printf(" | 5. Cancel an ongoing service with id 5 - |\n");
printf(" | > publish -C -i 5 |\n");
printf(" | |\n");
printf(" | # NAN Datapath - |\n");
printf(" | 1. Subscriber can initiate datapath using 'ndp -I -p [pub_id]' |\n");
printf(" | 2. After NDP setup, use 'ping [Peer's IPv6]' to test datapath |\n");
printf(" | 3. Terminate the NDP using 'ndp -T' |\n");
printf(" | |\n");
printf(" ====================================================================\n\n");
// start console REPL
ESP_ERROR_CHECK(esp_console_start_repl(repl));
}

Wyświetl plik

@ -0,0 +1 @@
CONFIG_ESP_WIFI_NAN_ENABLE=y

Wyświetl plik

@ -0,0 +1,6 @@
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(nan_publisher)

Wyświetl plik

@ -0,0 +1,55 @@
| Supported Targets | ESP32 | ESP32-S2 |
| ----------------- | ----- | -------- |
# NAN Publisher Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
## Introduction
Neighbor Awareness Networking (NAN) is a protocol that allows Wi-Fi devices to discover services in their proximity. NAN uses direct device-to-device communication and does not require any Internet or AP connection.
Multiple NAN devices which are in the vicinity will form a NAN cluster which allows them to communicate with each other. Devices within a NAN cluster can advertise or look for services using NAN Service Discovery protocols.
A Publisher advertises a service and a Subscriber searches for a service. A subscriber either listens passively (Passive mode) or sends out broadcast Action frames (Active mode). Similarly a publisher either broadcasts its services (Unsolicited mode) or replies to Active subscribers (Solicited Mode). Matching of services is done by service name and optionally matching filters.
## How to use example
Publishing and Subscribing is possible dynamically on the NAN Interface. For simplicity this example demonstrates only the Publish method with some configuration options. Use option `Example Configuration -> NAN Service Name` for naming the Publish service. Select `Publish Type` and optionally set the `Matching Filter` and `Reply message` in the same menu. Another device in the vicinity running the Subscriber example will discover the Publisher. A service match happens when the service name (case insensitive) matches as well as the Matching filter(s) matche(s) (case sensitive). After this the Subscriber may send a Follow-up or initiate Datapath with the Publisher for further communication. The Publisher will send a reply to the Follow-up and will accept the Datapath request given that it has enough resources.
## Example Output
Usecase 1 : Publisher with a Follow-up exchange with a Subscriber
```
I (449) phy_init: phy_version 1800,e7ef680,Apr 13 2021,11:45:08
I (549) wifi:mode : NAN (18:fe:34:72:50:c8)
Set Vif NAN
I (559) NAN: State Init => Scanning
I (3559) NAN: Start own Cluster, Id 50:6f:9a:01:cc:4d
I (3559) wifi:Init max length of beacon: 752/752
I (3559) wifi:Init max length of beacon: 752/752
I (3559) NAN: State Scanning => AnchorMaster
I (3794) nan_app: NAN Discovery started.
I (5604) NAN: State Master => AnchorMaster
I (8244) nan_app: Received message 'Hello' from Peer e0:e2:e6:6a:7a:fe [Peer Service id - 5]
I (8244) nan_pub: Replied 'Welcome' to the Subscriber...
```
Usecase 2 : Publisher accepting Datapath request by a Subscriber
```
I (449) phy_init: phy_version 1800,e7ef680,Apr 13 2021,11:45:08
I (559) wifi:mode : NAN (18:fe:34:72:50:c8)
Set Vif NAN
I (559) NAN: State Init => Scanning
I (3559) NAN: Join Cluster with Id 50:6f:9a:01:cc:4d
I (3559) wifi:Init max length of beacon: 752/752
I (3559) wifi:Init max length of beacon: 752/752
I (3559) NAN: State Scanning => Master
I (3559) nan_pub: NAN Discovery started.
I (3569) nan_pub: Publishing Service test with ID 5
E (18809) wifi:Committed slots 0x3fff0000 for Peer 18:fe:34:72:50:b3 on Channel 6
I (18809) nan_pub: Datapath setup with 18:fe:34:72:50:b3
I (20349) nan_pub: Got IPv6 event: Interface "nan_pub: nan" address: fe80:0000:0000:0000:1afe:34ff:fe72:50ca, type: ESP_IP6_ADDR_IS_LINK_LOCAL
W (20929) wifi:<ba-add>idx:5 (ifx:2, 18:fe:34:72:50:b3), tid:0, ssn:0, winSize:64
```

Wyświetl plik

@ -0,0 +1,2 @@
idf_component_register(SRCS "publisher_main.c"
INCLUDE_DIRS ".")

Wyświetl plik

@ -0,0 +1,26 @@
menu "Example Configuration"
config ESP_WIFI_NAN_SVC_NAME
string "NAN Service Name"
default "test"
choice
prompt "Publish Type"
default EXAMPLE_NAN_PUBLISH_UNSOLICITED
config EXAMPLE_NAN_PUBLISH_UNSOLICITED
bool "UNSOLICITED"
config EXAMPLE_NAN_PUBLISH_SOLICITED
bool "SOLICITED"
endchoice
config ESP_WIFI_NAN_MATCHING_FILTER
string "Matching Filter"
default ""
config ESP_WIFI_NAN_SERVICE_MESSAGE
string "Reply message"
default "Welcome"
help
Send a reply to the Follow Up sent by a Subscriber
endmenu

Wyświetl plik

@ -0,0 +1,119 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* WiFi Aware (NAN) Publisher Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_nan.h"
#include "esp_mac.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#define EXAMPLE_NAN_SERV_NAME CONFIG_ESP_WIFI_NAN_SVC_NAME
#define EXAMPLE_NAN_MATCHING_FILTER CONFIG_ESP_WIFI_NAN_MATCHING_FILTER
#ifdef CONFIG_ESP_WIFI_NAN_SERVICE_MESSAGE
#define EXAMPLE_NAN_SVC_MSG CONFIG_ESP_WIFI_NAN_SERVICE_MESSAGE
#else
#define EXAMPLE_NAN_SVC_MSG "Welcome"
#endif
static EventGroupHandle_t nan_event_group;
static int NAN_RECEIVE = BIT0;
uint8_t g_peer_inst_id;
static void nan_receive_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
wifi_event_nan_receive_t *evt = (wifi_event_nan_receive_t *)event_data;
g_peer_inst_id = evt->peer_inst_id;
xEventGroupSetBits(nan_event_group, NAN_RECEIVE);
}
void wifi_nan_publish(void)
{
nan_event_group = xEventGroupCreate();
esp_event_handler_instance_t instance_any_id;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
WIFI_EVENT_NAN_RECEIVE,
&nan_receive_event_handler,
NULL,
&instance_any_id));
/* Start NAN Discovery */
wifi_nan_config_t nan_cfg = WIFI_NAN_CONFIG_DEFAULT();
esp_netif_create_default_wifi_nan();
esp_wifi_nan_start(&nan_cfg);
/* Publish a service */
uint8_t pub_id;
wifi_nan_publish_cfg_t publish_cfg = {
.service_name = EXAMPLE_NAN_SERV_NAME,
#if CONFIG_EXAMPLE_NAN_PUBLISH_UNSOLICITED
.type = NAN_PUBLISH_UNSOLICITED,
#else
.type = NAN_PUBLISH_SOLICITED,
#endif
.matching_filter = EXAMPLE_NAN_MATCHING_FILTER,
.single_replied_event = 1,
};
pub_id = esp_wifi_nan_publish_service(&publish_cfg, false);
if (pub_id == 0) {
return;
}
while (1) {
EventBits_t bits = xEventGroupWaitBits(nan_event_group, NAN_RECEIVE, pdFALSE, pdFALSE, portMAX_DELAY);
if (bits & NAN_RECEIVE) {
xEventGroupClearBits(nan_event_group, NAN_RECEIVE);
wifi_nan_followup_params_t fup = {0};
fup.inst_id = pub_id,
fup.peer_inst_id = g_peer_inst_id,
strlcpy(fup.svc_info, EXAMPLE_NAN_SVC_MSG, ESP_WIFI_MAX_SVC_INFO_LEN);
/* Reply to the message from a subscriber */
esp_wifi_nan_send_message(&fup);
}
vTaskDelay(10);
}
}
void initialise_wifi(void)
{
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM) );
}
void app_main(void)
{
//Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
initialise_wifi();
wifi_nan_publish();
}

Wyświetl plik

@ -0,0 +1 @@
CONFIG_ESP_WIFI_NAN_ENABLE=y

Wyświetl plik

@ -0,0 +1,6 @@
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(nan_subscriber)

Wyświetl plik

@ -0,0 +1,65 @@
| Supported Targets | ESP32 | ESP32-S2 |
| ----------------- | ----- | -------- |
# NAN Subscriber Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
## Introduction
Neighbor Awareness Networking (NAN) is a protocol that allows Wi-Fi devices to discover services in their proximity. NAN uses direct device-to-device communication and does not require any Internet or AP connection.
Multiple NAN devices which are in the vicinity will form a NAN cluster which allows them to communicate with each other. Devices within a NAN cluster can advertise or look for services using NAN Service Discovery protocols.
A Publisher advertises a service and a Subscriber searches for a service. A subscriber either listens passively (Passive mode) or sends out broadcast Action frames (Active mode). Similarly a publisher either broadcasts its services (Unsolicited mode) or replies to Active subscribers (Solicited Mode). Matching of services is done by service name and optionally matching filters.
## How to use example
Publishing and Subscribing is possible dynamically on the NAN Interface. For simplicity this example demonstrates only the Subscribe method with some configuration options. Use option `Example Configuration -> NAN Service Name` for naming a service to subscribe to. Select `Subscribe Type` and optionally set the `Matching Filter`. Using option `Communication Type` it's possible to either send a message using Follow-up or initiate a datapath with the Publisher. The device will search for another device in the vicinity Publishing the same service. A service match happens when the service name (case insensitive) matches as well as the Matching filter(s) matche(s) (case sensitive). After this the Subscriber will initiate further communication as par configuration.
## Example Output
Usecase 1 : Subscriber sending a Follow-up to the Publisher
```
I (449) phy_init: phy_version 1800,e7ef680,Apr 13 2021,11:45:08
I (549) wifi:mode : NAN (18:fe:34:72:50:b1)
Set Vif NAN
I (549) NAN: State Init => Scanning
I (3549) NAN: Join Cluster with Id 50:6f:9a:01:cc:4d
I (3549) wifi:Init max length of beacon: 752/752
I (3549) wifi:Init max length of beacon: 752/752
I (3559) NAN: State Scanning => AnchorMaster
I (3762) nan_app: NAN Discovery started.
I (4222) nan_sub: NAN Publisher found for Serv ID 5
I (4222) nan_app: Service matched with e0:e2:e6:7b:c1:32 [Peer Publish id - 5]
I (4222) nan_sub: Sending message 'Hello' to Publisher e0:e2:e6:7b:c1:32 ...
I (4762) nan_app: Received message 'Welcome' from Peer e0:e2:e6:7b:c1:32 [Peer Service id - 5]
```
Usecase 2 : Subscriber setting up Datapath with the Publisher, then testing IPv6 ping
```
I (452) phy_init: phy_version 1800,e7ef680,Apr 13 2021,11:45:08
I (552) wifi:mode : NAN (18:fe:34:72:50:b1)
Set Vif NAN
I (552) NAN: State Init => Scanning
I (3552) NAN: Join Cluster with Id 50:6f:9a:01:cc:4d
I (3562) wifi:Init max length of beacon: 752/752
I (3562) wifi:Init max length of beacon: 752/752
I (3562) NAN: State Scanning => AnchorMaster
I (3562) nan_sub: NAN Discovery started.
I (3572) nan_sub: Subscribing to Service test with ID 5
I (3612) nan_sub: NAN Publisher found for Serv ID 5
E (3612) wifi:Committed slots 0x7fff0000 for Peer 18:fe:34:72:50:ca on Channel 6
I (3622) nan_sub: Datapath setup with 18:fe:34:72:50:ca
I (5452) nan_sub: Got IPv6 event: Interface "nan_sub: nan" address: fe80:0000:0000:0000:1afe:34ff:fe72:50b3, type: ESP_IP6_ADDR_IS_LINK_LOCAL
I (5452) nan_sub: Pinging Peer with IPv6 addr FE80::1AFE:34FF:FE72:50CA
W (5722) wifi:<ba-add>idx:5 (ifx:2, 18:fe:34:72:50:ca), tid:0, ssn:0, winSize:64
I (5742) nan_sub: 64 bytes from FE80::1AFE:34FF:FE72:50CA icmp_seq=1 ttl=0 time=278 ms
I (7462) nan_sub: 64 bytes from FE80::1AFE:34FF:FE72:50CA icmp_seq=2 ttl=0 time=2 ms
I (7462) nan_sub: 64 bytes from FE80::1AFE:34FF:FE72:50CA icmp_seq=3 ttl=0 time=2 ms
I (8462) nan_sub: 64 bytes from FE80::1AFE:34FF:FE72:50CA icmp_seq=4 ttl=0 time=1 ms
I (9462) nan_sub: 64 bytes from FE80::1AFE:34FF:FE72:50CA icmp_seq=5 ttl=0 time=1 ms
I (10462) nan_sub:
--- FE80::1AFE:34FF:FE72:50CA ping statistics ---
I (10462) nan_sub: 5 packets transmitted, 4 received, 19% packet loss, time 1281ms
```

Wyświetl plik

@ -0,0 +1,2 @@
idf_component_register(SRCS "subscriber_main.c"
INCLUDE_DIRS ".")

Wyświetl plik

@ -0,0 +1,36 @@
menu "Example Configuration"
config ESP_WIFI_NAN_SVC_NAME
string "NAN Service Name"
default "test"
choice
prompt "Subscribe Type"
default EXAMPLE_NAN_SUBSCRIBE_PASSIVE
config EXAMPLE_NAN_SUBSCRIBE_PASSIVE
bool "PASSIVE"
config EXAMPLE_NAN_SUBSCRIBE_ACTIVE
bool "ACTIVE"
endchoice
config ESP_WIFI_NAN_MATCHING_FILTER
string "Matching Filter"
default ""
choice
prompt "Communication Type"
default EXAMPLE_NAN_SEND_MESSAGE
config EXAMPLE_NAN_SEND_MESSAGE
bool "Send Message"
config EXAMPLE_NAN_SEND_PING
bool "IPv6 Ping"
endchoice
config ESP_WIFI_NAN_SERVICE_MESSAGE
depends on EXAMPLE_NAN_SEND_MESSAGE
string "Message"
default "Hello"
help
Send a message to the Publisher using NAN Follow Up
endmenu

Wyświetl plik

@ -0,0 +1,240 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* WiFi Aware (NAN) Subscriber Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_nan.h"
#include "esp_mac.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "ping/ping_sock.h"
#define EXAMPLE_NAN_SERV_NAME CONFIG_ESP_WIFI_NAN_SVC_NAME
#define EXAMPLE_NAN_MATCHING_FILTER CONFIG_ESP_WIFI_NAN_MATCHING_FILTER
#ifdef CONFIG_ESP_WIFI_NAN_SERVICE_MESSAGE
#define EXAMPLE_NAN_SVC_MSG CONFIG_ESP_WIFI_NAN_SERVICE_MESSAGE
#else
#define EXAMPLE_NAN_SVC_MSG "Hello"
#endif
static const char *TAG = "nan_sub";
static EventGroupHandle_t nan_event_group;
const int NAN_SERVICE_MATCH = BIT0;
const int NDP_CONFIRMED = BIT1;
const int NDP_FAILED = BIT2;
static wifi_event_nan_svc_match_t g_svc_match_evt;
#ifdef CONFIG_EXAMPLE_NAN_SEND_PING
static uint8_t g_peer_ndi[6];
static void cmd_ping_on_ping_success(esp_ping_handle_t hdl, void *args)
{
uint8_t ttl;
uint16_t seqno;
uint32_t elapsed_time, recv_len;
ip_addr_t target_addr;
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
esp_ping_get_profile(hdl, ESP_PING_PROF_TTL, &ttl, sizeof(ttl));
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len));
esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time));
ESP_LOGI(TAG, "%lu bytes from %s icmp_seq=%u ttl=%u time=%lu ms",
recv_len, ipaddr_ntoa((ip_addr_t *)&target_addr), seqno, ttl, elapsed_time);
}
static void cmd_ping_on_ping_timeout(esp_ping_handle_t hdl, void *args)
{
uint16_t seqno;
ip_addr_t target_addr;
esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
ESP_LOGI(TAG, "From %s icmp_seq=%d timeout", ipaddr_ntoa((ip_addr_t *)&target_addr), seqno);
}
static void cmd_ping_on_ping_end(esp_ping_handle_t hdl, void *args)
{
ip_addr_t target_addr;
uint32_t transmitted;
uint32_t received;
uint32_t total_time_ms;
esp_ping_get_profile(hdl, ESP_PING_PROF_REQUEST, &transmitted, sizeof(transmitted));
esp_ping_get_profile(hdl, ESP_PING_PROF_REPLY, &received, sizeof(received));
esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
esp_ping_get_profile(hdl, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms));
uint32_t loss = (uint32_t)((1 - ((float)received) / transmitted) * 100);
ESP_LOGI(TAG, "\n--- %s ping statistics ---", inet6_ntoa(*ip_2_ip6(&target_addr)));
ESP_LOGI(TAG, "%lu packets transmitted, %lu received, %lu%% packet loss, time %lums",
transmitted, received, loss, total_time_ms);
// delete the ping sessions, so that we clean up all resources and can create a new ping session
// we don't have to call delete function in the callback, instead we can call delete function from other tasks
esp_ping_delete_session(hdl);
}
static void nan_ndp_confirmed_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
wifi_event_ndp_confirm_t *evt = (wifi_event_ndp_confirm_t *)event_data;
if (evt->status == NDP_STATUS_REJECTED) {
ESP_LOGI(TAG, "NDP request to Peer "MACSTR" rejected [NDP ID - %d]", MAC2STR(evt->peer_nmi), evt->ndp_id);
xEventGroupSetBits(nan_event_group, NDP_FAILED);
} else {
memcpy(g_peer_ndi, evt->peer_ndi, sizeof(g_peer_ndi));
xEventGroupSetBits(nan_event_group, NDP_CONFIRMED);
}
}
static void ping_nan_peer(esp_netif_t *netif)
{
esp_ping_config_t config = ESP_PING_DEFAULT_CONFIG();
config.task_stack_size = 4096;
ip_addr_t target_addr = {0};
esp_wifi_nan_get_ipv6_linklocal_from_mac(&target_addr.u_addr.ip6, g_peer_ndi);
target_addr.type = IPADDR_TYPE_V6;
config.target_addr = target_addr;
config.interface = esp_netif_get_netif_impl_index(netif);
/* set callback functions */
esp_ping_callbacks_t cbs = {
.on_ping_success = cmd_ping_on_ping_success,
.on_ping_timeout = cmd_ping_on_ping_timeout,
.on_ping_end = cmd_ping_on_ping_end,
.cb_args = NULL
};
esp_ping_handle_t ping;
if (esp_ping_new_session(&config, &cbs, &ping) == ESP_OK) {
ESP_LOGI(TAG, "Pinging Peer with IPv6 addr %s", ipaddr_ntoa((ip_addr_t*)&target_addr));
esp_ping_start(ping);
} else {
ESP_LOGI(TAG, "Failed to ping Peer with IPv6 addr %s", ipaddr_ntoa((ip_addr_t*)&target_addr));
}
}
#endif
static void nan_svc_match_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
wifi_event_nan_svc_match_t *evt = (wifi_event_nan_svc_match_t *)event_data;
ESP_LOGI(TAG, "NAN Publisher found for Serv ID %d", evt->subscribe_id);
memcpy(&g_svc_match_evt, evt, sizeof(wifi_event_nan_svc_match_t));
xEventGroupSetBits(nan_event_group, NAN_SERVICE_MATCH);
}
void wifi_nan_subscribe(void)
{
nan_event_group = xEventGroupCreate();
esp_event_handler_instance_t instance_any_id;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
WIFI_EVENT_NAN_SVC_MATCH,
&nan_svc_match_event_handler,
NULL,
&instance_any_id));
#ifdef CONFIG_EXAMPLE_NAN_SEND_PING
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
WIFI_EVENT_NDP_CONFIRM,
&nan_ndp_confirmed_event_handler,
NULL,
&instance_any_id));
#endif
/* Start NAN Discovery */
wifi_nan_config_t nan_cfg = WIFI_NAN_CONFIG_DEFAULT();
esp_netif_t *nan_netif = esp_netif_create_default_wifi_nan();
(void) nan_netif;
esp_wifi_nan_start(&nan_cfg);
/* Subscribe a service */
uint8_t sub_id;
wifi_nan_subscribe_cfg_t subscribe_cfg = {
.service_name = EXAMPLE_NAN_SERV_NAME,
#if CONFIG_EXAMPLE_NAN_SUBSCRIBE_PASSIVE
.type = NAN_SUBSCRIBE_PASSIVE,
#else
.type = NAN_SUBSCRIBE_ACTIVE,
#endif
.matching_filter = EXAMPLE_NAN_MATCHING_FILTER,
.single_match_event = 1,
};
sub_id = esp_wifi_nan_subscribe_service(&subscribe_cfg);
if (sub_id == 0) {
return;
}
EventBits_t bits_1 = xEventGroupWaitBits(nan_event_group, NAN_SERVICE_MATCH, pdFALSE, pdFALSE,
portMAX_DELAY);
if (bits_1 & NAN_SERVICE_MATCH) {
#ifdef CONFIG_EXAMPLE_NAN_SEND_MESSAGE
wifi_nan_followup_params_t fup = {
.inst_id = sub_id,
.peer_inst_id = g_svc_match_evt.publish_id,
.svc_info = EXAMPLE_NAN_SVC_MSG,
};
memcpy(fup.peer_mac, g_svc_match_evt.pub_if_mac, sizeof(fup.peer_mac));
if (esp_wifi_nan_send_message(&fup) == ESP_OK)
ESP_LOGI(TAG, "Sending message '%s' to Publisher "MACSTR" ...",
EXAMPLE_NAN_SVC_MSG, MAC2STR(g_svc_match_evt.pub_if_mac));
#endif
#ifdef CONFIG_EXAMPLE_NAN_SEND_PING
wifi_nan_datapath_req_t ndp_req = {0};
ndp_req.confirm_required = true;
ndp_req.pub_id = g_svc_match_evt.publish_id;
memcpy(ndp_req.peer_mac, g_svc_match_evt.pub_if_mac, sizeof(ndp_req.peer_mac));
esp_wifi_nan_datapath_req(&ndp_req);
EventBits_t bits_2 = xEventGroupWaitBits(nan_event_group, NDP_CONFIRMED, pdFALSE, pdFALSE, portMAX_DELAY);
if (bits_2 & NDP_CONFIRMED) {
vTaskDelay(5000 / portTICK_PERIOD_MS);
ping_nan_peer(nan_netif);
} else if (bits_2 & NDP_FAILED) {
ESP_LOGI(TAG, "Failed to setup NAN Datapath");
}
#endif
}
}
void initialise_wifi(void)
{
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM) );
}
void app_main(void)
{
//Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
initialise_wifi();
wifi_nan_subscribe();
}

Wyświetl plik

@ -0,0 +1 @@
CONFIG_ESP_WIFI_NAN_ENABLE=y

Wyświetl plik

@ -404,7 +404,6 @@ components/esp_eth/test_apps/component_ut_test.py
components/esp_eth/test_apps/main/esp_eth_test.c
components/esp_event/esp_event_private.c
components/esp_event/event_loop_legacy.c
components/esp_event/event_send.c
components/esp_event/host_test/esp_event_unit_test/main/esp_event_test.cpp
components/esp_event/host_test/fixtures.hpp
components/esp_event/include/esp_event_loop.h