Compare commits

...

8 Commits

Author SHA1 Message Date
Philippe G
797a21ee9f release 2020-09-26 12:21:45 -07:00
Philippe G
7f1db60c45 fix reboot logic upon server loss - release 2020-09-25 21:50:44 -07:00
Philippe G
fb530645b8 CRLF 2020-09-25 19:01:53 -07:00
Sébastien
7f932630fc release 2020-09-13 16:47:00 -04:00
Sebastien
458efb376a Merge branch 'master-cmake' of https://github.com/sle118/squeezelite-esp32.git into master-cmake 2020-09-13 12:17:38 -04:00
Sebastien
3ffbe022e5 Added wifi scanmode NVS option - release
f= default, fast scan
a= All channel scan
2020-09-13 12:17:27 -04:00
Philippe G
762c529563 fix a couple of gpio names (SPI/I2C)
Also a few "style" consistency changes so that within each file, look is the same, although different files can have different styles
2020-09-12 22:58:52 -07:00
Sebastien
0c224b4b84 New config UI for Services (Airplay, bt, etc) - release 2020-09-12 23:09:38 -04:00
15 changed files with 1890 additions and 1805 deletions

View File

@@ -353,4 +353,3 @@ See squeezlite command line, but keys options are
- git clone --recursive https://github.com/sle118/squeezelite-esp32.git - git clone --recursive https://github.com/sle118/squeezelite-esp32.git
- If you have already cloned the repository and you are getting compile errors on one of the submodules (e.g. telnet), run the following git command in the root of the repository location - If you have already cloned the repository and you are getting compile errors on one of the submodules (e.g. telnet), run the following git command in the root of the repository location
- git submodule update --init --recursive - git submodule update --init --recursive

View File

