add nvs code.

This commit is contained in:
amass 2024-06-03 23:51:39 +08:00
parent ac6a5433c4
commit 7f3491094f
10 changed files with 798 additions and 151 deletions

View File

@ -0,0 +1,67 @@
#include "Application.h"
#include <esp_log.h>
#include <esp_wifi.h>
#include <freertos/FreeRTOS.h>
#include <string.h>
Application *Application::instance() {
static Application self;
return &self;
}
void Application::initialize() {
initializeWifi();
}
void Application::eventHandler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
auto self = reinterpret_cast<Application *>(arg);
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
esp_wifi_connect();
xEventGroupClearBits(self->m_wifiEventGroup, CONNECTED_BIT);
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
xEventGroupSetBits(self->m_wifiEventGroup, CONNECTED_BIT);
}
}
bool Application::wifiConnect(const std::string &ssid, const std::string &password, int timeoutMillisecond) {
wifi_config_t config = {};
strlcpy((char *)config.sta.ssid, ssid.c_str(), sizeof(config.sta.ssid));
if (!password.empty()) {
strlcpy((char *)config.sta.password, password.c_str(), sizeof(config.sta.password));
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &config));
esp_wifi_connect();
int bits =
xEventGroupWaitBits(m_wifiEventGroup, CONNECTED_BIT, pdFALSE, pdTRUE, timeoutMillisecond / portTICK_PERIOD_MS);
return (bits & CONNECTED_BIT) != 0;
}
void Application::initializeWifi() {
esp_log_level_set("wifi", ESP_LOG_WARN);
static bool initialized = false;
if (initialized) {
return;
}
ESP_ERROR_CHECK(esp_netif_init());
if (m_wifiEventGroup == nullptr) {
m_wifiEventGroup = xEventGroupCreate();
}
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_t *ap_netif = esp_netif_create_default_wifi_ap();
assert(ap_netif);
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_DISCONNECTED, &Application::eventHandler, this));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &Application::eventHandler, this));
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());
initialized = true;
}

View File

@ -0,0 +1,59 @@
#ifndef __APPLICATION_H__
#define __APPLICATION_H__
#include <esp_event.h>
#include <esp_log.h>
#include <freertos/event_groups.h>
#include <nvs.h>
#include <string>
#include <type_traits>
class Application {
constexpr static int CONNECTED_BIT = BIT0;
constexpr static auto Namespace = "settings";
public:
constexpr static int WifiJoinTimeoutMillisecond = 10000;
static Application *instance();
bool wifiConnect(const std::string &ssid, const std::string &password,
int timeoutMillisecond = WifiJoinTimeoutMillisecond);
void initialize();
template <typename T>
void setField(const std::string &key, const T &value) {
nvs_handle_t hanlde;
esp_err_t error = nvs_open(Namespace, NVS_READWRITE, &hanlde);
if (error != ESP_OK) {
ESP_LOGI("App", "nvs_open() failed.");
}
if (std::is_same_v<char *, std::decay_t<T>>) {
error = nvs_set_str(hanlde, key.c_str(), value);
} else if constexpr (std::is_same_v<std::string, T>) {
error = nvs_set_str(hanlde, key.c_str(), value.c_str());
} else {
ESP_LOGW("App", "unknown data");
}
if (error == ESP_OK) {
error = nvs_commit(hanlde);
}
nvs_close(hanlde);
}
template <typename T>
T field(const std::string &key) {
}
protected:
static void eventHandler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
void initializeWifi();
Application() = default;
private:
EventGroupHandle_t m_wifiEventGroup = nullptr;
nvs_handle_t m_nvs;
};
#endif // __APPLICATION_H__

View File

@ -1,5 +1,6 @@
idf_component_register(SRCS idf_component_register(SRCS
Application.h Application.cpp
MqttClient.h MqttClient.cpp MqttClient.h MqttClient.cpp
INCLUDE_DIRS . INCLUDE_DIRS .
REQUIRES mqtt json LedController REQUIRES esp_wifi nvs_flash mqtt json LedController
) )

View File

