From 6d01dc4cfa11f08258c31118c5d16e04f79fcc28 Mon Sep 17 00:00:00 2001 From: qiyuexia Date: Sat, 28 Mar 2020 20:56:02 +0800 Subject: [PATCH] mesh/ps: add mesh network power save function --- components/esp_common/src/esp_err_to_name.c | 9 +++ components/esp_wifi/include/esp_mesh.h | 56 ++++++++++++++++++- components/esp_wifi/lib | 2 +- .../internal_communication/main/mesh_main.c | 26 ++++++++- 4 files changed, 89 insertions(+), 4 deletions(-) diff --git a/components/esp_common/src/esp_err_to_name.c b/components/esp_common/src/esp_err_to_name.c index ec31af218..edce6981c 100644 --- a/components/esp_common/src/esp_err_to_name.c +++ b/components/esp_common/src/esp_err_to_name.c @@ -460,6 +460,15 @@ static const esp_err_msg_t esp_err_msg_table[] = { # endif # ifdef ESP_ERR_MESH_VOTING ERR_TBL_IT(ESP_ERR_MESH_VOTING), /* 16406 0x4016 */ +# endif +# ifdef ESP_ERR_MESH_XMIT + ERR_TBL_IT(ESP_ERR_MESH_XMIT), /* 16407 0x4017 */ +# endif +# ifdef ESP_ERR_MESH_QUEUE_READ + ERR_TBL_IT(ESP_ERR_MESH_QUEUE_READ), /* 16408 0x4018 */ +# endif +# ifdef ESP_ERR_MESH_INACTIVE + ERR_TBL_IT(ESP_ERR_MESH_INACTIVE), /* 16409 0x4019 */ # endif // components/esp_netif/include/esp_netif_types.h # ifdef ESP_ERR_ESP_NETIF_BASE diff --git a/components/esp_wifi/include/esp_mesh.h b/components/esp_wifi/include/esp_mesh.h index 811cdb745..6b17a60ce 100644 --- a/components/esp_wifi/include/esp_mesh.h +++ b/components/esp_wifi/include/esp_mesh.h @@ -125,6 +125,9 @@ extern "C" { #define ESP_ERR_MESH_DISCARD_DUPLICATE (ESP_ERR_MESH_BASE + 20) /**< discard the packet due to the duplicate sequence number */ #define ESP_ERR_MESH_DISCARD (ESP_ERR_MESH_BASE + 21) /**< discard the packet */ #define ESP_ERR_MESH_VOTING (ESP_ERR_MESH_BASE + 22) /**< vote in progress */ +#define ESP_ERR_MESH_XMIT (ESP_ERR_MESH_BASE + 23) /**< XMIT */ +#define ESP_ERR_MESH_QUEUE_READ (ESP_ERR_MESH_BASE + 24) /**< error in reading queue */ +#define ESP_ERR_MESH_INACTIVE (ESP_ERR_MESH_BASE + 25) /**< mesh network is not active */ /** * @brief Flags bitmap for esp_mesh_send() and esp_mesh_recv() @@ -151,6 +154,12 @@ extern "C" { #define MESH_ASSOC_FLAG_ROOTS_FOUND (0x20) /**< root conflict is found */ #define MESH_ASSOC_FLAG_ROOT_FIXED (0x40) /**< fixed root */ + +/** + * @brief Mesh PS (Power Save) duty cycle type + */ +#define MESH_PS_DEVICE_DUTY_REQUEST (0x01) /**< requests to join a network PS without specifying a duty cycle */ + /******************************************************* * Enumerations *******************************************************/ @@ -421,7 +430,6 @@ typedef union { packets out. If not, devices had better to wait until this state changes to be MESH_TODS_REACHABLE. */ mesh_event_vote_started_t vote_started; /**< vote started */ - //mesh_event_root_got_ip_t got_ip; /**< root obtains IP address */ mesh_event_root_address_t root_addr; /**< root address */ mesh_event_root_switch_req_t switch_req; /**< root switch request */ mesh_event_root_conflict_t root_conflict; /**< other powerful root */ @@ -591,6 +599,7 @@ esp_err_t esp_mesh_start(void); * - Delete TX and RX queues. * - Release resources. * - Restore Wi-Fi softAP to default settings if Wi-Fi dual mode is enabled. + * - Set Wi-Fi power save type to WIFI_PS_NONE. * * @return * - ESP_OK @@ -1008,7 +1017,7 @@ bool esp_mesh_get_self_organized(void); esp_err_t esp_mesh_waive_root(const mesh_vote_t *vote, int reason); /** - * @brief Set vote percentage threshold for approval of being a root + * @brief Set vote percentage threshold for approval of being a root (default:0.9) * - During the networking, only obtaining vote percentage reaches this threshold, * the device could be a root. * @@ -1484,6 +1493,49 @@ esp_err_t esp_mesh_set_topology(esp_mesh_topology_t topo); */ esp_mesh_topology_t esp_mesh_get_topology(void); +/** + * @brief Check whether the mesh network is in active state + * - If the mesh network is not in active state, mesh devices will neither transmit nor receive frames. + * - If power save mode of the mesh network is enabled, devices should check whether the network is active before + * sending any packets. (i.e. before calling esp_mesh_send()). + * - Power save mode is enabled by setting the PS type to WIFI_PS_MIN_MODEM for all devices before mesh is started. + * + * @return true/false + */ +bool esp_mesh_is_network_active(void); + +/** + * @brief Set device duty cycle and type + * + * @attention This API can be called at any time after mesh is initialized. + * + * @param[in] dev_duty device duty cycle + * @param[in] dev_duty_type device PS duty cycle type + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_mesh_set_active_duty_cycle(int dev_duty, int dev_duty_type); + +/** + * @brief Get device duty cycle and type + * + * @param[out] dev_duty device duty cycle + * @param[out] dev_duty_type device PS duty cycle type + * + * @return + * - ESP_OK + */ +esp_err_t esp_mesh_get_active_duty_cycle(int* dev_duty, int* dev_duty_type); + +/** + * @brief Get the running active duty cycle + * + * @return the running active duty cycle + */ +int esp_mesh_get_running_active_duty_cycle(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index ef66c9a7e..d9f3c27ad 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit ef66c9a7ee824b78d015782b6a886c053c4f9b51 +Subproject commit d9f3c27adec317ebe418aee5ecec6bfc3e8a684f diff --git a/examples/mesh/internal_communication/main/mesh_main.c b/examples/mesh/internal_communication/main/mesh_main.c index f9b2b6c2d..052a11379 100644 --- a/examples/mesh/internal_communication/main/mesh_main.c +++ b/examples/mesh/internal_communication/main/mesh_main.c @@ -19,6 +19,7 @@ /******************************************************* * Macros *******************************************************/ +//#define MESH_ENABLE_POWER_SAVE /******************************************************* * Constants @@ -101,6 +102,12 @@ void esp_mesh_p2p_tx_main(void *arg) } for (i = 0; i < route_table_size; i++) { +#ifdef MESH_ENABLE_POWER_SAVE + /* PS is enabled, it's better to check if the device is active now. */ + while (!esp_mesh_is_network_active()) { + vTaskDelay(10 / portTICK_RATE_MS); + } +#endif err = esp_mesh_send(&route_table[i], &data, MESH_DATA_P2P, NULL, 0); if (err) { ESP_LOGE(MESH_TAG, @@ -380,13 +387,19 @@ void app_main(void) ESP_ERROR_CHECK(esp_netif_init()); /* event initialization */ ESP_ERROR_CHECK(esp_event_loop_create_default()); - /* crete network interfaces for mesh (only station instance saved for further manipulation, soft AP instance ignored */ + /* create network interfaces for mesh (only station instance saved for further manipulation, soft AP instance ignored */ ESP_ERROR_CHECK(esp_netif_create_default_wifi_mesh_netifs(&netif_sta, NULL)); /* wifi initialization */ wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&config)); ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &ip_event_handler, NULL)); ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_FLASH)); +#ifdef MESH_ENABLE_POWER_SAVE + /* enable the mesh PS function by setting WIFI_PS_MIN_MODEM for all mesh devices before mesh is started */ + ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_MIN_MODEM)); +#else + ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE)); +#endif ESP_ERROR_CHECK(esp_wifi_start()); /* mesh initialization */ ESP_ERROR_CHECK(esp_mesh_init()); @@ -396,7 +409,14 @@ void app_main(void) /* set mesh max layer according to the topology */ ESP_ERROR_CHECK(esp_mesh_set_max_layer(CONFIG_MESH_MAX_LAYER)); ESP_ERROR_CHECK(esp_mesh_set_vote_percentage(1)); +#ifdef MESH_ENABLE_POWER_SAVE + /* PS is enabled, it's better to increase the associate expired time. */ + ESP_ERROR_CHECK(esp_mesh_set_ap_assoc_expire(60)); + /* PS is enabled, it's better to increase the announce interval. */ + ESP_ERROR_CHECK(esp_mesh_set_announce_interval(600, 3300)); +#else ESP_ERROR_CHECK(esp_mesh_set_ap_assoc_expire(10)); +#endif mesh_cfg_t cfg = MESH_INIT_CONFIG_DEFAULT(); /* mesh ID */ memcpy((uint8_t *) &cfg.mesh_id, MESH_ID, 6); @@ -412,6 +432,10 @@ void app_main(void) memcpy((uint8_t *) &cfg.mesh_ap.password, CONFIG_MESH_AP_PASSWD, strlen(CONFIG_MESH_AP_PASSWD)); ESP_ERROR_CHECK(esp_mesh_set_config(&cfg)); +#ifdef MESH_ENABLE_POWER_SAVE + /* PS is enabled, set the device active duty cycle. (default:12) */ + ESP_ERROR_CHECK(esp_mesh_set_active_duty_cycle(15, MESH_PS_DEVICE_DUTY_REQUEST)); +#endif /* mesh start */ ESP_ERROR_CHECK(esp_mesh_start()); ESP_LOGI(MESH_TAG, "mesh starts successfully, heap:%d, %s<%d>%s\n", esp_get_free_heap_size(),