2023-12-07 20:26:47 +11:00
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_netif.h"
#include "esp_console.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_netif_net_stack.h"
#include "lwip/ip6.h"
#include "lwip/opt.h"
#include "esp_wifi.h"
#include "console_wifi.h"
#define DEFAULT_SCAN_LIST_SIZE 10
2024-02-23 21:32:16 +11:00
#if CONFIG_WIFI_CMD_AUTO_REGISTRATION
2023-12-07 20:26:47 +11:00
/**
* Static registration of this plugin is achieved by defining the plugin description
* structure and placing it into .console_cmd_desc section.
* The name of the section and its placement is determined by linker.lf file in 'plugins' component.
*/
static const console_cmd_plugin_desc_t __attribute__ (( section ( ".console_cmd_desc" ), used )) PLUGIN = {
. name = "console_cmd_wifi" ,
. plugin_regd_fn = & console_cmd_wifi_register
};
2024-02-23 21:32:16 +11:00
#endif
2023-12-07 20:26:47 +11:00
typedef struct wifi_op_t {
char * name ;
esp_err_t ( * operation )( struct wifi_op_t * self , int argc , char * argv []);
int arg_cnt ;
int start_index ;
char * help ;
} wifi_op_t ;
static esp_err_t wifi_help_op ( wifi_op_t * self , int argc , char * argv []);
static esp_err_t wifi_show_op ( wifi_op_t * self , int argc , char * argv []);
static esp_err_t wifi_sta_join_op ( wifi_op_t * self , int argc , char * argv []);
static esp_err_t wifi_sta_leave_op ( wifi_op_t * self , int argc , char * argv []);
static const char * TAG = "console_wifi" ;
#define JOIN_TIMEOUT_MS (10000)
static EventGroupHandle_t wifi_event_group ;
static const int STA_STARTED_BIT = BIT0 ;
static const int CONNECTED_BIT = BIT1 ;
static wifi_op_t cmd_list [] = {
{. name = "help" , . operation = wifi_help_op , . arg_cnt = 2 , . start_index = 1 , . help = "wifi help: Prints the help text for all wifi commands" },
{. name = "show" , . operation = wifi_show_op , . arg_cnt = 3 , . start_index = 1 , . help = "wifi show network/sta: Scans and displays all available wifi APs./ Shows the details of wifi station." },
2024-02-23 21:32:16 +11:00
{. name = "join" , . operation = wifi_sta_join_op , . arg_cnt = 5 , . start_index = 2 , . help = "wifi sta join <network ssid> <password>: Station joins the given wifi network." },
{. name = "join" , . operation = wifi_sta_join_op , . arg_cnt = 4 , . start_index = 2 , . help = "wifi sta join <network ssid>: Station joins the given unsecured wifi network." },
{. name = "join" , . operation = wifi_sta_join_op , . arg_cnt = 3 , . start_index = 2 , . help = "wifi sta join: Station joins the pre-configured wifi network." },
2023-12-07 20:26:47 +11:00
{. name = "leave" , . operation = wifi_sta_leave_op , . arg_cnt = 3 , . start_index = 2 , . help = "wifi sta leave: Station leaves the wifi network." },
};
static void event_handler ( void * arg , esp_event_base_t event_base ,
int32_t event_id , void * event_data )
{
if ( event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START ) {
xEventGroupSetBits ( wifi_event_group , STA_STARTED_BIT );
} else if ( event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED ) {
esp_wifi_connect ();
xEventGroupClearBits ( wifi_event_group , CONNECTED_BIT );
} else if ( event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP ) {
xEventGroupSetBits ( wifi_event_group , CONNECTED_BIT );
}
}
static esp_err_t wifi_help_op ( wifi_op_t * self , int argc , char * argv [])
{
int cmd_count = sizeof ( cmd_list ) / sizeof ( cmd_list [ 0 ]);
for ( int i = 0 ; i < cmd_count ; i ++ ) {
if (( cmd_list [ i ]. help != NULL ) && ( strlen ( cmd_list [ i ]. help ) != 0 )) {
printf ( " %s \n " , cmd_list [ i ]. help );
}
}
return ESP_OK ;
}
uint8_t wifi_connection_status = 0 ;
void wifi_init ( void )
{
static bool init_flag = false ;
if ( init_flag ) {
return ;
}
wifi_event_group = xEventGroupCreate ();
esp_netif_t * sta_netif = esp_netif_create_default_wifi_sta ();
assert ( sta_netif );
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT ();
ESP_ERROR_CHECK ( esp_wifi_init ( & cfg ));
ESP_ERROR_CHECK ( esp_event_handler_register ( WIFI_EVENT , WIFI_EVENT_STA_START , & event_handler , NULL ));
ESP_ERROR_CHECK ( esp_event_handler_register ( WIFI_EVENT , WIFI_EVENT_STA_DISCONNECTED , & event_handler , NULL ));
ESP_ERROR_CHECK ( esp_event_handler_register ( IP_EVENT , IP_EVENT_STA_GOT_IP , & event_handler , NULL ));
ESP_ERROR_CHECK ( esp_wifi_set_storage ( WIFI_STORAGE_RAM ));
ESP_ERROR_CHECK ( esp_wifi_set_mode ( WIFI_MODE_STA ));
ESP_ERROR_CHECK ( esp_wifi_start ());
int bits = xEventGroupWaitBits ( wifi_event_group , STA_STARTED_BIT ,
pdFALSE , pdTRUE , JOIN_TIMEOUT_MS / portTICK_PERIOD_MS );
if (( bits & STA_STARTED_BIT ) == 0 ) {
ESP_LOGE ( TAG , "Error: Wifi Connection timed out" );
return ;
}
init_flag = true ;
}
/* Initialize Wi-Fi as sta and set scan method */
static void wifi_scan ( void )
{
uint16_t number = DEFAULT_SCAN_LIST_SIZE ;
wifi_ap_record_t ap_info [ DEFAULT_SCAN_LIST_SIZE ];
uint16_t ap_count = 0 ;
memset ( ap_info , 0 , sizeof ( ap_info ));
wifi_init ();
esp_wifi_scan_start ( NULL , true );
ESP_ERROR_CHECK ( esp_wifi_scan_get_ap_records ( & number , ap_info ));
ESP_ERROR_CHECK ( esp_wifi_scan_get_ap_num ( & ap_count ));
ESP_LOGI ( TAG , "Showing Wifi networks" );
ESP_LOGI ( TAG , "*********************" );
for ( int i = 0 ; i < number ; i ++ ) {
ESP_LOGI ( TAG , "RSSI: %d \t Channel: %d \t SSID: %s" , ap_info [ i ]. rssi , ap_info [ i ]. primary , ap_info [ i ]. ssid );
}
ESP_LOGI ( TAG , "Total APs scanned = %u, actual AP number ap_info holds = %u" , ap_count , number );
}
static esp_err_t wifi_show_op ( wifi_op_t * self , int argc , char * argv [])
{
if ( ! strcmp ( "network" , argv [ self -> start_index + 1 ])) {
wifi_scan ();
return ESP_OK ;
}
if ( ! strcmp ( "sta" , argv [ self -> start_index + 1 ])) {
{
wifi_config_t wifi_config = { 0 };
wifi_init ();
ESP_ERROR_CHECK ( esp_wifi_get_config ( WIFI_IF_STA , & wifi_config ));
ESP_LOGI ( TAG , "Showing Joind AP details:" );
ESP_LOGI ( TAG , "*************************" );
ESP_LOGI ( TAG , "SSID: %s" , wifi_config . sta . ssid );
ESP_LOGI ( TAG , "Channel: %d" , wifi_config . sta . channel );
ESP_LOGI ( TAG , "bssid: %02x:%02x:%02x:%02x:%02x:%02x" , wifi_config . sta . bssid [ 0 ],
wifi_config . sta . bssid [ 1 ], wifi_config . sta . bssid [ 2 ], wifi_config . sta . bssid [ 3 ],
wifi_config . sta . bssid [ 4 ], wifi_config . sta . bssid [ 5 ]);
}
return ESP_OK ;
}
return ESP_OK ;
}
static esp_err_t wifi_sta_join_op ( wifi_op_t * self , int argc , char * argv [])
{
wifi_config_t wifi_config = { 0 };
if ( strcmp ( "sta" , argv [ self -> start_index - 1 ])) {
ESP_LOGE ( TAG , "Error: Invalid command \n " );
ESP_LOGE ( TAG , "%s \n " , self -> help );
return ESP_FAIL ;
}
2024-02-23 21:32:16 +11:00
if ( self -> arg_cnt == 3 ) {
strlcpy (( char * ) wifi_config . sta . ssid , CONFIG_WIFI_CMD_NETWORK_SSID , sizeof ( wifi_config . sta . ssid ));
strlcpy (( char * ) wifi_config . sta . password , CONFIG_WIFI_CMD_NETWORK_PASSWORD , sizeof ( wifi_config . sta . password ));
} else {
strlcpy (( char * ) wifi_config . sta . ssid , argv [ self -> start_index + 1 ], sizeof ( wifi_config . sta . ssid ));
}
2023-12-07 20:26:47 +11:00
if ( self -> arg_cnt == 5 ) {
strlcpy (( char * ) wifi_config . sta . password , argv [ self -> start_index + 2 ], sizeof ( wifi_config . sta . password ));
}
wifi_init ();
ESP_ERROR_CHECK ( esp_wifi_set_config ( WIFI_IF_STA , & wifi_config ));
esp_wifi_connect ();
int bits = xEventGroupWaitBits ( wifi_event_group , CONNECTED_BIT ,
pdFALSE , pdTRUE , JOIN_TIMEOUT_MS / portTICK_PERIOD_MS );
if (( bits & CONNECTED_BIT ) == 0 ) {
ESP_LOGE ( TAG , "Error: Wifi Connection timed out" );
return ESP_OK ;
}
return ESP_OK ;
}
static esp_err_t wifi_sta_leave_op ( wifi_op_t * self , int argc , char * argv [])
{
wifi_config_t wifi_config = { 0 };
if ( strcmp ( "sta" , argv [ self -> start_index - 1 ])) {
ESP_LOGE ( TAG , "Error: Invalid command \n " );
ESP_LOGE ( TAG , "%s \n " , self -> help );
return ESP_FAIL ;
}
esp_wifi_disconnect ();
ESP_ERROR_CHECK ( esp_wifi_set_config ( WIFI_IF_STA , & wifi_config ));
return ESP_OK ;
}
/* handle 'wifi' command */
static esp_err_t do_cmd_wifi ( int argc , char ** argv )
{
int cmd_count = sizeof ( cmd_list ) / sizeof ( cmd_list [ 0 ]);
wifi_op_t cmd ;
for ( int i = 0 ; i < cmd_count ; i ++ ) {
cmd = cmd_list [ i ];
if ( argc < cmd . start_index + 1 ) {
continue ;
}
if ( ! strcmp ( cmd . name , argv [ cmd . start_index ])) {
/* Get interface for eligible commands */
if ( cmd . arg_cnt == argc ) {
if ( cmd . operation != NULL ) {
if ( cmd . operation ( & cmd , argc , argv ) != ESP_OK ) {
ESP_LOGE ( TAG , "Usage: \n %s" , cmd . help );
return 0 ;
}
}
return ESP_OK ;
}
}
}
ESP_LOGE ( TAG , "Command not available" );
return ESP_OK ;
}
/**
* @brief Registers the wifi command.
*
* @return
* - esp_err_t
*/
esp_err_t console_cmd_wifi_register ( void )
{
2024-02-23 21:32:16 +11:00
esp_err_t ret = ESP_OK ;
2023-12-07 20:26:47 +11:00
esp_console_cmd_t command = {
. command = "wifi" ,
. help = "Command for wifi configuration and monitoring \n For more info run 'wifi help'" ,
. func = & do_cmd_wifi
};
ret = esp_console_cmd_register ( & command );
if ( ret ) {
ESP_LOGE ( TAG , "Unable to register wifi" );
}
return ret ;
}