@ -1,10 +1,10 @@
idf_component_register(SRCS idf_component_register(SRCS
cmd_nvs.h cmd_nvs.c
cmd_system.c cmd_system.c
cmd_system_common.c cmd_system_common.c
cmd_wifi.h cmd_wifi.c
CustomCommand.cpp CustomCommand.cpp
INCLUDE_DIRS . INCLUDE_DIRS .
REQUIRES console spi_flash driver esp_wifi LedController Communication REQUIRES console spi_flash nvs_flash driver esp_wifi LedController Communication
) )
target_sources(${COMPONENT_LIB} PRIVATE cmd_system_sleep.c) target_sources(${COMPONENT_LIB} PRIVATE cmd_system_sleep.c)

View File

@ -1,7 +1,10 @@
#include "CustomCommand.h" #include "CustomCommand.h"
#include "Application.h"
#include "LedController.h" #include "LedController.h"
#include "MqttClient.h" #include "MqttClient.h"
#include "esp_console.h" #include "esp_console.h"
#include <argtable3/argtable3.h>
#include <esp_log.h>
#include <iostream> #include <iostream>
static int custom_command(int argc, char **argv) { static int custom_command(int argc, char **argv) {
@ -23,6 +26,36 @@ static int mqtt_command(int argc, char **argv) {
return 0; return 0;
} }
static struct {
struct arg_int *timeout;
struct arg_str *ssid;
struct arg_str *password;
struct arg_end *end;
} join_args;
static int wifi_connect(int argc, char **argv) {
int nerrors = arg_parse(argc, argv, (void **)&join_args);
if (nerrors != 0) {
arg_print_errors(stderr, join_args.end, argv[0]);
return 1;
}
ESP_LOGI(__func__, "Connecting to '%s'", join_args.ssid->sval[0]);
/* set default value*/
if (join_args.timeout->count == 0) {
join_args.timeout->ival[0] = Application::WifiJoinTimeoutMillisecond;
}
bool connected = Application::instance()->wifiConnect(join_args.ssid->sval[0], join_args.password->sval[0],
join_args.timeout->ival[0]);
if (!connected) {
ESP_LOGW(__func__, "Connection timed out");
return 1;
}
ESP_LOGI(__func__, "Connected");
return 0;
}
void register_custom() { void register_custom() {
const esp_console_cmd_t heap_cmd = { const esp_console_cmd_t heap_cmd = {
.command = "amass", .command = "amass",
@ -33,6 +66,21 @@ void register_custom() {
}; };
ESP_ERROR_CHECK(esp_console_cmd_register(&heap_cmd)); ESP_ERROR_CHECK(esp_console_cmd_register(&heap_cmd));
join_args.timeout = arg_int0(NULL, "timeout", "<t>", "Connection timeout, ms");
join_args.ssid = arg_str1(NULL, NULL, "<ssid>", "SSID of AP");
join_args.password = arg_str0(NULL, NULL, "<pass>", "PSK of AP");
join_args.end = arg_end(2);
const esp_console_cmd_t join_cmd = {
.command = "join",
.help = "Join WiFi AP as a station",
.hint = NULL,
.func = &wifi_connect,
.argtable = &join_args,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&join_cmd));
const esp_console_cmd_t led_cmd = { const esp_console_cmd_t led_cmd = {
.command = "led", .command = "led",
.help = "led pwm duty.", .help = "led pwm duty.",

View File

@ -0,0 +1,609 @@
/* Console example — NVS commands
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 <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "esp_log.h"
#include "esp_console.h"
#include "argtable3/argtable3.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_err.h"
#include "cmd_nvs.h"
#include "nvs.h"
typedef struct {
nvs_type_t type;
const char *str;
} type_str_pair_t;
static const type_str_pair_t type_str_pair[] = {
{ NVS_TYPE_I8, "i8" },
{ NVS_TYPE_U8, "u8" },
{ NVS_TYPE_U16, "u16" },
{ NVS_TYPE_I16, "i16" },
{ NVS_TYPE_U32, "u32" },
{ NVS_TYPE_I32, "i32" },
{ NVS_TYPE_U64, "u64" },
{ NVS_TYPE_I64, "i64" },
{ NVS_TYPE_STR, "str" },
{ NVS_TYPE_BLOB, "blob" },
{ NVS_TYPE_ANY, "any" },
};
static const size_t TYPE_STR_PAIR_SIZE = sizeof(type_str_pair) / sizeof(type_str_pair[0]);
static const char *ARG_TYPE_STR = "type can be: i8, u8, i16, u16 i32, u32 i64, u64, str, blob";
static char current_namespace[16] = "storage";
static const char *TAG = "cmd_nvs";
static struct {
struct arg_str *key;
struct arg_str *type;
struct arg_str *value;
struct arg_end *end;
} set_args;
static struct {
struct arg_str *key;
struct arg_str *type;
struct arg_end *end;
} get_args;
static struct {
struct arg_str *key;
struct arg_end *end;
} erase_args;
static struct {
struct arg_str *namespace;
struct arg_end *end;
} erase_all_args;
static struct {
struct arg_str *namespace;
struct arg_end *end;
} namespace_args;
static struct {
struct arg_str *partition;
struct arg_str *namespace;
struct arg_str *type;
struct arg_end *end;
} list_args;
static nvs_type_t str_to_type(const char *type)
{
for (int i = 0; i < TYPE_STR_PAIR_SIZE; i++) {
const type_str_pair_t *p = &type_str_pair[i];
if (strcmp(type, p->str) == 0) {
return p->type;
}
}
return NVS_TYPE_ANY;
}
static const char *type_to_str(nvs_type_t type)
{
for (int i = 0; i < TYPE_STR_PAIR_SIZE; i++) {
const type_str_pair_t *p = &type_str_pair[i];
if (p->type == type) {
return p->str;
}
}
return "Unknown";
}
static esp_err_t store_blob(nvs_handle_t nvs, const char *key, const char *str_values)
{
uint8_t value;
size_t str_len = strlen(str_values);
size_t blob_len = str_len / 2;
if (str_len % 2) {
ESP_LOGE(TAG, "Blob data must contain even number of characters");
return ESP_ERR_NVS_TYPE_MISMATCH;
}
char *blob = (char *)malloc(blob_len);
if (blob == NULL) {
return ESP_ERR_NO_MEM;
}
for (int i = 0, j = 0; i < str_len; i++) {
char ch = str_values[i];
if (ch >= '0' && ch <= '9') {
value = ch - '0';
} else if (ch >= 'A' && ch <= 'F') {
value = ch - 'A' + 10;
} else if (ch >= 'a' && ch <= 'f') {
value = ch - 'a' + 10;
} else {
ESP_LOGE(TAG, "Blob data contain invalid character");
free(blob);
return ESP_ERR_NVS_TYPE_MISMATCH;
}
if (i & 1) {
blob[j++] += value;
} else {
blob[j] = value << 4;
}
}
esp_err_t err = nvs_set_blob(nvs, key, blob, blob_len);
free(blob);
if (err == ESP_OK) {
err = nvs_commit(nvs);
}
return err;
}
static void print_blob(const char *blob, size_t len)
{
for (int i = 0; i < len; i++) {
printf("%02x", blob[i]);
}
printf("\n");
}
static esp_err_t set_value_in_nvs(const char *key, const char *str_type, const char *str_value)
{
esp_err_t err;
nvs_handle_t nvs;
bool range_error = false;
nvs_type_t type = str_to_type(str_type);
if (type == NVS_TYPE_ANY) {
ESP_LOGE(TAG, "Type '%s' is undefined", str_type);
return ESP_ERR_NVS_TYPE_MISMATCH;
}
err = nvs_open(current_namespace, NVS_READWRITE, &nvs);
if (err != ESP_OK) {
return err;
}
if (type == NVS_TYPE_I8) {
int32_t value = strtol(str_value, NULL, 0);
if (value < INT8_MIN || value > INT8_MAX || errno == ERANGE) {
range_error = true;
} else {
err = nvs_set_i8(nvs, key, (int8_t)value);
}
} else if (type == NVS_TYPE_U8) {
uint32_t value = strtoul(str_value, NULL, 0);
if (value > UINT8_MAX || errno == ERANGE) {
range_error = true;
} else {
err = nvs_set_u8(nvs, key, (uint8_t)value);
}
} else if (type == NVS_TYPE_I16) {
int32_t value = strtol(str_value, NULL, 0);
if (value < INT16_MIN || value > INT16_MAX || errno == ERANGE) {
range_error = true;
} else {
err = nvs_set_i16(nvs, key, (int16_t)value);
}
} else if (type == NVS_TYPE_U16) {
uint32_t value = strtoul(str_value, NULL, 0);
if (value > UINT16_MAX || errno == ERANGE) {
range_error = true;
} else {
err = nvs_set_u16(nvs, key, (uint16_t)value);
}
} else if (type == NVS_TYPE_I32) {
int32_t value = strtol(str_value, NULL, 0);
if (errno != ERANGE) {
err = nvs_set_i32(nvs, key, value);
}
} else if (type == NVS_TYPE_U32) {
uint32_t value = strtoul(str_value, NULL, 0);
if (errno != ERANGE) {
err = nvs_set_u32(nvs, key, value);
}
} else if (type == NVS_TYPE_I64) {
int64_t value = strtoll(str_value, NULL, 0);
if (errno != ERANGE) {
err = nvs_set_i64(nvs, key, value);
}
} else if (type == NVS_TYPE_U64) {
uint64_t value = strtoull(str_value, NULL, 0);
if (errno != ERANGE) {
err = nvs_set_u64(nvs, key, value);
}
} else if (type == NVS_TYPE_STR) {
err = nvs_set_str(nvs, key, str_value);
} else if (type == NVS_TYPE_BLOB) {
err = store_blob(nvs, key, str_value);
}
if (range_error || errno == ERANGE) {
nvs_close(nvs);
return ESP_ERR_NVS_VALUE_TOO_LONG;
}
if (err == ESP_OK) {
err = nvs_commit(nvs);
if (err == ESP_OK) {
ESP_LOGI(TAG, "Value stored under key '%s'", key);
}
}
nvs_close(nvs);
return err;
}
static esp_err_t get_value_from_nvs(const char *key, const char *str_type)
{
nvs_handle_t nvs;
esp_err_t err;
nvs_type_t type = str_to_type(str_type);
if (type == NVS_TYPE_ANY) {
ESP_LOGE(TAG, "Type '%s' is undefined", str_type);
return ESP_ERR_NVS_TYPE_MISMATCH;
}
err = nvs_open(current_namespace, NVS_READONLY, &nvs);
if (err != ESP_OK) {
return err;
}
if (type == NVS_TYPE_I8) {
int8_t value;
err = nvs_get_i8(nvs, key, &value);
if (err == ESP_OK) {
printf("%d\n", value);
}
} else if (type == NVS_TYPE_U8) {
uint8_t value;
err = nvs_get_u8(nvs, key, &value);
if (err == ESP_OK) {
printf("%u\n", value);
}
} else if (type == NVS_TYPE_I16) {
int16_t value;
err = nvs_get_i16(nvs, key, &value);
if (err == ESP_OK) {
printf("%u\n", value);
}
} else if (type == NVS_TYPE_U16) {
uint16_t value;
if ((err = nvs_get_u16(nvs, key, &value)) == ESP_OK) {
printf("%u\n", value);
}
} else if (type == NVS_TYPE_I32) {
int32_t value;
if ((err = nvs_get_i32(nvs, key, &value)) == ESP_OK) {
printf("%"PRIi32"\n", value);
}
} else if (type == NVS_TYPE_U32) {
uint32_t value;
if ((err = nvs_get_u32(nvs, key, &value)) == ESP_OK) {
printf("%"PRIu32"\n", value);
}
} else if (type == NVS_TYPE_I64) {
int64_t value;
if ((err = nvs_get_i64(nvs, key, &value)) == ESP_OK) {
printf("%lld\n", value);
}
} else if (type == NVS_TYPE_U64) {
uint64_t value;
if ( (err = nvs_get_u64(nvs, key, &value)) == ESP_OK) {
printf("%llu\n", value);
}
} else if (type == NVS_TYPE_STR) {
size_t len;
if ( (err = nvs_get_str(nvs, key, NULL, &len)) == ESP_OK) {
char *str = (char *)malloc(len);
if ( (err = nvs_get_str(nvs, key, str, &len)) == ESP_OK) {
printf("%s\n", str);
}
free(str);
}
} else if (type == NVS_TYPE_BLOB) {
size_t len;
if ( (err = nvs_get_blob(nvs, key, NULL, &len)) == ESP_OK) {
char *blob = (char *)malloc(len);
if ( (err = nvs_get_blob(nvs, key, blob, &len)) == ESP_OK) {
print_blob(blob, len);
}
free(blob);
}
}
nvs_close(nvs);
return err;
}
static esp_err_t erase(const char *key)
{
nvs_handle_t nvs;
esp_err_t err = nvs_open(current_namespace, NVS_READWRITE, &nvs);
if (err == ESP_OK) {
err = nvs_erase_key(nvs, key);
if (err == ESP_OK) {
err = nvs_commit(nvs);
if (err == ESP_OK) {
ESP_LOGI(TAG, "Value with key '%s' erased", key);
}
}
nvs_close(nvs);
}
return err;
}
static esp_err_t erase_all(const char *name)
{
nvs_handle_t nvs;
esp_err_t err = nvs_open(name, NVS_READWRITE, &nvs);
if (err == ESP_OK) {
err = nvs_erase_all(nvs);
if (err == ESP_OK) {
err = nvs_commit(nvs);
}
}
ESP_LOGI(TAG, "Namespace '%s' was %s erased", name, (err == ESP_OK) ? "" : "not");
nvs_close(nvs);
return ESP_OK;
}
static int list(const char *part, const char *name, const char *str_type)
{
nvs_type_t type = str_to_type(str_type);
nvs_iterator_t it = NULL;
esp_err_t result = nvs_entry_find(part, NULL, type, &it);
if (result == ESP_ERR_NVS_NOT_FOUND) {
ESP_LOGE(TAG, "No such entry was found");
return 1;
}
if (result != ESP_OK) {
ESP_LOGE(TAG, "NVS error: %s", esp_err_to_name(result));
return 1;
}
do {
nvs_entry_info_t info;
nvs_entry_info(it, &info);
result = nvs_entry_next(&it);
printf("namespace '%s', key '%s', type '%s' \n",
info.namespace_name, info.key, type_to_str(info.type));
} while (result == ESP_OK);
if (result != ESP_ERR_NVS_NOT_FOUND) { // the last iteration ran into an internal error
ESP_LOGE(TAG, "NVS error %s at current iteration, stopping.", esp_err_to_name(result));
return 1;
}
return 0;
}
static int set_value(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &set_args);
if (nerrors != 0) {
arg_print_errors(stderr, set_args.end, argv[0]);
return 1;
}
const char *key = set_args.key->sval[0];
const char *type = set_args.type->sval[0];
const char *values = set_args.value->sval[0];
esp_err_t err = set_value_in_nvs(key, type, values);
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s", esp_err_to_name(err));
return 1;
}
return 0;
}
static int get_value(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &get_args);
if (nerrors != 0) {
arg_print_errors(stderr, get_args.end, argv[0]);
return 1;
}
const char *key = get_args.key->sval[0];
const char *type = get_args.type->sval[0];
esp_err_t err = get_value_from_nvs(key, type);
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s", esp_err_to_name(err));
return 1;
}
return 0;
}
static int erase_value(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &erase_args);
if (nerrors != 0) {
arg_print_errors(stderr, erase_args.end, argv[0]);
return 1;
}
const char *key = erase_args.key->sval[0];
esp_err_t err = erase(key);
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s", esp_err_to_name(err));
return 1;
}
return 0;
}
static int erase_namespace(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &erase_all_args);
if (nerrors != 0) {
arg_print_errors(stderr, erase_all_args.end, argv[0]);
return 1;
}
const char *name = erase_all_args.namespace->sval[0];
esp_err_t err = erase_all(name);
if (err != ESP_OK) {
ESP_LOGE(TAG, "%s", esp_err_to_name(err));
return 1;
}
return 0;
}
static int set_namespace(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &namespace_args);
if (nerrors != 0) {
arg_print_errors(stderr, namespace_args.end, argv[0]);
return 1;
}
const char *namespace = namespace_args.namespace->sval[0];
strlcpy(current_namespace, namespace, sizeof(current_namespace));
ESP_LOGI(TAG, "Namespace set to '%s'", current_namespace);
return 0;
}
static int list_entries(int argc, char **argv)
{
list_args.partition->sval[0] = "";
list_args.namespace->sval[0] = "";
list_args.type->sval[0] = "";
int nerrors = arg_parse(argc, argv, (void **) &list_args);
if (nerrors != 0) {
arg_print_errors(stderr, list_args.end, argv[0]);
return 1;
}
const char *part = list_args.partition->sval[0];
const char *name = list_args.namespace->sval[0];
const char *type = list_args.type->sval[0];
return list(part, name, type);
}
void register_nvs(void)
{
set_args.key = arg_str1(NULL, NULL, "<key>", "key of the value to be set");
set_args.type = arg_str1(NULL, NULL, "<type>", ARG_TYPE_STR);
set_args.value = arg_str1("v", "value", "<value>", "value to be stored");
set_args.end = arg_end(2);
get_args.key = arg_str1(NULL, NULL, "<key>", "key of the value to be read");
get_args.type = arg_str1(NULL, NULL, "<type>", ARG_TYPE_STR);
get_args.end = arg_end(2);
erase_args.key = arg_str1(NULL, NULL, "<key>", "key of the value to be erased");
erase_args.end = arg_end(2);
erase_all_args.namespace = arg_str1(NULL, NULL, "<namespace>", "namespace to be erased");
erase_all_args.end = arg_end(2);
namespace_args.namespace = arg_str1(NULL, NULL, "<namespace>", "namespace of the partition to be selected");
namespace_args.end = arg_end(2);
list_args.partition = arg_str1(NULL, NULL, "<partition>", "partition name");
list_args.namespace = arg_str0("n", "namespace", "<namespace>", "namespace name");
list_args.type = arg_str0("t", "type", "<type>", ARG_TYPE_STR);
list_args.end = arg_end(2);
const esp_console_cmd_t set_cmd = {
.command = "nvs_set",
.help = "Set key-value pair in selected namespace.\n"
"Examples:\n"
" nvs_set VarName i32 -v 123 \n"
" nvs_set VarName str -v YourString \n"
" nvs_set VarName blob -v 0123456789abcdef \n",
.hint = NULL,
.func = &set_value,
.argtable = &set_args
};
const esp_console_cmd_t get_cmd = {
.command = "nvs_get",
.help = "Get key-value pair from selected namespace. \n"
"Example: nvs_get VarName i32",
.hint = NULL,
.func = &get_value,
.argtable = &get_args
};
const esp_console_cmd_t erase_cmd = {
.command = "nvs_erase",
.help = "Erase key-value pair from current namespace",
.hint = NULL,
.func = &erase_value,
.argtable = &erase_args
};
const esp_console_cmd_t erase_namespace_cmd = {
.command = "nvs_erase_namespace",
.help = "Erases specified namespace",
.hint = NULL,
.func = &erase_namespace,
.argtable = &erase_all_args
};
const esp_console_cmd_t namespace_cmd = {
.command = "nvs_namespace",
.help = "Set current namespace",
.hint = NULL,
.func = &set_namespace,
.argtable = &namespace_args
};
const esp_console_cmd_t list_entries_cmd = {
.command = "nvs_list",
.help = "List stored key-value pairs stored in NVS."
"Namespace and type can be specified to print only those key-value pairs.\n"
"Following command list variables stored inside 'nvs' partition, under namespace 'storage' with type uint32_t"
"Example: nvs_list nvs -n storage -t u32 \n",
.hint = NULL,
.func = &list_entries,
.argtable = &list_args
};
ESP_ERROR_CHECK(esp_console_cmd_register(&set_cmd));
ESP_ERROR_CHECK(esp_console_cmd_register(&get_cmd));
ESP_ERROR_CHECK(esp_console_cmd_register(&erase_cmd));
ESP_ERROR_CHECK(esp_console_cmd_register(&namespace_cmd));
ESP_ERROR_CHECK(esp_console_cmd_register(&list_entries_cmd));
ESP_ERROR_CHECK(esp_console_cmd_register(&erase_namespace_cmd));
}

View File

@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* Console example — declarations of command registration functions. /* Console example — declarations of command registration functions.
This example code is in the Public Domain (or CC0 licensed, at your option.) This example code is in the Public Domain (or CC0 licensed, at your option.)
@ -17,8 +12,8 @@
extern "C" { extern "C" {
#endif #endif
// Register WiFi functions // Register NVS functions
void register_wifi(void); void register_nvs(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,136 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* Console example — WiFi commands
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 <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "esp_console.h"
#include "argtable3/argtable3.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "cmd_wifi.h"
#define JOIN_TIMEOUT_MS (10000)
static EventGroupHandle_t wifi_event_group;
const int CONNECTED_BIT = BIT0;
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_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 void initialise_wifi(void)
{
esp_log_level_set("wifi", ESP_LOG_WARN);
static bool initialized = false;
if (initialized) {
return;
}
ESP_ERROR_CHECK(esp_netif_init());
wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_t *ap_netif = esp_netif_create_default_wifi_ap();
assert(ap_netif);
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_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_NULL) );
ESP_ERROR_CHECK( esp_wifi_start() );
initialized = true;
}
static bool wifi_join(const char *ssid, const char *pass, int timeout_ms)
{
initialise_wifi();
wifi_config_t wifi_config = { 0 };
strlcpy((char *) wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid));
if (pass) {
strlcpy((char *) wifi_config.sta.password, pass, sizeof(wifi_config.sta.password));
}
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
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, timeout_ms / portTICK_PERIOD_MS);
return (bits & CONNECTED_BIT) != 0;
}
/** Arguments used by 'join' function */
static struct {
struct arg_int *timeout;
struct arg_str *ssid;
struct arg_str *password;
struct arg_end *end;
} join_args;
static int connect(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **) &join_args);
if (nerrors != 0) {
arg_print_errors(stderr, join_args.end, argv[0]);
return 1;
}
ESP_LOGI(__func__, "Connecting to '%s'",
join_args.ssid->sval[0]);
/* set default value*/
if (join_args.timeout->count == 0) {
join_args.timeout->ival[0] = JOIN_TIMEOUT_MS;
}
bool connected = wifi_join(join_args.ssid->sval[0],
join_args.password->sval[0],
join_args.timeout->ival[0]);
if (!connected) {
ESP_LOGW(__func__, "Connection timed out");
return 1;
}
ESP_LOGI(__func__, "Connected");
return 0;
}
void register_wifi(void)
{
join_args.timeout = arg_int0(NULL, "timeout", "<t>", "Connection timeout, ms");
join_args.ssid = arg_str1(NULL, NULL, "<ssid>", "SSID of AP");
join_args.password = arg_str0(NULL, NULL, "<pass>", "PSK of AP");
join_args.end = arg_end(2);
const esp_console_cmd_t join_cmd = {
.command = "join",
.help = "Join WiFi AP as a station",
.hint = NULL,
.func = &connect,
.argtable = &join_args
};
ESP_ERROR_CHECK( esp_console_cmd_register(&join_cmd) );
}

View File

@ -1,7 +1,8 @@
#include "Application.h"
#include "CustomCommand.h" #include "CustomCommand.h"
#include "LedController.h" #include "LedController.h"
#include "cmd_nvs.h"
#include "cmd_system.h" #include "cmd_system.h"
#include "cmd_wifi.h"
#include "driver/uart.h" #include "driver/uart.h"
#include "esp_console.h" #include "esp_console.h"
#include "esp_log.h" #include "esp_log.h"
@ -29,13 +30,16 @@ extern "C" void app_main() {
initialize_nvs(); initialize_nvs();
initialize_filesystem(); initialize_filesystem();
initialize_console(); initialize_console();
Application::instance()->initialize();
Application::instance()->setField("author", "amass");
esp_console_register_help_command(); esp_console_register_help_command();
register_system_common(); register_system_common();
register_system_sleep(); register_system_sleep();
register_wifi();
register_custom(); register_custom();
register_nvs();
LedController::instance()->initialize(); LedController::instance()->initialize();
while (true) { while (true) {
char *line = linenoise(prompt); char *line = linenoise(prompt);
if (line == NULL) { /* Break on EOF or error */ if (line == NULL) { /* Break on EOF or error */
@ -73,7 +77,7 @@ static void initialize_console() {
esp_vfs_dev_uart_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR); esp_vfs_dev_uart_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR);
esp_vfs_dev_uart_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF); esp_vfs_dev_uart_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF);
uart_config_t uart_config = {0}; uart_config_t uart_config = {};
uart_config.baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE; uart_config.baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE;
uart_config.data_bits = UART_DATA_8_BITS; uart_config.data_bits = UART_DATA_8_BITS;
uart_config.parity = UART_PARITY_DISABLE; uart_config.parity = UART_PARITY_DISABLE;
@ -84,7 +88,7 @@ static void initialize_console() {
esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM); esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM);
esp_console_config_t console_config = {0}; esp_console_config_t console_config = {};
console_config.max_cmdline_args = 8; console_config.max_cmdline_args = 8;
console_config.max_cmdline_length = 256; console_config.max_cmdline_length = 256;
console_config.hint_color = atoi(LOG_COLOR_CYAN); console_config.hint_color = atoi(LOG_COLOR_CYAN);

View File

@ -2,5 +2,5 @@
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs, data, nvs, 0x9000, 0x6000, nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000, phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1216K, factory, app, factory, 0x10000, 1280K,
storage, data, fat, , 1M, storage, data, fat, , 1M,

1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
3 nvs, data, nvs, 0x9000, 0x6000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 1216K, factory, app, factory, 0x10000, 1280K,
6 storage, data, fat, , 1M,