NVS Refactor ** Factory+Squeezelite FLASH required for this branch!

This is a major refactoring of the nvs parameters storage. To support
this, a new partition was added. To start using this branch, one must
flash all binaries and possibly re-configure the system.
This commit is contained in:
Sebastien
2019-10-03 14:15:59 -04:00
parent 725636e0c4
commit b6f1ce9a7a
22 changed files with 168 additions and 196 deletions

View File

@@ -24,7 +24,7 @@ extern "C" {
#include "esp_err.h" #include "esp_err.h"
#include "cmd_nvs.h" #include "cmd_nvs.h"
#include "nvs.h" #include "nvs.h"
#include "nvs_utilities.h"
typedef struct { typedef struct {
nvs_type_t type; nvs_type_t type;
@@ -47,7 +47,6 @@ static const type_str_pair_t type_str_pair[] = {
static const size_t TYPE_STR_PAIR_SIZE = sizeof(type_str_pair) / sizeof(type_str_pair[0]); 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 const char *ARG_TYPE_STR = "type can be: i8, u8, i16, u16 i32, u32 i64, u64, str, blob";
char current_namespace[] = "config";
static const char * TAG = "platform_esp32"; static const char * TAG = "platform_esp32";
static struct { static struct {
@@ -73,11 +72,6 @@ static struct {
struct arg_end *end; struct arg_end *end;
} erase_all_args; } erase_all_args;
static struct {
struct arg_str *namespace;
struct arg_end *end;
} namespace_args;
static struct { static struct {
struct arg_str *partition; struct arg_str *partition;
struct arg_str *namespace; struct arg_str *namespace;
@@ -175,7 +169,7 @@ static esp_err_t set_value_in_nvs(const char *key, const char *str_type, const c
return ESP_ERR_NVS_TYPE_MISMATCH; return ESP_ERR_NVS_TYPE_MISMATCH;
} }
err = nvs_open(current_namespace, NVS_READWRITE, &nvs); err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READWRITE, &nvs);
if (err != ESP_OK) { if (err != ESP_OK) {
return err; return err;
} }
@@ -262,7 +256,7 @@ static esp_err_t get_value_from_nvs(const char *key, const char *str_type)
return ESP_ERR_NVS_TYPE_MISMATCH; return ESP_ERR_NVS_TYPE_MISMATCH;
} }
err = nvs_open(current_namespace, NVS_READONLY, &nvs); err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READWRITE, &nvs);
if (err != ESP_OK) { if (err != ESP_OK) {
return err; return err;
} }
@@ -339,7 +333,7 @@ static esp_err_t erase(const char *key)
{ {
nvs_handle nvs; nvs_handle nvs;
esp_err_t err = nvs_open(current_namespace, NVS_READWRITE, &nvs); esp_err_t err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READWRITE, &nvs);
if (err == ESP_OK) { if (err == ESP_OK) {
err = nvs_erase_key(nvs, key); err = nvs_erase_key(nvs, key);
if (err == ESP_OK) { if (err == ESP_OK) {
@@ -358,7 +352,7 @@ static esp_err_t erase_all(const char *name)
{ {
nvs_handle nvs; nvs_handle nvs;
esp_err_t err = nvs_open(current_namespace, NVS_READWRITE, &nvs); esp_err_t err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READWRITE, &nvs);
if (err == ESP_OK) { if (err == ESP_OK) {
err = nvs_erase_all(nvs); err = nvs_erase_all(nvs);
if (err == ESP_OK) { if (err == ESP_OK) {
@@ -457,19 +451,7 @@ static int erase_namespace(int argc, char **argv)
return 0; 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(const char *part, const char *name, const char *str_type) static int list(const char *part, const char *name, const char *str_type)
{ {
@@ -528,8 +510,6 @@ void register_nvs()
erase_all_args.namespace = arg_str1(NULL, NULL, "<namespace>", "namespace to be erased"); erase_all_args.namespace = arg_str1(NULL, NULL, "<namespace>", "namespace to be erased");
erase_all_args.end = arg_end(2); 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.partition = arg_str1(NULL, NULL, "<partition>", "partition name");
list_args.namespace = arg_str0("n", "namespace", "<namespace>", "namespace name"); list_args.namespace = arg_str0("n", "namespace", "<namespace>", "namespace name");
list_args.type = arg_str0("t", "type", "<type>", ARG_TYPE_STR); list_args.type = arg_str0("t", "type", "<type>", ARG_TYPE_STR);
@@ -571,13 +551,6 @@ void register_nvs()
.argtable = &erase_all_args .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 = { const esp_console_cmd_t list_entries_cmd = {
.command = "nvs_list", .command = "nvs_list",
@@ -593,7 +566,6 @@ void register_nvs()
ESP_ERROR_CHECK(esp_console_cmd_register(&set_cmd)); 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(&get_cmd));
ESP_ERROR_CHECK(esp_console_cmd_register(&erase_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(&erase_namespace_cmd)); ESP_ERROR_CHECK(esp_console_cmd_register(&erase_namespace_cmd));
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -9,4 +9,5 @@
COMPONENT_ADD_INCLUDEDIRS := . COMPONENT_ADD_INCLUDEDIRS := .
CFLAGS += -I$(COMPONENT_PATH)/../squeezelite-ota CFLAGS += -I$(COMPONENT_PATH)/../squeezelite-ota
COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/components/tools/
COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/main

View File

@@ -96,21 +96,19 @@ static void register_version()
/** 'restart' command restarts the program */ /** 'restart' command restarts the program */
static int restart(int argc, char **argv)
{ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
ESP_LOGI(TAG, "Restarting");
esp_restart();
}
esp_err_t guided_factory()
{ {
#if RECOVERY_APPLICATION #if RECOVERY_APPLICATION
ESP_LOGW(TAG,"RECOVERY application is already active"); if(partition_subtype ==ESP_PARTITION_SUBTYPE_APP_FACTORY){
return ESP_OK; ESP_LOGW(TAG,"RECOVERY application is already active");
return ESP_OK;
}
#else #else
bool bFound=false; bool bFound=false;
ESP_LOGI(TAG, "Looking for recovery partition."); ESP_LOGI(TAG, "Looking for partition type %u",partition_subtype);
const esp_partition_t *partition; const esp_partition_t *partition;
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, partition_subtype, NULL);
if(it == NULL){ if(it == NULL){
ESP_LOGE(TAG,"Unable initialize partition iterator!"); ESP_LOGE(TAG,"Unable initialize partition iterator!");
@@ -120,13 +118,13 @@ esp_err_t guided_factory()
partition = (esp_partition_t *) esp_partition_get(it); partition = (esp_partition_t *) esp_partition_get(it);
if(partition != NULL){ if(partition != NULL){
ESP_LOGI(TAG, "Found recovery partition."); ESP_LOGI(TAG, "Found partition type %u",partition_subtype);
esp_ota_set_boot_partition(partition); esp_ota_set_boot_partition(partition);
bFound=true; bFound=true;
} }
else else
{ {
ESP_LOGE(TAG,"Recovery partition not found! Unable to reboot to recovery."); ESP_LOGE(TAG,"partition type %u not found! Unable to reboot to recovery.",partition_subtype);
} }
esp_partition_iterator_release(it); esp_partition_iterator_release(it);
if(bFound) { if(bFound) {
@@ -137,9 +135,20 @@ esp_err_t guided_factory()
#endif #endif
return ESP_OK; return ESP_OK;
} }
static int restart(int argc, char **argv)
{
ESP_LOGI(TAG, "Restarting");
guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0);
return 0; // return fail. This should never return... we're rebooting!
}
esp_err_t guided_factory(){
guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY);
return ESP_FAIL; // return fail. This should never return... we're rebooting!
}
static int restart_factory(int argc, char **argv) static int restart_factory(int argc, char **argv)
{ {
guided_factory(); guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY);
return 0; // return fail. This should never return... we're rebooting! return 0; // return fail. This should never return... we're rebooting!
} }
static void register_restart() static void register_restart()

View File

@@ -22,7 +22,7 @@
#include "esp_a2dp_api.h" #include "esp_a2dp_api.h"
#include "esp_avrc_api.h" #include "esp_avrc_api.h"
#include "nvs.h" #include "nvs.h"
#include "nvs_utilities.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
@@ -43,12 +43,11 @@
#define CONFIG_BT_NAME "ESP32-BT" #define CONFIG_BT_NAME "ESP32-BT"
#endif #endif
extern char current_namespace[];
/* event for handler "bt_av_hdl_stack_up */ /* event for handler "bt_av_hdl_stack_up */
enum { enum {
BT_APP_EVT_STACK_UP = 0, BT_APP_EVT_STACK_UP = 0,
}; };
char * bt_name = NULL;
static void (*bt_app_a2d_cmd_cb)(bt_sink_cmd_t cmd, ...); static void (*bt_app_a2d_cmd_cb)(bt_sink_cmd_t cmd, ...);
static void (*bt_app_a2d_data_cb)(const uint8_t *data, uint32_t len); static void (*bt_app_a2d_data_cb)(const uint8_t *data, uint32_t len);
@@ -467,17 +466,9 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param)
switch (event) { switch (event) {
case BT_APP_EVT_STACK_UP: { case BT_APP_EVT_STACK_UP: {
/* set up device name */ /* set up device name */
nvs_handle nvs; bt_name = (char * )get_nvs_value_alloc_default(NVS_TYPE_STR, "bt_name", CONFIG_BT_NAME, 0);
char dev_name[32] = CONFIG_BT_NAME; esp_bt_dev_set_device_name(bt_name);
free(bt_name);
if (nvs_open(current_namespace, NVS_READONLY, &nvs) == ESP_OK) {
size_t len = 31;
nvs_get_str(nvs, "bt_name", dev_name, &len);
nvs_close(nvs);
}
esp_bt_dev_set_device_name(dev_name);
esp_bt_gap_register_callback(bt_app_gap_cb); esp_bt_gap_register_callback(bt_app_gap_cb);
/* initialize AVRCP controller */ /* initialize AVRCP controller */

View File

@@ -10,4 +10,4 @@
CFLAGS += -I$(COMPONENT_PATH)/../tools CFLAGS += -I$(COMPONENT_PATH)/../tools
COMPONENT_ADD_INCLUDEDIRS := . COMPONENT_ADD_INCLUDEDIRS := .
COMPONENT_ADD_INCLUDEDIRS += $(COMPONENT_PATH)/../tools COMPONENT_ADD_INCLUDEDIRS += $(COMPONENT_PATH)/../tools
COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/main/

View File

@@ -9,5 +9,5 @@
CFLAGS += -fstack-usage \ CFLAGS += -fstack-usage \
-I$(COMPONENT_PATH)/../tools \ -I$(COMPONENT_PATH)/../tools \
-I$(COMPONENT_PATH)/../codecs/inc/alac -I$(COMPONENT_PATH)/../codecs/inc/alac \
-I$(PROJECT_PATH)/main/

View File

@@ -11,7 +11,7 @@
#include "esp_pthread.h" #include "esp_pthread.h"
#include "esp_system.h" #include "esp_system.h"
#include "freertos/timers.h" #include "freertos/timers.h"
#include "nvs_utilities.h"
#include "raop.h" #include "raop.h"
#include "log_util.h" #include "log_util.h"
@@ -23,7 +23,6 @@
#endif #endif
static const char * TAG = "platform"; static const char * TAG = "platform";
extern char current_namespace[];
log_level raop_loglevel = lINFO; log_level raop_loglevel = lINFO;
log_level util_loglevel; log_level util_loglevel;
@@ -58,11 +57,12 @@ void raop_sink_init(raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb) {
ESP_ERROR_CHECK( mdns_init() ); ESP_ERROR_CHECK( mdns_init() );
ESP_ERROR_CHECK( mdns_hostname_set(hostname) ); ESP_ERROR_CHECK( mdns_hostname_set(hostname) );
if (nvs_open(current_namespace, NVS_READONLY, &nvs) == ESP_OK) { char * sink_name_buffer= get_nvs_value_alloc(NVS_TYPE_STR, "airplay_name");
size_t len = sizeof(sink_name) - 1; if(sink_name_buffer != NULL){
nvs_get_str(nvs, "airplay_name", sink_name, &len); memset(sink_name, 0x00, sizeof(sink_name));
nvs_close(nvs); strncpy(sink_name,sizeof(sink_name)-1, sink_name_buffer );
} free(sink_name_buffer);
}
ESP_LOGI(TAG, "mdns hostname set to: [%s] with servicename %s", hostname, sink_name); ESP_LOGI(TAG, "mdns hostname set to: [%s] with servicename %s", hostname, sink_name);

View File

@@ -269,29 +269,27 @@ void raop_sink_cmd_handler(raop_event_t event, void *param)
* We provide the generic codec register option * We provide the generic codec register option
*/ */
void register_external(void) { void register_external(void) {
#ifdef CONFIG_BT_SINK if (!strcasestr(output.device, "BT ") ) {
if (!strcasestr(output.device, "BT ")) { if(enable_bt_sink){
bt_sink_init(bt_sink_cmd_handler, sink_data_handler); bt_sink_init(bt_sink_cmd_handler, sink_data_handler);
LOG_INFO("Initializing BT sink"); LOG_INFO("Initializing BT sink");
}
} else { } else {
LOG_WARN("Cannot be a BT sink and source"); LOG_WARN("Cannot be a BT sink and source");
} }
#endif if(enable_airplay){
#ifdef CONFIG_AIRPLAY_SINK raop_sink_init(raop_sink_cmd_handler, raop_sink_data_handler);
raop_sink_init(raop_sink_cmd_handler, raop_sink_data_handler); LOG_INFO("Initializing AirPlay sink");
LOG_INFO("Initializing AirPlay sink"); }
#endif
} }
void deregister_external(void) { void deregister_external(void) {
#ifdef CONFIG_BT_SINK if (!strcasestr(output.device, "BT ") && enable_bt_sink) {
if (!strcasestr(output.device, "BT ")) {
bt_sink_deinit(); bt_sink_deinit();
LOG_INFO("Stopping BT sink"); LOG_INFO("Stopping BT sink");
} }
#endif if(enable_airplay){
#ifdef CONFIG_AIRPLAY_SINK raop_sink_deinit();
raop_sink_deinit(); LOG_INFO("Stopping AirPlay sink");
LOG_INFO("Stopping AirPlay sink"); }
#endif
} }

View File

@@ -1,6 +1,6 @@
#ifndef EMBEDDED_H #ifndef EMBEDDED_H
#define EMBEDDED_H #define EMBEDDED_H
#include "esp_system.h"
#include <inttypes.h> #include <inttypes.h>
/* must provide /* must provide
@@ -42,6 +42,9 @@ int pthread_create_name(pthread_t *thread, _CONST pthread_attr_t *attr,
void *(*start_routine)( void * ), void *arg, char *name); void *(*start_routine)( void * ), void *arg, char *name);
// these are here as they can be #define to nothing // these are here as they can be #define to nothing
extern bool enable_bt_sink;
extern bool enable_airplay;
void register_external(void); void register_external(void);
void deregister_external(void); void deregister_external(void);

View File

@@ -109,6 +109,7 @@ extern struct outputstate output;
extern struct buffer *streambuf; extern struct buffer *streambuf;
extern struct buffer *outputbuf; extern struct buffer *outputbuf;
extern u8_t *silencebuf; extern u8_t *silencebuf;
extern bool jack_mutes_amp;
static log_level loglevel; static log_level loglevel;
static bool running, isI2SStarted; static bool running, isI2SStarted;
@@ -433,7 +434,9 @@ static void *output_thread_i2s() {
TIME_MEASUREMENT_START(timer_start); TIME_MEASUREMENT_START(timer_start);
LOCK; LOCK;
if(jack_mutes_amp){
// todo: implement some muting logic
}
// manage led display // manage led display
if (state != output.state) { if (state != output.state) {
LOG_INFO("Output state is %d", output.state); LOG_INFO("Output state is %d", output.state);

View File

@@ -14,3 +14,5 @@ COMPONENT_ADD_INCLUDEDIRS += $(COMPONENT_PATH)/../tools
COMPONENT_ADD_INCLUDEDIRS += $(COMPONENT_PATH)/../squeezelite-ota COMPONENT_ADD_INCLUDEDIRS += $(COMPONENT_PATH)/../squeezelite-ota
COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/main/ COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/main/

View File

@@ -50,7 +50,6 @@ static char *s = "\"";
static char *r = "\\\""; static char *r = "\\\"";
/* @brief task handle for the http server */ /* @brief task handle for the http server */
static TaskHandle_t task_http_server = NULL; static TaskHandle_t task_http_server = NULL;
extern char current_namespace[];
/** /**
* @brief embedded binary data. * @brief embedded binary data.
@@ -74,14 +73,14 @@ extern const uint8_t index_html_end[] asm("_binary_index_html_end");
/* const http headers stored in ROM */ /* const http headers stored in ROM */
const static char http_hdr_template[] = "HTTP/1.1 200 OK\nContent-type: %s\nAccept-Ranges: bytes\nContent-Length: %d\nContent-Encoding: %s\n\n"; const static char http_hdr_template[] = "HTTP/1.1 200 OK\nContent-type: %s\nAccept-Ranges: bytes\nContent-Length: %d\nContent-Encoding: %s\nAccess-Control-Allow-Origin: *\n\n";
const static char http_html_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/html\n\n"; const static char http_html_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/html\nAccess-Control-Allow-Origin: *\n\n";
const static char http_css_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/css\nCache-Control: public, max-age=31536000\n\n"; const static char http_css_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/css\nCache-Control: public, max-age=31536000\nAccess-Control-Allow-Origin: *\n\n";
const static char http_js_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/javascript\n\n"; const static char http_js_hdr[] = "HTTP/1.1 200 OK\nContent-type: text/javascript\nAccess-Control-Allow-Origin: *\n\n";
const static char http_400_hdr[] = "HTTP/1.1 400 Bad Request\nContent-Length: 0\n\n"; const static char http_400_hdr[] = "HTTP/1.1 400 Bad Request\nContent-Length: 0\n\n";
const static char http_404_hdr[] = "HTTP/1.1 404 Not Found\nContent-Length: 0\n\n"; const static char http_404_hdr[] = "HTTP/1.1 404 Not Found\nContent-Length: 0\n\n";
const static char http_503_hdr[] = "HTTP/1.1 503 Service Unavailable\nContent-Length: 0\n\n"; const static char http_503_hdr[] = "HTTP/1.1 503 Service Unavailable\nContent-Length: 0\n\n";
const static char http_ok_json_no_cache_hdr[] = "HTTP/1.1 200 OK\nContent-type: application/json\nCache-Control: no-store, no-cache, must-revalidate, max-age=0\nPragma: no-cache\n\n"; const static char http_ok_json_no_cache_hdr[] = "HTTP/1.1 200 OK\nContent-type: application/json\nCache-Control: no-store, no-cache, must-revalidate, max-age=0\nPragma: no-cache\nAccess-Control-Allow-Origin: *\n\n";
const static char http_redirect_hdr_start[] = "HTTP/1.1 302 Found\nLocation: http://"; const static char http_redirect_hdr_start[] = "HTTP/1.1 302 Found\nLocation: http://";
const static char http_redirect_hdr_end[] = "/\n\n"; const static char http_redirect_hdr_end[] = "/\n\n";
@@ -308,12 +307,18 @@ void http_server_netconn_serve(struct netconn *conn) {
/* captive portal functionality: redirect to access point IP for HOST that are not the access point IP OR the STA IP */ /* captive portal functionality: redirect to access point IP for HOST that are not the access point IP OR the STA IP */
int lenH = 0; int lenH = 0;
char *host = http_server_get_header(save_ptr, "Host: ", &lenH); char *host = http_server_get_header(save_ptr, "Host: ", &lenH);
const char * host_name=NULL;
if((err=tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &host_name )) !=ESP_OK){
ESP_LOGE(TAG,"Unable to get host name. Error: %s",esp_err_to_name(err));
}
/* determine if Host is from the STA IP address */ /* determine if Host is from the STA IP address */
wifi_manager_lock_sta_ip_string(portMAX_DELAY); wifi_manager_lock_sta_ip_string(portMAX_DELAY);
bool access_from_sta_ip = lenH > 0?strstr(host, wifi_manager_get_sta_ip_string()):false; bool access_from_sta_ip = lenH > 0?strstr(host, wifi_manager_get_sta_ip_string()):false;
wifi_manager_unlock_sta_ip_string(); wifi_manager_unlock_sta_ip_string();
bool access_from_host_name = (host_name!=NULL) && strstr(host, host_name);
if (lenH > 0 && !strstr(host, DEFAULT_AP_IP) && !access_from_sta_ip) { if (lenH > 0 && !strstr(host, DEFAULT_AP_IP) && !(access_from_sta_ip || access_from_host_name)) {
ESP_LOGI(TAG,"Redirecting to default AP IP Address : %s", DEFAULT_AP_IP); ESP_LOGI(TAG,"Redirecting to default AP IP Address : %s", DEFAULT_AP_IP);
netconn_write(conn, http_redirect_hdr_start, sizeof(http_redirect_hdr_start) - 1, NETCONN_NOCOPY); netconn_write(conn, http_redirect_hdr_start, sizeof(http_redirect_hdr_start) - 1, NETCONN_NOCOPY);
netconn_write(conn, DEFAULT_AP_IP, sizeof(DEFAULT_AP_IP) - 1, NETCONN_NOCOPY); netconn_write(conn, DEFAULT_AP_IP, sizeof(DEFAULT_AP_IP) - 1, NETCONN_NOCOPY);
@@ -402,16 +407,9 @@ void http_server_netconn_serve(struct netconn *conn) {
bOTA=true; bOTA=true;
} }
else { else {
if(lenA < MAX_COMMAND_LINE_SIZE ){
ESP_LOGD(TAG, "http_server_netconn_serve: config.json/ Storing parameter"); ESP_LOGD(TAG, "http_server_netconn_serve: config.json/ Storing parameter");
wifi_manager_save_config(last_parm,last_parm_name,lenA); err= store_nvs_value(NVS_TYPE_STR, last_parm_name , last_parm);
} if(err!=ESP_OK) ESP_LOGE(TAG,"Unable to save nvs value. Error: %s",esp_err_to_name(err));
else
{
ESP_LOGE(TAG,"length is too long : %s = %s", last_parm_name, last_parm);
last_parm=NULL;
bErrorFound=true;
}
} }
} }
if(last_parm_name!=NULL) { if(last_parm_name!=NULL) {

View File

@@ -59,6 +59,7 @@ Contains the freeRTOS task and all necessary support
#include "driver/gpio.h" #include "driver/gpio.h"
#include "driver/adc.h" #include "driver/adc.h"
#include "cJSON.h" #include "cJSON.h"
#include "nvs_utilities.h"
#ifndef RECOVERY_APPLICATION #ifndef RECOVERY_APPLICATION
#define RECOVERY_APPLICATION 0 #define RECOVERY_APPLICATION 0
@@ -84,6 +85,7 @@ uint16_t ap_num = MAX_AP_NUM;
wifi_ap_record_t *accessp_records; wifi_ap_record_t *accessp_records;
char *accessp_json = NULL; char *accessp_json = NULL;
char *ip_info_json = NULL; char *ip_info_json = NULL;
char *host_name = NULL;
cJSON * ip_info_cjson=NULL; cJSON * ip_info_cjson=NULL;
wifi_config_t* wifi_manager_config_sta = NULL; wifi_config_t* wifi_manager_config_sta = NULL;
static update_reason_code_t last_update_reason_code=0; static update_reason_code_t last_update_reason_code=0;
@@ -113,7 +115,6 @@ struct wifi_settings_t wifi_settings = {
const char wifi_manager_nvs_namespace[] = "config"; const char wifi_manager_nvs_namespace[] = "config";
extern char current_namespace[];
EventGroupHandle_t wifi_manager_event_group; EventGroupHandle_t wifi_manager_event_group;
@@ -185,78 +186,20 @@ void wifi_manager_start(){
wifi_manager_sta_ip = (char*)malloc(sizeof(char) * IP4ADDR_STRLEN_MAX); wifi_manager_sta_ip = (char*)malloc(sizeof(char) * IP4ADDR_STRLEN_MAX);
wifi_manager_safe_update_sta_ip_string((uint32_t)0); wifi_manager_safe_update_sta_ip_string((uint32_t)0);
host_name = (char * )get_nvs_value_alloc_default(NVS_TYPE_STR, "host_name", "squeezelite-esp32", 0);
char * release_url = (char * )get_nvs_value_alloc_default(NVS_TYPE_STR, "release_url", SQUEEZELITE_ESP32_RELEASE_URL, 0);
if(release_url == NULL){
ESP_LOGE(TAG,"Unable to retrieve the release url from nvs");
}
else {
free(release_url);
}
/* start wifi manager task */ /* start wifi manager task */
xTaskCreate(&wifi_manager, "wifi_manager", 4096, NULL, WIFI_MANAGER_TASK_PRIORITY, &task_wifi_manager); xTaskCreate(&wifi_manager, "wifi_manager", 4096, NULL, WIFI_MANAGER_TASK_PRIORITY, &task_wifi_manager);
}
char * wifi_manager_alloc_get_config(char * name, size_t * l){
size_t len=0;
char * value=NULL;
nvs_handle handle;
ESP_LOGD(TAG, "About to get config value %s from flash",name);
esp_err_t esp_err=nvs_open(current_namespace, NVS_READWRITE, &handle);
if(esp_err==ESP_ERR_NVS_NOT_INITIALIZED){
ESP_LOGE(TAG,"Unable to open nvs namespace %s. nvs is not initialized.",wifi_manager_nvs_namespace);
}
else if( esp_err == ESP_OK) {
if (nvs_get_str(handle, name, NULL, &len)==ESP_OK) {
value=(char *)malloc(len);
memset(value,0x0, len);
nvs_get_str(handle, name, value, &len);
*l=len;
ESP_LOGD(TAG,"Found value %s, length %u = %s",name,*l,value);
}
else
{
ESP_LOGW(TAG, "Value %s does one exist in flash",name);
}
nvs_close(handle);
}
else
{
ESP_LOGE(TAG,"Unable to open nvs namespace %s. Error: %d, %s", wifi_manager_nvs_namespace,esp_err, esp_err_to_name(esp_err));
}
return value;
} }
esp_err_t wifi_manager_save_config(char * value, char * name, int len){
nvs_handle handle;
esp_err_t esp_err;
ESP_LOGI(TAG, "About to save config to flash. Name: %s, value: %s", name,value);
esp_err = nvs_open(current_namespace, NVS_READWRITE, &handle);
if(esp_err==ESP_ERR_NVS_NOT_INITIALIZED){
ESP_LOGE(TAG,"Unable to open nvs namespace %s. nvs is not initialized.",wifi_manager_nvs_namespace);
}
else if (esp_err != ESP_OK) {
ESP_LOGE(TAG,"Unable to open nvs namespace %s. Error: %d, %s", wifi_manager_nvs_namespace, esp_err, esp_err_to_name(esp_err));
return esp_err;
}
esp_err = nvs_set_str(handle, name, value);
if (esp_err != ESP_OK){
ESP_LOGE(TAG,"Unable to save value %s=%s",name,value);
nvs_close(handle);
return esp_err;
}
esp_err = nvs_commit(handle);
if (esp_err != ESP_OK){
ESP_LOGE(TAG,"nvs commit error");
return esp_err;
}
nvs_close(handle);
ESP_LOGD(TAG, "wifi_manager_wrote %s=%s with length %i", name, value, len);
return ESP_OK;
}
esp_err_t wifi_manager_save_sta_config(){ esp_err_t wifi_manager_save_sta_config(){
nvs_handle handle; nvs_handle handle;
esp_err_t esp_err; esp_err_t esp_err;
@@ -626,7 +569,7 @@ char* wifi_manager_get_ip_info_json(){
void wifi_manager_destroy(){ void wifi_manager_destroy(){
vTaskDelete(task_wifi_manager); vTaskDelete(task_wifi_manager);
task_wifi_manager = NULL; task_wifi_manager = NULL;
free(host_name);
/* heap buffers */ /* heap buffers */
free(accessp_records); free(accessp_records);
accessp_records = NULL; accessp_records = NULL;
@@ -729,7 +672,7 @@ void wifi_manager( void * pvParameters ){
BaseType_t xStatus; BaseType_t xStatus;
EventBits_t uxBits; EventBits_t uxBits;
uint8_t retries = 0; uint8_t retries = 0;
esp_err_t err=ESP_OK;
/* initialize the tcp stack */ /* initialize the tcp stack */
tcpip_adapter_init(); tcpip_adapter_init();
@@ -782,7 +725,6 @@ void wifi_manager( void * pvParameters ){
ESP_ERROR_CHECK(esp_wifi_set_bandwidth(WIFI_IF_AP, wifi_settings.ap_bandwidth)); ESP_ERROR_CHECK(esp_wifi_set_bandwidth(WIFI_IF_AP, wifi_settings.ap_bandwidth));
ESP_ERROR_CHECK(esp_wifi_set_ps(wifi_settings.sta_power_save)); ESP_ERROR_CHECK(esp_wifi_set_ps(wifi_settings.sta_power_save));
/* STA - Wifi Station configuration setup */ /* STA - Wifi Station configuration setup */
tcpip_adapter_dhcp_status_t status; tcpip_adapter_dhcp_status_t status;
if(wifi_settings.sta_static_ip) { if(wifi_settings.sta_static_ip) {
@@ -802,15 +744,12 @@ void wifi_manager( void * pvParameters ){
ESP_ERROR_CHECK(tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &status)); ESP_ERROR_CHECK(tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &status));
if (status!=TCPIP_ADAPTER_DHCP_STARTED) if (status!=TCPIP_ADAPTER_DHCP_STARTED)
ESP_ERROR_CHECK(tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA)); ESP_ERROR_CHECK(tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA));
} }
/* by default the mode is STA because wifi_manager will not start the access point unless it has to! */ /* by default the mode is STA because wifi_manager will not start the access point unless it has to! */
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_start()); ESP_ERROR_CHECK(esp_wifi_start());
/* start http server */ /* start http server */
http_server_start(); http_server_start();
@@ -906,6 +845,10 @@ void wifi_manager( void * pvParameters ){
else{ else{
/* update config to latest and attempt connection */ /* update config to latest and attempt connection */
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, wifi_manager_get_wifi_sta_config())); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, wifi_manager_get_wifi_sta_config()));
ESP_LOGI(TAG,"Setting host name to : %s",host_name);
if((err=tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, host_name)) !=ESP_OK){
ESP_LOGE(TAG,"Unable to set host name. Error: %s",esp_err_to_name(err));
}
ESP_ERROR_CHECK(esp_wifi_connect()); ESP_ERROR_CHECK(esp_wifi_connect());
} }

View File

@@ -279,19 +279,12 @@ void wifi_manager( void * pvParameters );
char* wifi_manager_get_ap_list_json(); char* wifi_manager_get_ap_list_json();
char* wifi_manager_get_ip_info_json(); char* wifi_manager_get_ip_info_json();
char * wifi_manager_alloc_get_config(char * name, size_t * l);
/** /**
* @brief saves the current STA wifi config to flash ram storage. * @brief saves the current STA wifi config to flash ram storage.
*/ */
esp_err_t wifi_manager_save_sta_config(); esp_err_t wifi_manager_save_sta_config();
/**
* @brief saves the current configuration to flash ram storage
*/
esp_err_t wifi_manager_save_config(char * value, char * name, int len);
/** /**
* @brief fetch a previously STA wifi config in the flash ram storage. * @brief fetch a previously STA wifi config in the flash ram storage.

View File

@@ -2,7 +2,7 @@ set(COMPONENT_ADD_INCLUDEDIRS . )
set(COMPONENT_SRCS "esp_app_main.c" "platform_esp32.c" "cmd_wifi.c" "console.c" "nvs_utilities.c" "cmd_squeezelite.c") set(COMPONENT_SRCS "esp_app_main.c" "platform_esp32.c" "cmd_wifi.c" "console.c" "nvs_utilities.c" "cmd_squeezelite.c")
set(REQUIRES esp_common) set(REQUIRES esp_common)
set(REQUIRES_COMPONENTS freertos squeezelite nvs_flash esp32 spi_flash newlib log console ota ) set(REQUIRES_COMPONENTS freertos squeezelite nvs_flash esp32 spi_flash newlib log console ota tools )
register_component() register_component()

View File

@@ -7,4 +7,6 @@
# please read the SDK documents if you need to do this. # please read the SDK documents if you need to do this.
# #
CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_DEBUG CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_DEBUG
COMPONENT_ADD_INCLUDEDIRS += $(COMPONENT_PATH)/../tools
COMPONENT_EXTRA_INCLUDES += $(PROJECT_PATH)/components/tools/
LDFLAGS += -s LDFLAGS += -s

View File

@@ -40,12 +40,14 @@
#include "lwip/netdb.h" #include "lwip/netdb.h"
#include "nvs_utilities.h" #include "nvs_utilities.h"
#include "http_server.h" #include "http_server.h"
#include "trace.h"
#include "wifi_manager.h" #include "wifi_manager.h"
#include "squeezelite-ota.h" #include "squeezelite-ota.h"
static EventGroupHandle_t wifi_event_group; static EventGroupHandle_t wifi_event_group;
extern char current_namespace[]; bool enable_bt_sink=false;
bool enable_airplay=false;
bool jack_mutes_amp=false;
const int CONNECTED_BIT = BIT0; const int CONNECTED_BIT = BIT0;
#define JOIN_TIMEOUT_MS (10000) #define JOIN_TIMEOUT_MS (10000)
@@ -61,6 +63,9 @@ char * fwurl = NULL;
#endif #endif
static bool bWifiConnected=false; static bool bWifiConnected=false;
/* brief this is an exemple of a callback that you can setup in your own app to get notified of wifi manager event */ /* brief this is an exemple of a callback that you can setup in your own app to get notified of wifi manager event */
void cb_connection_got_ip(void *pvParameter){ void cb_connection_got_ip(void *pvParameter){
ESP_LOGI(TAG, "I have a connection!"); ESP_LOGI(TAG, "I have a connection!");
@@ -104,7 +109,7 @@ char * process_ota_url(){
if(fwurl!=NULL) if(fwurl!=NULL)
{ {
ESP_LOGD(TAG,"Deleting nvs entry for Firmware URL %s", fwurl); ESP_LOGD(TAG,"Deleting nvs entry for Firmware URL %s", fwurl);
esp_err_t err = nvs_open(current_namespace, NVS_READWRITE, &nvs); esp_err_t err = nvs_open_from_partition(settings_partition, current_namespace, NVS_READWRITE, &nvs);
if (err == ESP_OK) { if (err == ESP_OK) {
err = nvs_erase_key(nvs, "fwurl"); err = nvs_erase_key(nvs, "fwurl");
if (err == ESP_OK) { if (err == ESP_OK) {
@@ -133,11 +138,50 @@ char * process_ota_url(){
return fwurl; return fwurl;
} }
//CONFIG_SDIF_NUM=0
//CONFIG_SPDIF_BCK_IO=26
//CONFIG_SPDIF_WS_IO=25
//CONFIG_SPDIF_DO_IO=15
//CONFIG_A2DP_CONTROL_DELAY_MS=500
//CONFIG_A2DP_CONNECT_TIMEOUT_MS=1000
//CONFIG_WIFI_MANAGER_MAX_RETRY=2
void register_default_nvs(){
nvs_value_set_default(NVS_TYPE_STR, "bt_sink_name", CONFIG_BT_NAME, 0);
nvs_value_set_default(NVS_TYPE_STR, "bt_sink_pin", QUOTE(CONFIG_BT_SINK_PIN), 0);
nvs_value_set_default(NVS_TYPE_STR, "host_name", "squeezelite-esp32", 0);
nvs_value_set_default(NVS_TYPE_STR, "release_url", SQUEEZELITE_ESP32_RELEASE_URL, 0);
nvs_value_set_default(NVS_TYPE_STR, "ap_ip_address",CONFIG_DEFAULT_AP_IP , 0);
nvs_value_set_default(NVS_TYPE_STR, "ap_ip_gateway",CONFIG_DEFAULT_AP_GATEWAY , 0);
nvs_value_set_default(NVS_TYPE_STR, "ap_ip_netmask",CONFIG_DEFAULT_AP_NETMASK , 0);
nvs_value_set_default(NVS_TYPE_STR, "ap_channel",QUOTE(CONFIG_DEFAULT_AP_CHANNEL) , 0);
nvs_value_set_default(NVS_TYPE_STR, "ap_ssid",CONFIG_DEFAULT_AP_SSID , 0);
nvs_value_set_default(NVS_TYPE_STR, "ap_password", CONFIG_DEFAULT_AP_PASSWORD, 0);
nvs_value_set_default(NVS_TYPE_STR, "airplay_name",CONFIG_AIRPLAY_NAME , 0);
nvs_value_set_default(NVS_TYPE_STR, "airplay_port", CONFIG_AIRPLAY_PORT, 0);
nvs_value_set_default(NVS_TYPE_STR, "a2dp_sink_name", CONFIG_A2DP_SINK_NAME, 0);
nvs_value_set_default(NVS_TYPE_STR, "a2dp_device_name", CONFIG_A2DP_DEV_NAME, 0);
char * flag = get_nvs_value_alloc_default(NVS_TYPE_STR, "enable_bt_sink", QUOTE(CONFIG_BT_SINK), 0);
enable_bt_sink= (strcmp(flag,"1")==0 ||strcasecmp(flag,"y")==0);
free(flag);
flag = get_nvs_value_alloc_default(NVS_TYPE_STR, "enable_airplay", QUOTE(CONFIG_AIRPLAY_SINK), 0);
enable_airplay= (strcmp(flag,"1")==0 ||strcasecmp(flag,"y")==0);
free(flag);
flag = get_nvs_value_alloc_default(NVS_TYPE_STR, "jack_mutes_amp", "n", 0);
jack_mutes_amp= (strcmp(flag,"1")==0 ||strcasecmp(flag,"y")==0);
free(flag);
}
void app_main() void app_main()
{ {
char * fwurl = NULL; char * fwurl = NULL;
initialize_nvs(); initialize_nvs();
register_default_nvs();
led_config(LED_GREEN, LED_GREEN_GPIO, 0); led_config(LED_GREEN, LED_GREEN_GPIO, 0);
led_config(LED_RED, LED_RED_GPIO, 0); led_config(LED_RED, LED_RED_GPIO, 0);
wifi_event_group = xEventGroupCreate(); wifi_event_group = xEventGroupCreate();

View File

@@ -13,9 +13,11 @@
#include "esp_vfs_fat.h" #include "esp_vfs_fat.h"
#include "nvs.h" #include "nvs.h"
#include "nvs_flash.h" #include "nvs_flash.h"
extern char current_namespace[];
const char current_namespace[] = "config";
const char settings_partition[] = "settings";
static const char * TAG = "platform_esp32"; static const char * TAG = "platform_esp32";
bool isNameValid(char * key){ bool isNameValid(char * key){
bool bFound=false; bool bFound=false;
nvs_handle nvs; nvs_handle nvs;
@@ -99,9 +101,10 @@ esp_err_t store_nvs_value_len(nvs_type_t type, const char *key, void * data,
nvs_close(nvs); nvs_close(nvs);
return err; return err;
} }
void nvs_value_set_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size) {
free(get_nvs_value_alloc_default(type, key, default_value, blob_size));
}
void * get_nvs_value_alloc_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size) { void * get_nvs_value_alloc_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size) {
void * current_value = get_nvs_value_alloc(type, key); void * current_value = get_nvs_value_alloc(type, key);
if(current_value == NULL && default_value != NULL){ if(current_value == NULL && default_value != NULL){
if(type == NVS_TYPE_BLOB && blob_size == 0){ if(type == NVS_TYPE_BLOB && blob_size == 0){
@@ -114,6 +117,9 @@ void * get_nvs_value_alloc_default(nvs_type_t type, const char *key, void * defa
ESP_LOGE(TAG,"Unable to store default nvs value. Error: %s",esp_err_to_name(err)); ESP_LOGE(TAG,"Unable to store default nvs value. Error: %s",esp_err_to_name(err));
return NULL; return NULL;
} }
else{
ESP_LOGI(TAG,"Stored new default value for key %s", key);
}
} }
} }
if(current_value == NULL){ if(current_value == NULL){

View File

@@ -4,6 +4,8 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
extern const char current_namespace[];
extern const char settings_partition[];
bool isNameValid(char * key); bool isNameValid(char * key);
esp_err_t store_nvs_value_len(nvs_type_t type, const char *key, void * data, size_t data_len); esp_err_t store_nvs_value_len(nvs_type_t type, const char *key, void * data, size_t data_len);
esp_err_t store_nvs_value(nvs_type_t type, const char *key, void * data); esp_err_t store_nvs_value(nvs_type_t type, const char *key, void * data);
@@ -11,6 +13,7 @@ esp_err_t get_nvs_value(nvs_type_t type, const char *key, void*value, const uint
void * get_nvs_value_alloc(nvs_type_t type, const char *key); void * get_nvs_value_alloc(nvs_type_t type, const char *key);
esp_err_t erase_nvs(const char *key); esp_err_t erase_nvs(const char *key);
void * get_nvs_value_alloc_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size); void * get_nvs_value_alloc_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size);
void nvs_value_set_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -22,6 +22,9 @@
#pragma once #pragma once
#include "esp_pthread.h" #include "esp_pthread.h"
#ifndef SQUEEZELITE_ESP32_RELEASE_URL
#define SQUEEZELITE_ESP32_RELEASE_URL "https://github.com/sle118/squeezelite-esp32/releases"
#endif
extern void run_command(char * line); extern void run_command(char * line);
extern bool wait_for_wifi(); extern bool wait_for_wifi();

View File

@@ -4,4 +4,5 @@ nvs, data, nvs, 0x9000, 0x4000,
otadata, data, ota, 0xD000, 0x2000, otadata, data, ota, 0xD000, 0x2000,
phy_init, data, phy, 0xF000, 0x1000, phy_init, data, phy, 0xF000, 0x1000,
recovery, app, factory, 0x10000, 0x140000, recovery, app, factory, 0x10000, 0x140000,
ota_0, app, ota_0, 0x150000, 0x2B0000, ota_0, app, ota_0, 0x150000, 0x2A0000,
settings, data, nvs, 0x3F0000, 0x10000,
1 # Name, Type, SubType, Offset, Size, Flags
4 otadata, data, ota, 0xD000, 0x2000,
5 phy_init, data, phy, 0xF000, 0x1000,
6 recovery, app, factory, 0x10000, 0x140000,
7 ota_0, app, ota_0, 0x150000, 0x2B0000, ota_0, app, ota_0, 0x150000, 0x2A0000,
8 settings, data, nvs, 0x3F0000, 0x10000,