-
Notifications
You must be signed in to change notification settings - Fork 136
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(console): Console for runtime wifi configuration
- Loading branch information
1 parent
82c2cf8
commit e565f7b
Showing
13 changed files
with
462 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
name: "console_cmd_wifi: build-tests" | ||
|
||
on: | ||
push: | ||
branches: | ||
- master | ||
pull_request: | ||
types: [opened, synchronize, reopened, labeled] | ||
|
||
jobs: | ||
build_console_cmd_wifi: | ||
if: contains(github.event.pull_request.labels.*.name, 'console') || github.event_name == 'push' | ||
name: Build | ||
strategy: | ||
matrix: | ||
idf_ver: ["latest", "release-v5.0"] | ||
idf_target: ["esp32"] | ||
test: [ { app: example, path: "components/console_cmd_wifi/examples" }] | ||
runs-on: ubuntu-20.04 | ||
container: espressif/idf:${{ matrix.idf_ver }} | ||
steps: | ||
- name: Checkout esp-protocols | ||
uses: actions/checkout@v3 | ||
with: | ||
submodules: recursive | ||
- name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }} | ||
shell: bash | ||
working-directory: ${{matrix.test.path}} | ||
run: | | ||
${IDF_PATH}/install.sh --enable-pytest | ||
. ${IDF_PATH}/export.sh | ||
python $IDF_PATH/tools/ci/ci_build_apps.py . --target ${{ matrix.idf_target }} -vv --preserve-all --pytest-app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
--- | ||
commitizen: | ||
bump_message: 'bump(console): $current_version -> $new_version' | ||
pre_bump_hooks: python ../../ci/changelog.py console_cmd_wifi | ||
tag_format: console_cmd_wifi-v$version | ||
version: 0.0.9 | ||
version_files: | ||
- idf_component.yml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
idf_component_register(SRCS "console_wifi.c" | ||
INCLUDE_DIRS "." | ||
PRIV_REQUIRES esp_netif console esp_wifi | ||
WHOLE_ARCHIVE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# Console command wifi | ||
The component offers a console with a command that enables runtime wifi configuration for any example project. | ||
|
||
## API | ||
|
||
### Steps to enable console in an example code: | ||
1. Add this component to your project using ```idf.py add-dependency``` command. | ||
2. In the main file of the example, add the following line: | ||
```c | ||
#include "console_wifi.h" | ||
``` | ||
3. Ensure esp-netif and NVS flash is initialized and default event loop is created in your app_main(): | ||
```c | ||
ESP_ERROR_CHECK(esp_netif_init()); | ||
ESP_ERROR_CHECK(esp_event_loop_create_default()); | ||
esp_err_t ret = nvs_flash_init(); //Initialize NVS | ||
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); | ||
``` | ||
4. In your app_main() function, add the following line as the last line: | ||
```c | ||
ESP_ERROR_CHECK(console_cmd_init()); // Initialize console | ||
|
||
// Register all plugin command added to your project | ||
ESP_ERROR_CHECK(console_cmd_all_register()); | ||
|
||
// To register only wifi command skip calling console_cmd_all_register() | ||
ESP_ERROR_CHECK(console_cmd_wifi_register()); | ||
|
||
ESP_ERROR_CHECK(console_cmd_start()); // Start console | ||
``` | ||
|
||
## Suported command: | ||
|
||
### wifi: | ||
* ```wifi help```: Prints the help text for all wifi commands | ||
* ```wifi show network```: Scans and displays upto 10 available wifi networks. | ||
* ```wifi show sta```: Shows the details of wifi station. | ||
* ```wifi sta join <network ssid> <password>```: Station joins the given wifi network. | ||
* ```wifi sta join <network ssid>```: Station joins the given unsecured wifi network. | ||
* ```wifi sta leave```: Station leaves the wifi network. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,276 @@ | ||
/* | ||
* 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 | ||
|
||
/** | ||
* 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 | ||
}; | ||
|
||
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."}, | ||
{.name = "join", .operation = wifi_sta_join_op, .arg_cnt = 4, .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 = 5, .start_index = 2, .help = "wifi sta join <network ssid>: Station joins the given unsecured wifi network."}, | ||
{.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\tChannel: %d\tSSID: %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, "Password: %s", wifi_config.sta.password); | ||
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; | ||
} | ||
|
||
strlcpy((char *) wifi_config.sta.ssid, argv[self->start_index + 1], sizeof(wifi_config.sta.ssid)); | ||
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) | ||
{ | ||
esp_err_t ret; | ||
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; | ||
} |
Oops, something went wrong.