@@ -1,4 +1,3 @@
idf_component_register(SRC_DIRS . core core/ifaces fonts idf_component_register(SRC_DIRS . core core/ifaces fonts
INCLUDE_DIRS . fonts core INCLUDE_DIRS . fonts core
REQUIRES platform_config tools esp_common REQUIRES platform_config tools esp_common

View File

@@ -1179,7 +1179,7 @@ cJSON * spiconfig_cb(){
static void register_spiconfig(void) static void register_spiconfig(void)
{ {
spiconfig_args.clear = arg_lit0(NULL, "clear", "Clear configuration"); spiconfig_args.clear = arg_lit0(NULL, "clear", "Clear configuration");
spiconfig_args.clk = arg_int0("k", "clock", "<n>", "Clock GPIO"); spiconfig_args.clk = arg_int0("k", "clk", "<n>", "Clock GPIO");
spiconfig_args.data = arg_int0("d","data", "<n>","Data GPIO"); spiconfig_args.data = arg_int0("d","data", "<n>","Data GPIO");
spiconfig_args.dc = arg_int0("c","dc", "<n>", "DC GPIO"); spiconfig_args.dc = arg_int0("c","dc", "<n>", "DC GPIO");
spiconfig_args.host= arg_int0("h", "host", "int", "SPI Host Number"); spiconfig_args.host= arg_int0("h", "host", "int", "SPI Host Number");
@@ -1198,7 +1198,7 @@ static void register_i2cconfig(void)
{ {
i2cconfig_args.clear = arg_lit0(NULL, "clear", "Clear configuration"); i2cconfig_args.clear = arg_lit0(NULL, "clear", "Clear configuration");
i2cconfig_args.port = arg_int0("p", "port", "0|1", "Port"); i2cconfig_args.port = arg_int0("p", "port", "0|1", "Port");
i2cconfig_args.freq = arg_int0("f", "freq", "int", "Frequency (Hz) e.g. 100000"); i2cconfig_args.freq = arg_int0("f", "speed", "int", "Frequency (Hz) e.g. 100000");
i2cconfig_args.sda = arg_int0("d", "sda", "<n>", "SDA GPIO. e.g. 19"); i2cconfig_args.sda = arg_int0("d", "sda", "<n>", "SDA GPIO. e.g. 19");
i2cconfig_args.scl = arg_int0("c", "scl", "<n>", "SCL GPIO. e.g. 18"); i2cconfig_args.scl = arg_int0("c", "scl", "<n>", "SCL GPIO. e.g. 18");
i2cconfig_args.load = arg_lit0("l", "load", "Load Existing Configuration"); i2cconfig_args.load = arg_lit0("l", "load", "Load Existing Configuration");

View File

@@ -41,7 +41,13 @@ static struct {
struct arg_str *name; struct arg_str *name;
struct arg_end *end; struct arg_end *end;
} name_args; } name_args;
static struct {
struct arg_lit *telnet;
struct arg_lit *btspeaker;
struct arg_lit *airplay;
struct arg_lit *stats;
struct arg_end *end;
} set_services_args;
static const char * TAG = "cmd_system"; static const char * TAG = "cmd_system";
static void register_setbtsource(); static void register_setbtsource();
@@ -55,6 +61,7 @@ static void register_light_sleep();
static void register_factory_boot(); static void register_factory_boot();
static void register_restart_ota(); static void register_restart_ota();
static void register_update_certs(); static void register_update_certs();
static void register_set_services();
#if WITH_TASKS_INFO #if WITH_TASKS_INFO
static void register_tasks(); static void register_tasks();
#endif #endif
@@ -63,6 +70,7 @@ void register_system()
{ {
register_setbtsource(); register_setbtsource();
register_free(); register_free();
register_set_services();
register_heap(); register_heap();
register_setdevicename(); register_setdevicename();
register_version(); register_version();
@@ -110,9 +118,6 @@ static void register_version()
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
} }
/** 'restart' command restarts the program */
esp_err_t guided_boot(esp_partition_subtype_t partition_subtype) esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
{ {
if(is_recovery_running){ if(is_recovery_running){
@@ -582,7 +587,80 @@ static void register_deep_sleep()
}; };
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
} }
static int enable_disable(FILE * f,char * nvs_name, struct arg_lit *arg){
esp_err_t err = config_set_value(NVS_TYPE_STR, nvs_name, arg->count>0?"Y":"N");
const char * name = arg->hdr.longopts?arg->hdr.longopts:arg->hdr.glossary;
if(err!=ESP_OK){
fprintf(f,"Error %s %s. %s\n",arg->count>0?"Enabling":"Disabling", name, esp_err_to_name(err));
}
else {
fprintf(f,"%s %s\n",arg->count>0?"Enabled":"Disabled",name);
}
return err;
}
static int do_set_services(int argc, char **argv)
{
int nerrors = arg_parse_msg(argc, argv,(struct arg_hdr **)&set_services_args);
if (nerrors != 0) {
return 0;
}
char *buf = NULL;
size_t buf_size = 0;
FILE *f = open_memstream(&buf, &buf_size);
if (f == NULL) {
log_send_messaging(MESSAGING_ERROR,"Unable to open memory stream.");
return 0;
}
nerrors += enable_disable(f,"enable_airplay",set_services_args.airplay);
nerrors += enable_disable(f,"enable_bt_sink",set_services_args.btspeaker);
nerrors += enable_disable(f,"telnet_enable",set_services_args.telnet);
nerrors += enable_disable(f,"stats",set_services_args.stats);
fflush (f);
log_send_messaging(nerrors>0?MESSAGING_ERROR:MESSAGING_INFO,"%s", buf);
fclose(f);
FREE_AND_NULL(buf);
return nerrors==0;
}
cJSON * set_services_cb(){
cJSON * values = cJSON_CreateObject();
char * p=NULL;
if ((p = config_alloc_get(NVS_TYPE_STR, "enable_bt_sink")) != NULL) {
cJSON_AddBoolToObject(values,"BT_Speaker",strcmp(p,"1") == 0 || strcasecmp(p,"y") == 0);
FREE_AND_NULL(p);
}
if ((p = config_alloc_get(NVS_TYPE_STR, "enable_airplay")) != NULL) {
cJSON_AddBoolToObject(values,"AirPlay",strcmp(p,"1") == 0 || strcasecmp(p,"y") == 0);
FREE_AND_NULL(p);
}
if ((p = config_alloc_get(NVS_TYPE_STR, "telnet_enable")) != NULL) {
cJSON_AddBoolToObject(values,"telnet",strcasestr("YXD",p)!=NULL);
FREE_AND_NULL(p);
}
if((p = config_alloc_get_default(NVS_TYPE_STR, "stats", "n", 0))!=NULL){
cJSON_AddBoolToObject(values,"stats",(*p == '1' || *p == 'Y' || *p == 'y')) ;
}
return values;
}
static void register_set_services(){
set_services_args.airplay = arg_lit0(NULL, "AirPlay", "AirPlay");
set_services_args.btspeaker = arg_lit0(NULL, "BT_Speaker", "Bluetooth Speaker");
set_services_args.telnet= arg_lit0(NULL, "telnet", "Telnet server. Use only for troubleshooting");
set_services_args.stats= arg_lit0(NULL, "stats", "System Statistics. Use only for troubleshooting");
set_services_args.end=arg_end(2);
const esp_console_cmd_t cmd = {
.command = "set_services",
.help = "Services",
.argtable = &set_services_args,
.hint = NULL,
.func = &do_set_services,
};
cmd_to_json_with_cb(&cmd,&set_services_cb);
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
}
/** 'light_sleep' command puts the chip into light sleep mode */ /** 'light_sleep' command puts the chip into light sleep mode */
static struct { static struct {

View File

@@ -228,7 +228,6 @@ void raop_delete(struct raop_ctx_s *ctx) {
ctx->running = false; ctx->running = false;
// wake-up thread by connecting socket, needed for freeBSD // wake-up thread by connecting socket, needed for freeBSD
sock = socket(AF_INET, SOCK_STREAM, 0);
sock = socket(AF_INET, SOCK_STREAM, 0); sock = socket(AF_INET, SOCK_STREAM, 0);
getsockname(ctx->sock, (struct sockaddr *) &addr, &nlen); getsockname(ctx->sock, (struct sockaddr *) &addr, &nlen);
connect(sock, (struct sockaddr*) &addr, sizeof(addr)); connect(sock, (struct sockaddr*) &addr, sizeof(addr));
@@ -248,13 +247,16 @@ void raop_delete(struct raop_ctx_s *ctx) {
// stop broadcasting devices // stop broadcasting devices
mdns_service_remove(ctx->svr, ctx->svc); mdns_service_remove(ctx->svr, ctx->svc);
mdnsd_stop(ctx->svr);
#else
// then the RTSP task
ctx->joiner = xTaskGetCurrentTaskHandle();
ctx->running = false;
// brute-force exit of accept() // brute-force exit of accept()
shutdown(ctx->sock, SHUT_RDWR); shutdown(ctx->sock, SHUT_RDWR);
closesocket(ctx->sock); closesocket(ctx->sock);
ctx->running = false;
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
// wait to make sure LWIP if scheduled (avoid issue with NotifyTake) // wait to make sure LWIP if scheduled (avoid issue with NotifyTake)
vTaskDelay(100 / portTICK_PERIOD_MS); vTaskDelay(100 / portTICK_PERIOD_MS);
ulTaskNotifyTake(pdFALSE, portMAX_DELAY); ulTaskNotifyTake(pdFALSE, portMAX_DELAY);

View File

@@ -47,6 +47,7 @@ esp_err_t config_i2c_set(const i2c_config_t * config, int port){
} }
return ESP_OK; return ESP_OK;
} }
/**************************************************************************************** /****************************************************************************************
* *
*/ */
@@ -259,32 +260,28 @@ esp_err_t get_gpio_structure(cJSON * gpio_entry, gpio_entry_t ** gpio){
cJSON * val = cJSON_GetObjectItem(gpio_entry,"gpio"); cJSON * val = cJSON_GetObjectItem(gpio_entry,"gpio");
if(val){ if(val){
(*gpio)->gpio= (int)val->valuedouble; (*gpio)->gpio= (int)val->valuedouble;
} } else {
else {
ESP_LOGE(TAG,"gpio pin not found"); ESP_LOGE(TAG,"gpio pin not found");
err=ESP_FAIL; err=ESP_FAIL;
} }
val = cJSON_GetObjectItem(gpio_entry,"name"); val = cJSON_GetObjectItem(gpio_entry,"name");
if(val){ if(val){
(*gpio)->name= strdup(cJSON_GetStringValue(val)); (*gpio)->name= strdup(cJSON_GetStringValue(val));
} } else {
else {
ESP_LOGE(TAG,"gpio name value not found"); ESP_LOGE(TAG,"gpio name value not found");
err=ESP_FAIL; err=ESP_FAIL;
} }
val = cJSON_GetObjectItem(gpio_entry,"group"); val = cJSON_GetObjectItem(gpio_entry,"group");
if(val){ if(val){
(*gpio)->group= strdup(cJSON_GetStringValue(val)); (*gpio)->group= strdup(cJSON_GetStringValue(val));
} } else {
else {
ESP_LOGE(TAG,"gpio group value not found"); ESP_LOGE(TAG,"gpio group value not found");
err=ESP_FAIL; err=ESP_FAIL;
} }
val = cJSON_GetObjectItem(gpio_entry,"fixed"); val = cJSON_GetObjectItem(gpio_entry,"fixed");
if(val){ if(val){
(*gpio)->fixed= cJSON_IsTrue(val); (*gpio)->fixed= cJSON_IsTrue(val);
} } else {
else {
ESP_LOGE(TAG,"gpio fixed indicator not found"); ESP_LOGE(TAG,"gpio fixed indicator not found");
err=ESP_FAIL; err=ESP_FAIL;
} }
@@ -357,8 +354,7 @@ cJSON * get_gpio_list() {
if (bat_config) { if (bat_config) {
char *p; char *p;
int channel; int channel;
if ((p = strcasestr(bat_config, "channel") ) != NULL) if ((p = strcasestr(bat_config, "channel") ) != NULL) {
{
channel = atoi(strchr(p, '=') + 1); channel = atoi(strchr(p, '=') + 1);
if(channel != -1){ if(channel != -1){
if(adc1_pad_get_io_num(channel,&gpio_num )==ESP_OK){ if(adc1_pad_get_io_num(channel,&gpio_num )==ESP_OK){

View File

@@ -237,7 +237,7 @@ void monitor_svc_init(void) {
monitor_timer = xTimerCreate("monitor", MONITOR_TIMER / portTICK_RATE_MS, pdTRUE, NULL, monitor_callback); monitor_timer = xTimerCreate("monitor", MONITOR_TIMER / portTICK_RATE_MS, pdTRUE, NULL, monitor_callback);
xTimerStart(monitor_timer, portMAX_DELAY); xTimerStart(monitor_timer, portMAX_DELAY);
} }
free(p); FREE_AND_NULL(p);
ESP_LOGI(TAG, "Heap internal:%zu (min:%zu) external:%zu (min:%zu)", ESP_LOGI(TAG, "Heap internal:%zu (min:%zu) external:%zu (min:%zu)",
heap_caps_get_free_size(MALLOC_CAP_INTERNAL), heap_caps_get_free_size(MALLOC_CAP_INTERNAL),

View File

@@ -327,12 +327,12 @@ void register_external(void) {
void deregister_external(void) { void deregister_external(void) {
if (!strcasestr(output.device, "BT ") && enable_bt_sink) { if (!strcasestr(output.device, "BT ") && enable_bt_sink) {
bt_sink_deinit();
LOG_INFO("Stopping BT sink"); LOG_INFO("Stopping BT sink");
bt_sink_deinit();
} }
if (enable_airplay){ if (enable_airplay){
raop_sink_deinit();
LOG_INFO("Stopping AirPlay sink"); LOG_INFO("Stopping AirPlay sink");
raop_sink_deinit();
} }
} }

View File

@@ -35,7 +35,7 @@ typedef unsigned long long u64_t;
#define OUTPUT_THREAD_STACK_SIZE 6 * 1024 #define OUTPUT_THREAD_STACK_SIZE 6 * 1024
#define IR_THREAD_STACK_SIZE 6 * 1024 #define IR_THREAD_STACK_SIZE 6 * 1024
// number of 5s times search for a server will happen beforee slimproto exits (0 = no limit) // number of times the 5s search for a server will happen before slimproto exits (0 = no limit)
#define MAX_SERVER_RETRIES 5 #define MAX_SERVER_RETRIES 5
// or can be as simple as #define PLAYER_ID 100 // or can be as simple as #define PLAYER_ID 100

View File

@@ -962,7 +962,7 @@ void slimproto(log_level level, char *server, u8_t mac[6], const char *name, con
if (++failed_connect > 5 && !server) { if (++failed_connect > 5 && !server) {
slimproto_ip = serv_addr.sin_addr.s_addr = discover_server(NULL, MAX_SERVER_RETRIES); slimproto_ip = serv_addr.sin_addr.s_addr = discover_server(NULL, MAX_SERVER_RETRIES);
if (!slimproto_ip) return; if (!slimproto_ip) return;
} else if (MAX_SERVER_RETRIES && failed_connect > 5 * MAX_SERVER_RETRIES) return; } else if (reconnect && MAX_SERVER_RETRIES && failed_connect > 5 * MAX_SERVER_RETRIES) return;
#else #else
// rediscover server if it was not set at startup or exit // rediscover server if it was not set at startup or exit
if (!server && ++failed_connect > 5) { if (!server && ++failed_connect > 5) {

View File

@@ -1243,8 +1243,9 @@ function getCommands() {
} }
function getConfig() { function getConfig() {
$.getJSON("/config.json", function(data) { $.getJSON("/config.json", function(entries) {
Object.keys(data.hasOwnProperty('config') ? data.config : data).sort().forEach(function(key, i) { data = entries.hasOwnProperty('config') ? entries.config : entries;
Object.keys(data).sort().forEach(function(key, i) {
if (data.hasOwnProperty(key)) { if (data.hasOwnProperty(key)) {
if (key == 'autoexec') { if (key == 'autoexec') {
if (data["autoexec"].value === "1") { if (data["autoexec"].value === "1") {
@@ -1280,9 +1281,9 @@ function getConfig() {
} }
}); });
$("tbody#nvsTable").append("<tr><td><input type='text' class='form-control' id='nvs-new-key' placeholder='new key'></td><td><input type='text' class='form-control' id='nvs-new-value' placeholder='new value' nvs_type=33 ></td></tr>"); $("tbody#nvsTable").append("<tr><td><input type='text' class='form-control' id='nvs-new-key' placeholder='new key'></td><td><input type='text' class='form-control' id='nvs-new-value' placeholder='new value' nvs_type=33 ></td></tr>");
if (data.hasOwnProperty('gpio')) { if (entries.hasOwnProperty('gpio')) {
data.gpio.forEach(function(gpio_entry) { entries.gpio.forEach(function(gpio_entry) {
cl = gpio_entry.fixed ? "table-light" : "table-dark"; cl = gpio_entry.fixed ? "table-secondary" : "table-primary";
$("tbody#gpiotable").append('<tr class=' + cl + '><th scope="row">' + gpio_entry.group + '</th><td>' + gpio_entry.name + '</td><td>' + gpio_entry.gpio + '</td><td>' + (gpio_entry.fixed ? 'Fixed':'Configuration') + '</td></tr>'); $("tbody#gpiotable").append('<tr class=' + cl + '><th scope="row">' + gpio_entry.group + '</th><td>' + gpio_entry.name + '</td><td>' + gpio_entry.gpio + '</td><td>' + (gpio_entry.fixed ? 'Fixed':'Configuration') + '</td></tr>');
}); });
} }

View File

@@ -207,6 +207,7 @@
</div> </div>
<!-- wifi --> <!-- wifi -->
<div class="tab-pane fade" id="tab-setdisplay"> <div class="tab-pane fade" id="tab-setdisplay">
<div id="set_services-list"></div>
<div id="setname-list"></div> <div id="setname-list"></div>
<div id="setdisplay-list"></div> <div id="setdisplay-list"></div>
<div id="i2cconfig-list"></div> <div id="i2cconfig-list"></div>

File diff suppressed because one or more lines are too long

View File

@@ -274,7 +274,7 @@ void wifi_manager_init_wifi(){
ESP_LOGD(TAG, "Initializing wifi. Starting wifi"); ESP_LOGD(TAG, "Initializing wifi. Starting wifi");
char * disable_ps = config_alloc_get_default(NVS_TYPE_STR, "disable_ps", "n", 0); char * disable_ps = config_alloc_get_default(NVS_TYPE_STR, "disable_ps", "n", 0);
if (gpio36_39_used || (disable_ps && strcasecmp(disable_ps,"y"))) { if (gpio36_39_used || (disable_ps && strcasecmp(disable_ps,"y")==0)) {
if(gpio36_39_used){ if(gpio36_39_used){
ESP_LOGW(TAG, "GPIO 36 or 39 are in use, need to disable WiFi PowerSave!"); ESP_LOGW(TAG, "GPIO 36 or 39 are in use, need to disable WiFi PowerSave!");
} }
@@ -1284,7 +1284,16 @@ void wifi_manager( void * pvParameters ){
} }
} }
ESP_LOGD(TAG, "MESSAGE: ORDER_CONNECT_STA - setting config for WIFI_IF_STA"); ESP_LOGD(TAG, "MESSAGE: ORDER_CONNECT_STA - setting config for WIFI_IF_STA");
if((err=esp_wifi_set_config(WIFI_IF_STA, wifi_manager_get_wifi_sta_config()))!=ESP_OK) { wifi_config_t* cfg = wifi_manager_get_wifi_sta_config();
char * scan_mode = config_alloc_get_default(NVS_TYPE_STR, "wifi_smode", "f", 0);
if (scan_mode && strcasecmp(scan_mode,"a")==0) {
cfg->sta.scan_method=WIFI_ALL_CHANNEL_SCAN;
}
else {
cfg->sta.scan_method=WIFI_FAST_SCAN;
}
FREE_AND_NULL(scan_mode);
if((err=esp_wifi_set_config(WIFI_IF_STA, cfg))!=ESP_OK) {
ESP_LOGE(TAG, "Failed to set STA configuration. Error %s",esp_err_to_name(err)); ESP_LOGE(TAG, "Failed to set STA configuration. Error %s",esp_err_to_name(err));
break; break;
} }