Compare commits

...

13 Commits

Author SHA1 Message Date
Sebastien L
c76bbc3524 Fix recovery 2023-10-28 22:48:12 -04:00
philippe44
9619b1d792 Update CHANGELOG 2023-10-28 00:13:39 -07:00
philippe44
0bbd5a064f Merge branch 'master-v4.3' of https://github.com/sle118/squeezelite-esp32 into master-v4.3 2023-10-27 18:27:24 -07:00
philippe44
986521fd4a fix vorbis & opus memory leaks 2023-10-27 18:26:57 -07:00
github-actions
406a56a3a3 Update prebuilt objects [skip actions] 2023-10-26 05:59:15 +00:00
philippe44
c9455f70ff Update CHANGELOG 2023-10-25 22:47:14 -07:00
philippe44
b5b76480e4 Merge branch 'master-v4.3' of https://github.com/sle118/squeezelite-esp32 into master-v4.3 2023-10-25 22:45:37 -07:00
philippe44
e6744deab8 fix vorbis not closing properly - release 2023-10-25 22:45:26 -07:00
github-actions
94baf86989 Update prebuilt objects [skip actions] 2023-10-25 01:48:05 +00:00
philippe44
0c856a37c1 well, fix 16 bits as well... 2023-10-24 16:27:27 -07:00
philippe44
d5f28375ce fix SPDIF miscount 2023-10-24 13:39:56 -07:00
philippe44
7ea5a93647 backport webUI changes as well (-disable) 2023-10-23 17:15:02 -07:00
philippe44
ca38a14420 cspot fixes backport 2023-10-23 17:09:50 -07:00
47 changed files with 2567 additions and 2394 deletions

View File

@@ -1,3 +1,13 @@
2023-10-27
- fix vorbis (and opus) memory leak
2023-10-25
- fix vorbis codec close
2023-10-23
- fix Spotify track insertion
- [WEB] Allow running without LMS with option "Audio/Disable Squeezelite"
2023-10.07 2023-10.07
- catchup with official cspot - catchup with official cspot

View File

@@ -25,7 +25,11 @@ ENV GCC_TOOLS_BASE=/opt/esp/tools/xtensa-esp32-elf/esp-2021r2-patch3-8.4.0/xtens
# pushd components/wifi-manager/webapp/ && npm install && npm run-script build && popd # pushd components/wifi-manager/webapp/ && npm install && npm run-script build && popd
# #
# to run the docker with netwotrk port published on the host: # to run the docker with netwotrk port published on the host:
# (windows)
# docker run --rm -p 5000:5000/tcp -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv435 # docker run --rm -p 5000:5000/tcp -v %cd%:/project -w /project -it sle118/squeezelite-esp32-idfv435
# (linux)
# docker run --rm -p 5000:5000/tcp -v `pwd`:/project -w /project -it sle118/squeezelite-esp32-idfv435
ARG IDF_CLONE_URL=https://github.com/espressif/esp-idf.git ARG IDF_CLONE_URL=https://github.com/espressif/esp-idf.git
ARG IDF_CLONE_BRANCH_OR_TAG=master ARG IDF_CLONE_BRANCH_OR_TAG=master

View File

@@ -187,7 +187,7 @@ bck=<gpio>,ws=<gpio>,do=<gpio>[,mck=0|1|2][,mute=<gpio>[:0|1][,model=TAS57xx|TAS
``` ```
if "model" is not set or is not recognized, then default "I2S" is used. The option "mck" is used for some codecs that require a master clock (although they should not). By default GPIO0 is used as MCLK and only recent builds (post mid-2023) can use 1 or 2. Also be aware that this cannot coexit with RMII Ethernet (see ethernet section below). I2C parameters are optional and only needed if your DAC requires an I2C control (See 'dac_controlset' below). Note that "i2c" parameters are decimal, hex notation is not allowed. if "model" is not set or is not recognized, then default "I2S" is used. The option "mck" is used for some codecs that require a master clock (although they should not). By default GPIO0 is used as MCLK and only recent builds (post mid-2023) can use 1 or 2. Also be aware that this cannot coexit with RMII Ethernet (see ethernet section below). I2C parameters are optional and only needed if your DAC requires an I2C control (See 'dac_controlset' below). Note that "i2c" parameters are decimal, hex notation is not allowed.
So far, TAS57xx, TAS5713, AC101, WM8978 and ES8388 are recognized models where the proper init sequence/volume/power controls are sent. For other codecs that might require an I2C commands, please use the parameter "dac_controlset" that allows definition of simple commands to be sent over i2c for init, power, speakder and headset on and off using a JSON syntax: So far, TAS57xx, TAS5713, AC101, WM8978 and ES8388 are recognized models where the proper init sequence/volume/power controls are sent. For other codecs that might require an I2C commands, please use the parameter "dac_controlset" that allows definition of simple commands to be sent over i2c for init, power, speaker and headset on and off using a JSON syntax:
```json ```json
{ <command>: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ], { <command>: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ],
<command>: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ], <command>: [ {"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"}, ... {{"reg":<register>,"val":<value>,"mode":<nothing>|"or"|"and"} ],
@@ -197,6 +197,8 @@ Where `<command>` is one of init, poweron, poweroff, speakeron, speakeroff, head
This is standard JSON notation, so if you are not familiar with it, Google is your best friend. Be aware that the '...' means you can have as many entries as you want, it's not part of the syntax. Every section is optional, but it does not make sense to set i2c in the 'dac_config' parameter and not setting anything here. The parameter 'mode' allows to *or* the register with the value or to *and* it. Don't set 'mode' if you simply want to write. The 'val parameter can be an array [v1, v2,...] to write a serie of bytes in a single i2c burst (in that case 'mode' is ignored). **Note that all values must be decimal**. You can use a validator like [this](https://jsonlint.com) to verify your syntax This is standard JSON notation, so if you are not familiar with it, Google is your best friend. Be aware that the '...' means you can have as many entries as you want, it's not part of the syntax. Every section is optional, but it does not make sense to set i2c in the 'dac_config' parameter and not setting anything here. The parameter 'mode' allows to *or* the register with the value or to *and* it. Don't set 'mode' if you simply want to write. The 'val parameter can be an array [v1, v2,...] to write a serie of bytes in a single i2c burst (in that case 'mode' is ignored). **Note that all values must be decimal**. You can use a validator like [this](https://jsonlint.com) to verify your syntax
The 'power' command is used when powering on/off the DAC after the idle period (see -C option of squeezelite) and the 'speaker/headset' commands are sent when switching between speakers and headsets (see headset jack detection).
NB: For named configurations ((SqueezeAMP, Muse ... all except I2S), all this is ignored. For know codecs, the built-in sequences can be overwritten using dac_controlset NB: For named configurations ((SqueezeAMP, Muse ... all except I2S), all this is ignored. For know codecs, the built-in sequences can be overwritten using dac_controlset
**Please note that you can not use the same GPIO or port as the I2C.** **Please note that you can not use the same GPIO or port as the I2C.**
@@ -275,7 +277,7 @@ GPIO can be set to GND provide or Vcc at boot. This is convenient to power devic
The `<amp>` parameter can use used to assign a GPIO that will be set to active level (default 1) when playback starts. It will be reset when squeezelite becomes idle. The idle timeout is set on the squeezelite command line through `-C <timeout>` The `<amp>` parameter can use used to assign a GPIO that will be set to active level (default 1) when playback starts. It will be reset when squeezelite becomes idle. The idle timeout is set on the squeezelite command line through `-C <timeout>`
The `<power>` parameter can use used to assign a GPIO that will be set to active level (default 1) when player is powered on and reset when powered off The `<power>` parameter can use used to assign a GPIO that will be set to active level (default 1) when player is powered on and reset when powered off (in LMS, does not apply to AirPlay, Spotify or BT).
If you have an audio jack that supports insertion (use :0 or :1 to set the level when inserted), you can specify which GPIO it's connected to. Using the parameter jack_mutes_amp allows to mute the amp when headset (e.g.) is inserted. If you have an audio jack that supports insertion (use :0 or :1 to set the level when inserted), you can specify which GPIO it's connected to. Using the parameter jack_mutes_amp allows to mute the amp when headset (e.g.) is inserted.

View File

@@ -43,11 +43,15 @@ const __attribute__((section(".rodata_desc"))) esp_app_desc_t esp_app_desc = {
extern void register_audio_config(void); extern void register_audio_config(void);
extern void register_rotary_config(void); extern void register_rotary_config(void);
extern void register_ledvu_config(void); extern void register_ledvu_config(void);
extern void register_nvs();
void register_optional_cmd(void) { void register_optional_cmd(void) {
#if CONFIG_WITH_CONFIG_UI
register_rotary_config(); register_rotary_config();
register_ledvu_config(); #endif
register_audio_config(); register_audio_config();
register_ledvu_config();
register_nvs();
} }
extern int squeezelite_main(int argc, char **argv); extern int squeezelite_main(int argc, char **argv);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -73,24 +73,42 @@ static void register_set_services();
static void register_tasks(); static void register_tasks();
#endif #endif
extern BaseType_t network_manager_task; extern BaseType_t network_manager_task;
FILE * system_open_memstream(const char * cmdname,char **buf,size_t *buf_size){
FILE *f = open_memstream(buf, buf_size);
if (f == NULL) {
cmd_send_messaging(cmdname,MESSAGING_ERROR,"Unable to open memory stream.");
}
return f;
}
void register_system() void register_system()
{ {
register_free();
register_setdevicename();
register_set_services(); register_set_services();
register_free();
register_heap(); register_heap();
register_dump_heap(); register_dump_heap();
register_setdevicename();
register_version(); register_version();
register_restart(); register_restart();
register_deep_sleep();
register_light_sleep();
register_factory_boot(); register_factory_boot();
register_restart_ota(); register_restart_ota();
#if WITH_TASKS_INFO #if WITH_TASKS_INFO
register_tasks(); register_tasks();
#endif #endif
#if CONFIG_WITH_CONFIG_UI
register_deep_sleep();
register_light_sleep();
#endif
}
void simple_restart()
{
log_send_messaging(MESSAGING_WARNING,"Rebooting.");
if(!wait_for_commit()){
log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration. ");
}
vTaskDelay(750/ portTICK_PERIOD_MS);
esp_restart();
} }
/* 'version' command */ /* 'version' command */
static int get_version(int argc, char **argv) static int get_version(int argc, char **argv)
{ {
@@ -128,36 +146,23 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
{ {
if(is_recovery_running){ if(is_recovery_running){
if(partition_subtype ==ESP_PARTITION_SUBTYPE_APP_FACTORY){ if(partition_subtype ==ESP_PARTITION_SUBTYPE_APP_FACTORY){
log_send_messaging(MESSAGING_WARNING,"RECOVERY application is already active"); // log_send_messaging(MESSAGING_WARNING,"RECOVERY application is already active");
if(!wait_for_commit()){ simple_restart();
log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration. ");
}
vTaskDelay(750/ portTICK_PERIOD_MS);
esp_restart();
return ESP_OK;
} }
} }
else { else {
if(partition_subtype !=ESP_PARTITION_SUBTYPE_APP_FACTORY){ if(partition_subtype !=ESP_PARTITION_SUBTYPE_APP_FACTORY){
log_send_messaging(MESSAGING_WARNING,"SQUEEZELITE application is already active"); // log_send_messaging(MESSAGING_WARNING,"SQUEEZELITE application is already active");
if(!wait_for_commit()){ simple_restart();
log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration. ");
}
vTaskDelay(750/ portTICK_PERIOD_MS);
esp_restart();
return ESP_OK;
} }
} }
esp_err_t err = ESP_OK; esp_err_t err = ESP_OK;
bool bFound=false; // log_send_messaging(MESSAGING_INFO, "Looking for partition type %u",partition_subtype);
log_send_messaging(MESSAGING_INFO, "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, partition_subtype, NULL); esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, partition_subtype, NULL);
if(it == NULL){ if(it == NULL){
log_send_messaging(MESSAGING_ERROR,"Reboot failed. Cannot iterate through partitions"); log_send_messaging(MESSAGING_ERROR,"Reboot failed. Partitions error");
} }
else else
{ {
@@ -166,15 +171,11 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
ESP_LOGD(TAG, "Releasing partition iterator"); ESP_LOGD(TAG, "Releasing partition iterator");
esp_partition_iterator_release(it); esp_partition_iterator_release(it);
if(partition != NULL){ if(partition != NULL){
log_send_messaging(MESSAGING_INFO, "Found application partition %s sub type %u", partition->label,partition_subtype); log_send_messaging(MESSAGING_INFO, "Rebooting to %s", partition->label);
err=esp_ota_set_boot_partition(partition); err=esp_ota_set_boot_partition(partition);
if(err!=ESP_OK){ if(err!=ESP_OK){
bFound=false;
log_send_messaging(MESSAGING_ERROR,"Unable to select partition for reboot: %s",esp_err_to_name(err)); log_send_messaging(MESSAGING_ERROR,"Unable to select partition for reboot: %s",esp_err_to_name(err));
} }
else{
bFound=true;
}
} }
else else
{ {
@@ -183,13 +184,7 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
} }
ESP_LOGD(TAG, "Yielding to other processes"); ESP_LOGD(TAG, "Yielding to other processes");
taskYIELD(); taskYIELD();
if(bFound) { simple_restart();
if(!wait_for_commit()){
log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration changes. ");
}
vTaskDelay(750/ portTICK_PERIOD_MS);
esp_restart();
}
} }
return ESP_OK; return ESP_OK;
@@ -197,46 +192,31 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
static int restart(int argc, char **argv) static int restart(int argc, char **argv)
{ {
log_send_messaging(MESSAGING_WARNING, "\n\nPerforming a simple restart to the currently active partition."); simple_restart();
if(!wait_for_commit()){
cmd_send_messaging(argv[0],MESSAGING_WARNING,"Unable to commit configuration. ");
}
vTaskDelay(750/ portTICK_PERIOD_MS);
esp_restart();
return 0; return 0;
} }
void simple_restart()
{
log_send_messaging(MESSAGING_WARNING,"System reboot requested.");
if(!wait_for_commit()){
log_send_messaging(MESSAGING_WARNING,"Unable to commit configuration. ");
}
vTaskDelay(750/ portTICK_PERIOD_MS);
esp_restart();
}
esp_err_t guided_restart_ota(){ esp_err_t guided_restart_ota(){
log_send_messaging(MESSAGING_WARNING,"System reboot to Application requested"); log_send_messaging(MESSAGING_WARNING,"Booting to Squeezelite");
guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0); guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0);
return ESP_FAIL; // return fail. This should never return... we're rebooting! return ESP_FAIL; // return fail. This should never return... we're rebooting!
} }
esp_err_t guided_factory(){ esp_err_t guided_factory(){
log_send_messaging(MESSAGING_WARNING,"System reboot to recovery requested"); log_send_messaging(MESSAGING_WARNING,"Booting to recovery");
guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY); guided_boot(ESP_PARTITION_SUBTYPE_APP_FACTORY);
return ESP_FAIL; // return fail. This should never return... we're rebooting! 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)
{ {
cmd_send_messaging(argv[0],MESSAGING_WARNING, "Executing guided boot into recovery"); cmd_send_messaging(argv[0],MESSAGING_WARNING, "Booting to Recovery");
guided_boot(ESP_PARTITION_SUBTYPE_APP_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 int restart_ota(int argc, char **argv) static int restart_ota(int argc, char **argv)
{ {
cmd_send_messaging(argv[0],MESSAGING_WARNING, "Executing guided boot into ota app 0"); cmd_send_messaging(argv[0],MESSAGING_WARNING, "Booting to Squeezelite");
guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0); guided_boot(ESP_PARTITION_SUBTYPE_APP_OTA_0);
return 0; // return fail. This should never return... we're rebooting! return 0; // return fail. This should never return... we're rebooting!
} }
@@ -248,7 +228,9 @@ static void register_restart()
.hint = NULL, .hint = NULL,
.func = &restart, .func = &restart,
}; };
#if CONFIG_WITH_CONFIG_UI
cmd_to_json(&cmd); cmd_to_json(&cmd);
#endif
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
} }
static void register_restart_ota() static void register_restart_ota()
@@ -259,7 +241,9 @@ static void register_restart_ota()
.hint = NULL, .hint = NULL,
.func = &restart_ota, .func = &restart_ota,
}; };
#if CONFIG_WITH_CONFIG_UI
cmd_to_json(&cmd); cmd_to_json(&cmd);
#endif
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
} }
@@ -271,7 +255,9 @@ static void register_factory_boot()
.hint = NULL, .hint = NULL,
.func = &restart_factory, .func = &restart_factory,
}; };
#if CONFIG_WITH_CONFIG_UI
cmd_to_json(&cmd); cmd_to_json(&cmd);
#endif
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
} }
/** 'free' command prints available heap memory */ /** 'free' command prints available heap memory */
@@ -287,11 +273,14 @@ static void register_free()
{ {
const esp_console_cmd_t cmd = { const esp_console_cmd_t cmd = {
.command = "free", .command = "free",
.help = "Get the current size of free heap memory", .help = "Get free heap memory",
.hint = NULL, .hint = NULL,
.func = &free_mem, .func = &free_mem,
}; };
#if CONFIG_WITH_CONFIG_UI
cmd_to_json(&cmd); cmd_to_json(&cmd);
#endif
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) ); ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
} }
static int dump_heap(int argc, char **argv) static int dump_heap(int argc, char **argv)
@@ -303,16 +292,16 @@ static int dump_heap(int argc, char **argv)
/* 'heap' command prints minumum heap size */ /* 'heap' command prints minumum heap size */
static int heap_size(int argc, char **argv) static int heap_size(int argc, char **argv)
{ {
ESP_LOGI(TAG,"Heap internal:%zu (min:%zu) (largest block:%zu)\nexternal:%zu (min:%zu) (largest block:%zd)\ndma :%zu (min:%zu) (largest block:%zd)", // ESP_LOGI(TAG,"Heap internal:%zu (min:%zu) (largest block:%zu)\nexternal:%zu (min:%zu) (largest block:%zd)\ndma :%zu (min:%zu) (largest block:%zd)",
heap_caps_get_free_size(MALLOC_CAP_INTERNAL), // heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), // heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL),
heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL), // heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL),
heap_caps_get_free_size(MALLOC_CAP_SPIRAM), // heap_caps_get_free_size(MALLOC_CAP_SPIRAM),
heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM), // heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM),
heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM), // heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM),
heap_caps_get_free_size(MALLOC_CAP_DMA), // heap_caps_get_free_size(MALLOC_CAP_DMA),
heap_caps_get_minimum_free_size(MALLOC_CAP_DMA), // heap_caps_get_minimum_free_size(MALLOC_CAP_DMA),
heap_caps_get_largest_free_block(MALLOC_CAP_DMA)); // heap_caps_get_largest_free_block(MALLOC_CAP_DMA));
cmd_send_messaging(argv[0],MESSAGING_INFO,"Heap internal:%zu (min:%zu) (largest block:%zu)\nexternal:%zu (min:%zu) (largest block:%zd)\ndma :%zu (min:%zu) (largest block:%zd)", cmd_send_messaging(argv[0],MESSAGING_INFO,"Heap internal:%zu (min:%zu) (largest block:%zu)\nexternal:%zu (min:%zu) (largest block:%zd)\ndma :%zu (min:%zu) (largest block:%zd)",
heap_caps_get_free_size(MALLOC_CAP_INTERNAL), heap_caps_get_free_size(MALLOC_CAP_INTERNAL),
heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL), heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL),
@@ -457,9 +446,8 @@ static int setdevicename(int argc, char **argv)
char *buf = NULL; char *buf = NULL;
size_t buf_size = 0; size_t buf_size = 0;
FILE *f = open_memstream(&buf, &buf_size); FILE *f = system_open_memstream(argv[0],&buf, &buf_size);
if (f == NULL) { if (f == NULL) {
cmd_send_messaging(argv[0],MESSAGING_ERROR,"Unable to open memory stream.");
return 1; return 1;
} }
nerrors+=setnamevar("a2dp_dev_name", f, name); nerrors+=setnamevar("a2dp_dev_name", f, name);
@@ -488,11 +476,13 @@ static void register_heap()
{ {
const esp_console_cmd_t heap_cmd = { const esp_console_cmd_t heap_cmd = {
.command = "heap", .command = "heap",
.help = "Get minimum size of free heap memory found during execution", .help = "Get minimum size of free heap memory",
.hint = NULL, .hint = NULL,
.func = &heap_size, .func = &heap_size,
}; };
#if CONFIG_WITH_CONFIG_UI
cmd_to_json(&heap_cmd); cmd_to_json(&heap_cmd);
#endif
ESP_ERROR_CHECK( esp_console_cmd_register(&heap_cmd) ); ESP_ERROR_CHECK( esp_console_cmd_register(&heap_cmd) );
} }
@@ -521,6 +511,7 @@ static void register_setdevicename()
.func = &setdevicename, .func = &setdevicename,
.argtable = &name_args .argtable = &name_args
}; };
cmd_to_json_with_cb(&set_name,&setdevicename_cb); cmd_to_json_with_cb(&set_name,&setdevicename_cb);
ESP_ERROR_CHECK(esp_console_cmd_register(&set_name)); ESP_ERROR_CHECK(esp_console_cmd_register(&set_name));
} }
@@ -618,9 +609,7 @@ static void register_deep_sleep()
const esp_console_cmd_t cmd = { const esp_console_cmd_t cmd = {
.command = "deep_sleep", .command = "deep_sleep",
.help = "Enter deep sleep mode. " .help = "Enter deep sleep mode. ",
"Two wakeup modes are supported: timer and GPIO. "
"If no wakeup option is specified, will sleep indefinitely.",
.hint = NULL, .hint = NULL,
.func = &deep_sleep, .func = &deep_sleep,
.argtable = &deep_sleep_args .argtable = &deep_sleep_args
@@ -649,9 +638,8 @@ static int do_set_services(int argc, char **argv)
} }
char *buf = NULL; char *buf = NULL;
size_t buf_size = 0; size_t buf_size = 0;
FILE *f = open_memstream(&buf, &buf_size); FILE *f = system_open_memstream(argv[0],&buf, &buf_size);
if (f == NULL) { if (f == NULL) {
cmd_send_messaging(argv[0],MESSAGING_ERROR,"Unable to open memory stream.");
return 1; return 1;
} }
@@ -674,7 +662,7 @@ static int do_set_services(int argc, char **argv)
if(err!=ESP_OK){ if(err!=ESP_OK){
nerrors++; nerrors++;
fprintf(f,"Error setting telnet service to %s. %s\n",set_services_args.telnet->sval[0], esp_err_to_name(err)); fprintf(f,"Error setting telnet to %s. %s\n",set_services_args.telnet->sval[0], esp_err_to_name(err));
} }
else { else {
fprintf(f,"Telnet service changed to %s\n",set_services_args.telnet->sval[0]); fprintf(f,"Telnet service changed to %s\n",set_services_args.telnet->sval[0]);
@@ -706,7 +694,6 @@ cJSON * set_services_cb(){
#if WITH_TASKS_INFO #if WITH_TASKS_INFO
console_set_bool_parameter(values,"stats",set_services_args.stats); console_set_bool_parameter(values,"stats",set_services_args.stats);
#endif #endif
if ((p = config_alloc_get(NVS_TYPE_STR, "telnet_enable")) != NULL) { if ((p = config_alloc_get(NVS_TYPE_STR, "telnet_enable")) != NULL) {
if(strcasestr("YX",p)!=NULL){ if(strcasestr("YX",p)!=NULL){
cJSON_AddStringToObject(values,set_services_args.telnet->hdr.longopts,"Telnet Only"); cJSON_AddStringToObject(values,set_services_args.telnet->hdr.longopts,"Telnet Only");
@@ -717,7 +704,6 @@ cJSON * set_services_cb(){
else { else {
cJSON_AddStringToObject(values,set_services_args.telnet->hdr.longopts,"Disabled"); cJSON_AddStringToObject(values,set_services_args.telnet->hdr.longopts,"Disabled");
} }
FREE_AND_NULL(p); FREE_AND_NULL(p);
} }

View File

@@ -17,6 +17,7 @@ void register_system();
esp_err_t guided_factory(); esp_err_t guided_factory();
esp_err_t guided_restart_ota(); esp_err_t guided_restart_ota();
void simple_restart(); void simple_restart();
FILE * system_open_memstream(const char * cmdname,char **buf,size_t *buf_size);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -204,8 +204,10 @@ void register_wifi_join()
void register_wifi() void register_wifi()
{ {
#ifdef WIFI_CMDLINE
register_wifi_join(); register_wifi_join();
if(bypass_network_manager){ if(bypass_network_manager){
initialise_wifi(); initialise_wifi();
} }
#endif
} }

View File

@@ -13,7 +13,7 @@
#include "driver/i2s.h" #include "driver/i2s.h"
#include "driver/spi_master.h" #include "driver/spi_master.h"
#include "gpio_exp.h" #include "gpio_exp.h"
#include "cJSON.h"
extern const char *i2c_name_type; extern const char *i2c_name_type;
extern const char *spi_name_type; extern const char *spi_name_type;

View File

@@ -53,6 +53,7 @@ private:
std::atomic<states> state; std::atomic<states> state;
std::string credentials; std::string credentials;
bool zeroConf; bool zeroConf;
std::atomic<bool> flushed = false, notify = true;
int startOffset, volume = 0, bitrate = 160; int startOffset, volume = 0, bitrate = 160;
httpd_handle_t serverHandle; httpd_handle_t serverHandle;
@@ -60,6 +61,7 @@ private:
cspot_cmd_cb_t cmdHandler; cspot_cmd_cb_t cmdHandler;
cspot_data_cb_t dataHandler; cspot_data_cb_t dataHandler;
std::string lastTrackId; std::string lastTrackId;
cspot::TrackInfo trackInfo;
std::shared_ptr<cspot::LoginBlob> blob; std::shared_ptr<cspot::LoginBlob> blob;
std::unique_ptr<cspot::SpircHandler> spirc; std::unique_ptr<cspot::SpircHandler> spirc;
@@ -206,11 +208,13 @@ void cspotPlayer::eventHandler(std::unique_ptr<cspot::SpircHandler::Event> event
trackStatus = TRACK_INIT; trackStatus = TRACK_INIT;
// memorize position for when track's beginning will be detected // memorize position for when track's beginning will be detected
startOffset = std::get<int>(event->data); startOffset = std::get<int>(event->data);
notify = !flushed;
flushed = false;
// Spotify servers do not send volume at connection // Spotify servers do not send volume at connection
spirc->setRemoteVolume(volume); spirc->setRemoteVolume(volume);
cmdHandler(CSPOT_START, 44100); cmdHandler(CSPOT_START, 44100);
CSPOT_LOG(info, "(re)start playing"); CSPOT_LOG(info, "(re)start playing at %d", startOffset);
break; break;
} }
case cspot::SpircHandler::EventType::PLAY_PAUSE: { case cspot::SpircHandler::EventType::PLAY_PAUSE: {
@@ -219,16 +223,14 @@ void cspotPlayer::eventHandler(std::unique_ptr<cspot::SpircHandler::Event> event
break; break;
} }
case cspot::SpircHandler::EventType::TRACK_INFO: { case cspot::SpircHandler::EventType::TRACK_INFO: {
auto trackInfo = std::get<cspot::TrackInfo>(event->data); trackInfo = std::get<cspot::TrackInfo>(event->data);
cmdHandler(CSPOT_TRACK_INFO, trackInfo.duration, startOffset, trackInfo.artist.c_str(),
trackInfo.album.c_str(), trackInfo.name.c_str(), trackInfo.imageUrl.c_str());
spirc->updatePositionMs(startOffset);
startOffset = 0;
break; break;
} }
case cspot::SpircHandler::EventType::FLUSH:
flushed = true;
__attribute__ ((fallthrough));
case cspot::SpircHandler::EventType::NEXT: case cspot::SpircHandler::EventType::NEXT:
case cspot::SpircHandler::EventType::PREV: case cspot::SpircHandler::EventType::PREV: {
case cspot::SpircHandler::EventType::FLUSH: {
cmdHandler(CSPOT_FLUSH); cmdHandler(CSPOT_FLUSH);
break; break;
} }
@@ -411,8 +413,13 @@ void cspotPlayer::runTask() {
uint32_t started; uint32_t started;
cmdHandler(CSPOT_QUERY_STARTED, &started); cmdHandler(CSPOT_QUERY_STARTED, &started);
if (started) { if (started) {
CSPOT_LOG(info, "next track's audio has reached DAC"); CSPOT_LOG(info, "next track's audio has reached DAC (offset %d)", startOffset);
spirc->notifyAudioReachedPlayback(); if (notify) spirc->notifyAudioReachedPlayback();
else notify = true;
cmdHandler(CSPOT_TRACK_INFO, trackInfo.duration, startOffset, trackInfo.artist.c_str(),
trackInfo.album.c_str(), trackInfo.name.c_str(), trackInfo.imageUrl.c_str());
spirc->updatePositionMs(startOffset);
startOffset = 0;
trackStatus = TRACK_STREAM; trackStatus = TRACK_STREAM;
} }
} else if (trackStatus == TRACK_END) { } else if (trackStatus == TRACK_END) {

View File

@@ -204,8 +204,13 @@ void SpircHandler::handleFrame(std::vector<uint8_t>& data) {
CSPOT_LOG(debug, "Got replace frame"); CSPOT_LOG(debug, "Got replace frame");
playbackState->syncWithRemote(); playbackState->syncWithRemote();
trackQueue->updateTracks(playbackState->remoteFrame.state.position_ms, // 1st track is the current one, but update the position
false); trackQueue->updateTracks(
playbackState->remoteFrame.state.position_ms +
ctx->timeProvider->getSyncedTimestamp() -
playbackState->innerFrame.state.position_measured_at,
false);
this->notify(); this->notify();
sendEvent(EventType::FLUSH); sendEvent(EventType::FLUSH);

View File

@@ -186,7 +186,7 @@ static int read_opus_header(void) {
switch (u->status) { switch (u->status) {
case OGG_SYNC: case OGG_SYNC:
u->status = OGG_ID_HEADER; u->status = OGG_ID_HEADER;
OG(&gu, stream_init, &u->state, OG(&gu, page_serialno, &u->page)); OG(&gu, stream_reset_serialno, &u->state, OG(&gu, page_serialno, &u->page));
fetch = false; fetch = false;
break; break;
case OGG_ID_HEADER: case OGG_ID_HEADER:
@@ -359,10 +359,10 @@ static void opus_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
u->status = OGG_SYNC; u->status = OGG_SYNC;
u->overframes = 0; u->overframes = 0;
OG(&gu, sync_clear, &u->sync); OG(&go, stream_clear, &u->state);
OG(&gu, stream_clear, &u->state); OG(&go, sync_clear, &u->sync);
OG(&gu, stream_init, &u->state, -1); OG(&go, stream_init, &u->state, -1);
} }
static void opus_close(void) { static void opus_close(void) {
@@ -372,8 +372,8 @@ static void opus_close(void) {
free(u->overbuf); free(u->overbuf);
u->overbuf = NULL; u->overbuf = NULL;
OG(&gu, stream_clear, &u->state); OG(&go, stream_clear, &u->state);
OG(&gu, sync_clear, &u->sync); OG(&go, sync_clear, &u->sync);
} }
static bool load_opus(void) { static bool load_opus(void) {
@@ -394,7 +394,7 @@ static bool load_opus(void) {
} }
g_handle->ogg_stream_clear = dlsym(g_handle->handle, "ogg_stream_clear"); g_handle->ogg_stream_clear = dlsym(g_handle->handle, "ogg_stream_clear");
g_handle->.ogg_stream_reset = dlsym(g_handle->handle, "ogg_stream_reset"); g_handle->ogg_stream_reset = dlsym(g_handle->handle, "ogg_stream_reset");
g_handle->ogg_stream_eos = dlsym(g_handle->handle, "ogg_stream_eos"); g_handle->ogg_stream_eos = dlsym(g_handle->handle, "ogg_stream_eos");
g_handle->ogg_stream_reset_serialno = dlsym(g_handle->handle, "ogg_stream_reset_serialno"); g_handle->ogg_stream_reset_serialno = dlsym(g_handle->handle, "ogg_stream_reset_serialno");
g_handle->ogg_sync_clear = dlsym(g_handle->handle, "ogg_sync_clear"); g_handle->ogg_sync_clear = dlsym(g_handle->handle, "ogg_sync_clear");

View File

@@ -744,7 +744,7 @@ static void IRAM_ATTR spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst) {
// we assume frame == 0 as well... // we assume frame == 0 as well...
if (!src) { if (!src) {
count = 192; count = 0;
vu = VUCP24[0]; vu = VUCP24[0];
} }
@@ -757,7 +757,7 @@ static void IRAM_ATTR spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst) {
if (!count--) { if (!count--) {
*dst++ = (vu << 24) | (PREAMBLE_B << 16) | 0xCCCC; *dst++ = (vu << 24) | (PREAMBLE_B << 16) | 0xCCCC;
count = 192; count = 191;
} else { } else {
*dst++ = (vu << 24) | (PREAMBLE_M << 16) | 0xCCCC; *dst++ = (vu << 24) | (PREAMBLE_M << 16) | 0xCCCC;
} }
@@ -771,7 +771,7 @@ static void IRAM_ATTR spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst) {
if (!count--) { if (!count--) {
*dst++ = (vu << 24) | (PREAMBLE_B << 16) | aux; *dst++ = (vu << 24) | (PREAMBLE_B << 16) | aux;
count = 192; count = 191;
} else { } else {
*dst++ = (vu << 24) | (PREAMBLE_M << 16) | aux; *dst++ = (vu << 24) | (PREAMBLE_M << 16) | aux;
} }

View File

@@ -72,6 +72,13 @@ static struct vorbis {
// vorbis symbols to be dynamically loaded - from either vorbisfile or vorbisidec (tremor) version of library // vorbis symbols to be dynamically loaded - from either vorbisfile or vorbisidec (tremor) version of library
vorbis_info *(* ov_info)(OggVorbis_File *vf, int link); vorbis_info *(* ov_info)(OggVorbis_File *vf, int link);
int (* ov_clear)(OggVorbis_File *vf); int (* ov_clear)(OggVorbis_File *vf);
void (* ov_info_init)(vorbis_info* vi);
void (* ov_info_clear)(vorbis_info* vi);
void (* ov_comment_init)(vorbis_comment* vc);
void (* ov_comment_clear(vorbis_comment *vc);
int (* ov_block_init)(vorbis_dsp_state* v, vorbis_block* vb);
int (* ov_block_clear)(vorbis_block* vb);
void (* ov_vorbis_dsp_clear)(vorbis_dsp_state* v);
long (* ov_read)(OggVorbis_File *vf, char *buffer, int length, int bigendianp, int word, int sgned, int *bitstream); long (* ov_read)(OggVorbis_File *vf, char *buffer, int length, int bigendianp, int word, int sgned, int *bitstream);
long (* ov_read_tremor)(OggVorbis_File *vf, char *buffer, int length, int *bitstream); long (* ov_read_tremor)(OggVorbis_File *vf, char *buffer, int length, int *bitstream);
int (* ov_open_callbacks)(void *datasource, OggVorbis_File *vf, const char *initial, long ibytes, ov_callbacks callbacks); int (* ov_open_callbacks)(void *datasource, OggVorbis_File *vf, const char *initial, long ibytes, ov_callbacks callbacks);
@@ -396,33 +403,32 @@ static decode_state vorbis_decode(void) {
} }
static void vorbis_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) { static void vorbis_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
LOG_INFO("OPENING CODEC");
if (v->opened) { if (v->opened) {
OV(&go, block_clear, &v->block); OV(&gv, block_clear, &v->block);
OV(&go, info_clear, &v->info); OV(&gv, dsp_clear, &v->decoder);
OV(&go, dsp_clear, &v->decoder); OV(&gv, info_clear, &v->info);
} }
v->opened = false; v->opened = false;
v->status = OGG_SYNC; v->status = OGG_SYNC;
v->overflow = 0; v->overflow = 0;
OG(&gu, sync_clear, &v->sync); OG(&go, stream_clear, &v->state);
OG(&gu, stream_clear, &v->state); OG(&go, sync_clear, &v->sync);
OG(&gu, stream_init, &v->state, -1); OG(&go, stream_init, &v->state, -1);
} }
static void vorbis_close() { static void vorbis_close() {
return;
LOG_INFO("CLOSING CODEC");
if (v->opened) { if (v->opened) {
OV(&go, block_clear, &v->block); OV(&gv, block_clear, &v->block);
OV(&go, info_clear, &v->info); OV(&gv, dsp_clear, &v->decoder);
OV(&go, dsp_clear, &v->decoder); // info must be last otherwise there is memory leak (where is it said... nowhere)
OV(&gv, info_clear, &v->info);
// we don' t have comments to free
} }
v->opened = false; v->opened = false;
OG(&go, stream_clear, &v->state); OG(&go, stream_clear, &v->state);
OG(&go, sync_clear, &v->sync); OG(&go, sync_clear, &v->sync);
} }
@@ -469,6 +475,11 @@ static bool load_vorbis() {
v_handle.ov_read = dlsym(handle, "ov_read"); v_handle.ov_read = dlsym(handle, "ov_read");
v_handle.ov_info = dlsym(handle, "ov_info"); v_handle.ov_info = dlsym(handle, "ov_info");
v_handle.ov_clear = dlsym(handle, "ov_clear"); v_handle.ov_clear = dlsym(handle, "ov_clear");
v.handle.ov_info_clear = dlsym(gv.handle, "vorbis_info_clear");
v.handle.ov_comment_init = dlsym(gv.handle, "vorbis_comment_init");
v.handle.ov_comment_clear = dlsym(gv.handle, "vorbis_comment_clear");
v.handle.ov_block_init = dlsym(gv.handle, "vorbis_block_init");
v.handle.ov_block_clear = dlsym(gv.handle, "vorbis_block_clear");
v_handle.ov_open_callbacks = dlsym(handle, "ov_open_callbacks"); v_handle.ov_open_callbacks = dlsym(handle, "ov_open_callbacks");
if ((err = dlerror()) != NULL) { if ((err = dlerror()) != NULL) {

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -64,6 +64,10 @@ declare function getStatus(): {};
declare function getStatus(): {}; declare function getStatus(): {};
declare function getStatus(): {}; declare function getStatus(): {};
declare function getStatus(): {}; declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string; declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string; declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string; declare function getRadioButton(entry: any): string;
@@ -196,6 +200,8 @@ declare function pushStatus(): void;
declare function pushStatus(): void; declare function pushStatus(): void;
declare function pushStatus(): void; declare function pushStatus(): void;
declare function pushStatus(): void; declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare let sd: {}; declare let sd: {};
declare let rf: boolean; declare let rf: boolean;
declare function refreshStatus(): void; declare function refreshStatus(): void;

View File

@@ -22,7 +22,6 @@
"babel": "^6.23.0", "babel": "^6.23.0",
"babel-loader": "^8.2.3", "babel-loader": "^8.2.3",
"babel-runtime": "^6.26.0", "babel-runtime": "^6.26.0",
"bootswatch": "file:src/bootswatch",
"clean-webpack-plugin": "^4.0.0", "clean-webpack-plugin": "^4.0.0",
"commander": "^8.3.0", "commander": "^8.3.0",
"compression-webpack-plugin": "^9.2.0", "compression-webpack-plugin": "^9.2.0",
@@ -75,8 +74,10 @@
"@babel/runtime": "^7.16.7", "@babel/runtime": "^7.16.7",
"async-mutex": "^0.3.2", "async-mutex": "^0.3.2",
"bootstrap": "^5.1.3", "bootstrap": "^5.1.3",
"bootswatch": "^5.3.2",
"jquery": "^3.6.0", "jquery": "^3.6.0",
"npm": "^10.1.0", "npm": "^10.1.0",
"optipng-bin": "^9.0.0",
"popper.js": "^1.16.1", "popper.js": "^1.16.1",
"webpack-visualizer-plugin": "^0.1.11", "webpack-visualizer-plugin": "^0.1.11",
"webpack-visualizer-plugin2": "^1.0.0" "webpack-visualizer-plugin2": "^1.0.0"

View File

@@ -99,7 +99,7 @@
<div class="tab-pane fade" id="tab-cfg-gen"></div> <div class="tab-pane fade" id="tab-cfg-gen"></div>
<div class="tab-pane fade" id="tab-cfg-fw"> <div class="tab-pane fade" id="tab-cfg-fw">
<div class="card text-white mb-3"> <div class="card mb-3">
<div class="card-header">Software Updates</div> <div class="card-header">Software Updates</div>
<div class="card-body"> <div class="card-body">
<table class="table table-hover table-striped table-dark"> <table class="table table-hover table-striped table-dark">
@@ -171,7 +171,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card text-white mb-3"> <div class="card mb-3">
<div class="card-header">Local Firmware Upload</div> <div class="card-header">Local Firmware Upload</div>
<div class="card-body"> <div class="card-body">
<div id="uploaddiv" class="form-group row "> <div id="uploaddiv" class="form-group row ">
@@ -216,7 +216,7 @@
</div> </div>
<div class="tab-pane fade" id="tab-cfg-audio"> <div class="tab-pane fade" id="tab-cfg-audio">
<div class="card text-white mb-3"> <div class="card mb-3">
<div class="card-header">Usage Templates</div> <div class="card-header">Usage Templates</div>
<div class="card-body"> <div class="card-body">
<fieldset class="form-group" id="output-tmpl"> <fieldset class="form-group" id="output-tmpl">
@@ -331,8 +331,7 @@
<div class="form-check"> <div class="form-check">
<label class="form-check-label"> <label class="form-check-label">
<input class="form-check-input" type="checkbox" id="disable-squeezelite" <input class="form-check-input" type="checkbox" id="disable-squeezelite" value="" >
value="" checked="">
Disable Squeezelite Disable Squeezelite
</label> </label>
</div> </div>
@@ -356,7 +355,7 @@
</div> </div>
</div> </div>
<div class="tab-pane fade active show" id="tab-wifi"> <div class="tab-pane fade active show" id="tab-wifi">
<div class="card text-white mb-3"> <div class="card mb-3">
<div class="card-header">WiFi Status</div> <div class="card-header">WiFi Status</div>
<div class="card-body if_eth" style="display: none"> <div class="card-body if_eth" style="display: none">
@@ -528,7 +527,7 @@
</div> </div>
<!-- syslog --> <!-- syslog -->
<div class="tab-pane fade " id="tab-credits"> <div class="tab-pane fade " id="tab-credits">
<div class="card text-white mb-3"> <div class="card mb-3">
<div class="card-header">Credits</div> <div class="card-header">Credits</div>
<div class="card-body"> <div class="card-body">
<p><strong><a <p><strong><a
@@ -555,7 +554,7 @@
</ul> </ul>
</div> </div>
</div> </div>
<div class="card text-white mb-3"> <div class="card mb-3">
<div class="card-header">Extras/Overrides</div> <div class="card-header">Extras/Overrides</div>
<div class="card-body"> <div class="card-body">
<fieldset> <fieldset>

View File

@@ -923,10 +923,10 @@ window.saveAutoexec1 = function (apply) {
}; };
data.config = { data.config = {
autoexec1: { value: commandLine, type: 33 }, autoexec1: { value: commandLine, type: 33 },
autoexec: { // autoexec: {
value: $('#disable-squeezelite').prop('checked') ? '0' : '1', // value: $('#disable-squeezelite').prop('checked') ? '0' : '1',
type: 33, // type: 33,
}, // },
}; };
$.ajax({ $.ajax({
@@ -1216,6 +1216,28 @@ $(document).ready(function () {
} }
}); });
$('#disable-squeezelite').on('click', function () {
// this.checked = this.checked ? 1 : 0;
// $('#disable-squeezelite').prop('checked')
if (this.checked) {
// Store the current value before overwriting it
const currentValue = $('#cmd_opt_s').val();
$('#cmd_opt_s').data('originalValue', currentValue);
// Overwrite the value with '-disable'
$('#cmd_opt_s').val('-disable');
} else {
// Retrieve the original value
const originalValue = $('#cmd_opt_s').data('originalValue');
// Restore the original value if it exists, otherwise set it to an empty string
$('#cmd_opt_s').val(originalValue ? originalValue : '');
}
});
$('input#show-nvs').on('click', function () { $('input#show-nvs').on('click', function () {
this.checked = this.checked ? 1 : 0; this.checked = this.checked ? 1 : 0;
Cookies.set("show-nvs", this.checked ? 'Y' : 'N'); Cookies.set("show-nvs", this.checked ? 'Y' : 'N');
@@ -2075,7 +2097,7 @@ function getCommands() {
const isConfig = cmdParts[0] === 'cfg'; const isConfig = cmdParts[0] === 'cfg';
const targetDiv = '#tab-' + cmdParts[0] + '-' + cmdParts[1]; const targetDiv = '#tab-' + cmdParts[0] + '-' + cmdParts[1];
let innerhtml = ''; let innerhtml = '';
innerhtml += `<div class="card text-white mb-3"><div class="card-header">${command.help.encodeHTML().replace(/\n/g, '<br />')}</div><div class="card-body"><fieldset id="flds-${command.name}">`; innerhtml += `<div class="card mb-3"><div class="card-header">${command.help.encodeHTML().replace(/\n/g, '<br />')}</div><div class="card-body"><fieldset id="flds-${command.name}">`;
if (command.argtable) { if (command.argtable) {
command.argtable.forEach(function (arg) { command.argtable.forEach(function (arg) {
let placeholder = arg.datatype || ''; let placeholder = arg.datatype || '';
@@ -2199,13 +2221,7 @@ function getConfig() {
.sort() .sort()
.forEach(function (key) { .forEach(function (key) {
let val = data[key].value; let val = data[key].value;
if (key === 'autoexec') { if (key === 'autoexec1') {
if (data.autoexec.value === '0') {
$('#disable-squeezelite')[0].checked = true;
} else {
$('#disable-squeezelite')[0].checked = false;
}
} else if (key === 'autoexec1') {
/* call new function to parse the squeezelite options */ /* call new function to parse the squeezelite options */
processSqueezeliteCommandLine(val); processSqueezeliteCommandLine(val);
} else if (key === 'host_name') { } else if (key === 'host_name') {
@@ -2294,6 +2310,7 @@ function processSqueezeliteCommandLine(val) {
commandBTSinkName= parsed.otherOptions.btname; commandBTSinkName= parsed.otherOptions.btname;
} }
handleTemplateTypeRadio('bt'); handleTemplateTypeRadio('bt');
} }
Object.keys(parsed.options).forEach(function (key) { Object.keys(parsed.options).forEach(function (key) {
const option = parsed.options[key]; const option = parsed.options[key];
@@ -2312,6 +2329,17 @@ function processSqueezeliteCommandLine(val) {
$('#resample_i').prop('checked', true); $('#resample_i').prop('checked', true);
} }
} }
if (parsed.options.hasOwnProperty('s')) {
// parse -u v[:i] and check the appropriate radio button with id #resample_v
if(parsed.options.s === '-disable'){
$('#disable-squeezelite')[0].checked = true;
}
else {
$('#disable-squeezelite')[0].checked = false;
}
}
} }

View File

@@ -1,5 +1,5 @@
@import "~bootswatch/dist/darkly/variables"; // @import "~bootswatch/dist/darkly/variables"; -- remove darkly until bootswatch color is resolved
@import "utils/variables"; @import "utils/variables";
@import "~bootstrap/scss/bootstrap"; @import "~bootstrap/scss/bootstrap";
// @import "~bootstrap/scss/functions"; // @import "~bootstrap/scss/functions";
@@ -38,5 +38,5 @@
// // Utilities // // Utilities
// @import "~bootstrap/scss/utilities/api"; // @import "~bootstrap/scss/utilities/api";
@import "~bootswatch/dist/darkly/bootswatch"; // @import "~bootswatch/dist/darkly/bootswatch"; -- remove darkly until bootswatch color is resolved
@import "utils/style"; @import "utils/style";

View File

@@ -1,5 +1,5 @@
target_add_binary_data( __idf_wifi-manager webapp/dist/css/index.1ab179394339385e0a02.css.gz BINARY) target_add_binary_data( __idf_wifi-manager webapp/dist/css/index.1ab179394339385e0a02.css.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/favicon-32x32.png BINARY) target_add_binary_data( __idf_wifi-manager webapp/dist/favicon-32x32.png BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/index.html.gz BINARY) target_add_binary_data( __idf_wifi-manager webapp/dist/index.html.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/index.b02584.bundle.js.gz BINARY) target_add_binary_data( __idf_wifi-manager webapp/dist/js/index.e0b953.bundle.js.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/node_vendors.b02584.bundle.js.gz BINARY) target_add_binary_data( __idf_wifi-manager webapp/dist/js/node_vendors.e0b953.bundle.js.gz BINARY)

View File

@@ -6,29 +6,29 @@ extern const uint8_t _favicon_32x32_png_start[] asm("_binary_favicon_32x32_png_s
extern const uint8_t _favicon_32x32_png_end[] asm("_binary_favicon_32x32_png_end"); extern const uint8_t _favicon_32x32_png_end[] asm("_binary_favicon_32x32_png_end");
extern const uint8_t _index_html_gz_start[] asm("_binary_index_html_gz_start"); extern const uint8_t _index_html_gz_start[] asm("_binary_index_html_gz_start");
extern const uint8_t _index_html_gz_end[] asm("_binary_index_html_gz_end"); extern const uint8_t _index_html_gz_end[] asm("_binary_index_html_gz_end");
extern const uint8_t _index_b02584_bundle_js_gz_start[] asm("_binary_index_b02584_bundle_js_gz_start"); extern const uint8_t _index_e0b953_bundle_js_gz_start[] asm("_binary_index_e0b953_bundle_js_gz_start");
extern const uint8_t _index_b02584_bundle_js_gz_end[] asm("_binary_index_b02584_bundle_js_gz_end"); extern const uint8_t _index_e0b953_bundle_js_gz_end[] asm("_binary_index_e0b953_bundle_js_gz_end");
extern const uint8_t _node_vendors_b02584_bundle_js_gz_start[] asm("_binary_node_vendors_b02584_bundle_js_gz_start"); extern const uint8_t _node_vendors_e0b953_bundle_js_gz_start[] asm("_binary_node_vendors_e0b953_bundle_js_gz_start");
extern const uint8_t _node_vendors_b02584_bundle_js_gz_end[] asm("_binary_node_vendors_b02584_bundle_js_gz_end"); extern const uint8_t _node_vendors_e0b953_bundle_js_gz_end[] asm("_binary_node_vendors_e0b953_bundle_js_gz_end");
const char * resource_lookups[] = { const char * resource_lookups[] = {
"/css/index.1ab179394339385e0a02.css.gz", "/css/index.1ab179394339385e0a02.css.gz",
"/favicon-32x32.png", "/favicon-32x32.png",
"/index.html.gz", "/index.html.gz",
"/js/index.b02584.bundle.js.gz", "/js/index.e0b953.bundle.js.gz",
"/js/node_vendors.b02584.bundle.js.gz", "/js/node_vendors.e0b953.bundle.js.gz",
"" ""
}; };
const uint8_t * resource_map_start[] = { const uint8_t * resource_map_start[] = {
_index_1ab179394339385e0a02_css_gz_start, _index_1ab179394339385e0a02_css_gz_start,
_favicon_32x32_png_start, _favicon_32x32_png_start,
_index_html_gz_start, _index_html_gz_start,
_index_b02584_bundle_js_gz_start, _index_e0b953_bundle_js_gz_start,
_node_vendors_b02584_bundle_js_gz_start _node_vendors_e0b953_bundle_js_gz_start
}; };
const uint8_t * resource_map_end[] = { const uint8_t * resource_map_end[] = {
_index_1ab179394339385e0a02_css_gz_end, _index_1ab179394339385e0a02_css_gz_end,
_favicon_32x32_png_end, _favicon_32x32_png_end,
_index_html_gz_end, _index_html_gz_end,
_index_b02584_bundle_js_gz_end, _index_e0b953_bundle_js_gz_end,
_node_vendors_b02584_bundle_js_gz_end _node_vendors_e0b953_bundle_js_gz_end
}; };

View File

@@ -1,6 +1,6 @@
/*********************************** /***********************************
webpack_headers webpack_headers
dist/css/index.1ab179394339385e0a02.css.gz,dist/favicon-32x32.png,dist/index.html.gz,dist/js/index.b02584.bundle.js.gz,dist/js/node_vendors.b02584.bundle.js.gz dist/css/index.1ab179394339385e0a02.css.gz,dist/favicon-32x32.png,dist/index.html.gz,dist/js/index.e0b953.bundle.js.gz,dist/js/node_vendors.e0b953.bundle.js.gz
***********************************/ ***********************************/
#pragma once #pragma once
#include <inttypes.h> #include <inttypes.h>

View File

@@ -0,0 +1,117 @@
const path = require("path");
const fs = require('fs');
const zlib = require("zlib");
const glob = require('glob');
class BuildEventsHook {
constructor(name, fn, stage = 'afterEmit') {
this.name = name;
this.stage = stage;
this.function = fn;
}
apply(compiler) {
compiler.hooks[this.stage].tap(this.name, this.function);
}
}
function createBuildEventsHook(options){
return new BuildEventsHook('Update C App',
function (stats, arguments) {
if (options.mode !== "production") return;
let buildRootPath = path.join(process.cwd(), '..', '..', '..');
let wifiManagerPath = glob.sync(path.join(buildRootPath, 'components/**/wifi-manager*'))[0];
let buildCRootPath = glob.sync(buildRootPath)[0];
fs.appendFileSync('./dist/index.html.gz',
zlib.gzipSync(fs.readFileSync('./dist/index.html'),
{
chunckSize: 65536,
level: zlib.constants.Z_BEST_COMPRESSION
}));
let getDirectories = function getDirectories (src, callback) {
let searchPath = path.posix.join(src, '/**/*(*.gz|favicon-32x32.png)');
console.log(`Post build: Getting file list from ${searchPath}`);
glob(searchPath, callback);
};
let cleanUpPath = path.posix.join(buildCRootPath, '/build/*.S');
console.log(`Post build: Cleaning up previous builds in ${cleanUpPath}`);
glob(cleanUpPath, function (err, list) {
if (err) {
console.error('Error', err);
} else {
list.forEach(fileName => {
try {
console.log(`Post build: Purging old binary file ${fileName} from C project.`);
fs.unlinkSync(fileName)
//file removed
} catch (ferr) {
console.error(ferr)
}
});
}
},
'afterEmit'
);
console.log('Generating C include files from webpack build output');
getDirectories('./dist', function (err, list) {
console.log(`Post build: found ${list.length} files. Relative path: ${wifiManagerPath}.`);
if (err) {
console.log('Error', err);
} else {
let exportDefHead =
`/***********************************
webpack_headers
${arguments[1]}
***********************************/
#pragma once
#include <inttypes.h>
extern const char * resource_lookups[];
extern const uint8_t * resource_map_start[];
extern const uint8_t * resource_map_end[];`;
let exportDef = '// Automatically generated. Do not edit manually!.\n' +
'#include <inttypes.h>\n';
let lookupDef = 'const char * resource_lookups[] = {\n';
let lookupMapStart = 'const uint8_t * resource_map_start[] = {\n';
let lookupMapEnd = 'const uint8_t * resource_map_end[] = {\n';
let cMake = '';
list.forEach(foundFile => {
let exportName = path.basename(foundFile).replace(/[\. \-]/gm, '_');
//take the full path of the file and make it relative to the build directory
let cmakeFileName = path.posix.relative(wifiManagerPath, glob.sync(path.resolve(foundFile))[0]);
let httpRelativePath = path.posix.join('/', path.posix.relative('dist', foundFile));
exportDef += `extern const uint8_t _${exportName}_start[] asm("_binary_${exportName}_start");\nextern const uint8_t _${exportName}_end[] asm("_binary_${exportName}_end");\n`;
lookupDef += `\t"${httpRelativePath}",\n`;
lookupMapStart += '\t_' + exportName + '_start,\n';
lookupMapEnd += '\t_' + exportName + '_end,\n';
cMake += `target_add_binary_data( __idf_wifi-manager ${cmakeFileName} BINARY)\n`;
console.log(`Post build: adding cmake file reference to ${cmakeFileName} from C project, with web path ${httpRelativePath}.`);
});
lookupDef += '""\n};\n';
lookupMapStart = lookupMapStart.substring(0, lookupMapStart.length - 2) + '\n};\n';
lookupMapEnd = lookupMapEnd.substring(0, lookupMapEnd.length - 2) + '\n};\n';
try {
fs.writeFileSync('webapp.cmake', cMake);
fs.writeFileSync('webpack.c', exportDef + lookupDef + lookupMapStart + lookupMapEnd);
fs.writeFileSync('webpack.h', exportDefHead);
//file written successfully
} catch (e) {
console.error(e);
}
}
});
console.log('Post build completed.');
})
}
module.exports = {
BuildEventsHook,
createBuildEventsHook
}

View File

@@ -6,7 +6,7 @@ const HtmlWebPackPlugin = require('html-webpack-plugin');
const { Command } = require('commander'); const { Command } = require('commander');
let cmdLines= { }; let cmdLines= { };
var { parseArgsStringToArgv } = require('string-argv'); var { parseArgsStringToArgv } = require('string-argv');
const PORT = 9100; const PORT = 5000;
const data = { const data = {
messages: require("../mock/messages.json"), messages: require("../mock/messages.json"),
@@ -159,7 +159,7 @@ module.exports ={
open: true, open: true,
compress: true, compress: true,
port: PORT, port: PORT,
host: '127.0.0.1',//your ip address host: '0.0.0.0',
allowedHosts: "all", allowedHosts: "all",
headers: {'Access-Control-Allow-Origin': '*', 'Accept-Encoding': 'identity'}, headers: {'Access-Control-Allow-Origin': '*', 'Accept-Encoding': 'identity'},
client: { client: {

View File

@@ -0,0 +1,91 @@
param (
[Parameter(Position=0, Mandatory=$false)]
[ValidateSet("t", "u", "d")]
[string]$option
)
# Get the current directory
$currentDir = Get-Location
# Define target directories
$targetDir = "components\wifi-manager\webapp"
$distDir = "$targetDir\dist"
# Get list of files from the 'dist' directory
$fsFiles = Get-ChildItem -Recurse $distDir -File | ForEach-Object {
$_.FullName.Substring($currentDir.Path.Length + 1).Replace("\", "/")
}
# Define additional files to include
$additionalFiles = @("webpack.c", "webpack.h", "webapp.cmake")
# Check if additional files exist in $targetDir and format them
$additionalFilesFormatted = @()
Get-ChildItem $targetDir -File | ForEach-Object {
if ($additionalFiles -contains $_.Name) {
$formatted = $_.FullName.Substring($currentDir.Path.Length + 1).Replace("\", "/")
$additionalFilesFormatted += $formatted
Write-Host "Found $formatted"
}
}
# Get list of files from the Git index
$indexFiles = git ls-files -s $distDir | ForEach-Object {
($_ -split "\s+")[3]
}
# Combine and remove duplicates
$allFiles = $fsFiles + $additionalFilesFormatted + $indexFiles | Sort-Object -Unique
# ... (previous code remains unchanged)
# Apply the git command based on the option
$allFiles | ForEach-Object {
$relativePath = $_
$isInIndex = $indexFiles -contains $relativePath
if ($null -eq $option) {
$gitStatus = & git status --porcelain -- $relativePath
if ($gitStatus) {
$status = ($gitStatus -split "\s")[0]
Write-Host "$relativePath has Git status: $status"
} else {
Write-Host "$relativePath is not tracked"
}
}
elseif ($isInIndex) {
if ($option -eq "d") {
$resetResult = & git reset -- $relativePath 2>&1
if ($resetResult -match 'error:') {
Write-Host "Error resetting ${relativePath}: $resetResult"
continue
}
$checkoutResult = & git checkout -- $relativePath 2>&1
if ($checkoutResult -match 'error:') {
Write-Host "Error checking out ${relativePath}: $checkoutResult"
continue
}
Write-Host "Discarded changes in $relativePath"
}
# ... (rest of the code remains unchanged)
}
# else {
# # if ($option -eq "d") {
# # Remove-Item -Path $relativePath -Force
# # Write-Host "Removed untracked file $relativePath"
# # } else {
# # Write-Host "File $relativePath is not tracked."
# # }
# }
else {
if ($option -eq "t") {
git add $relativePath
git update-index --no-skip-worktree $relativePath
Write-Host "Started tracking changes in $relativePath"
} else {
Write-Host "File $relativePath is not tracked."
}
}
}

View File

@@ -68,7 +68,68 @@ bool cold_boot=true;
extern const char _ctype_[]; extern const char _ctype_[];
const char* __ctype_ptr__ = _ctype_; const char* __ctype_ptr__ = _ctype_;
#endif #endif
typedef struct {
const char *key;
const char *value;
} DefaultStringVal;
typedef struct {
const char *key;
unsigned int uint_value;
bool is_signed;
} DefaultNumVal;
const DefaultNumVal defaultNumVals[] = {
{"ota_erase_blk", OTA_FLASH_ERASE_BLOCK, 0},
{"ota_stack", OTA_STACK_SIZE, 0},
{"ota_prio", OTA_TASK_PRIOTITY, 1}
};
const DefaultStringVal defaultStringVals[] = {
{"equalizer", ""},
{"loudness", "0"},
{"actrls_config", ""},
{"lms_ctrls_raw", "n"},
{"rotary_config", CONFIG_ROTARY_ENCODER},
{"display_config", CONFIG_DISPLAY_CONFIG},
{"eth_config", CONFIG_ETH_CONFIG},
{"i2c_config", CONFIG_I2C_CONFIG},
{"spi_config", CONFIG_SPI_CONFIG},
{"set_GPIO", CONFIG_SET_GPIO},
{"sleep_config", ""},
{"led_brightness", ""},
{"spdif_config", ""},
{"dac_config", ""},
{"dac_controlset", ""},
{"jack_mutes_amp", "n"},
{"gpio_exp_config", CONFIG_GPIO_EXP_CONFIG},
{"bat_config", ""},
{"metadata_config", ""},
{"telnet_enable", ""},
{"telnet_buffer", "40000"},
{"telnet_block", "500"},
{"stats", "n"},
{"rel_api", CONFIG_RELEASE_API},
{"pollmx", "600"},
{"pollmin", "15"},
{"ethtmout", "8"},
{"dhcp_tmout", "8"},
{"target", CONFIG_TARGET},
{"led_vu_config", ""},
#ifdef CONFIG_BT_SINK
{"bt_sink_pin", STR(CONFIG_BT_SINK_PIN)},
{"bt_sink_volume", "127"},
// Note: register_default_with_mac("bt_name", CONFIG_BT_NAME); is a special case
{"enable_bt_sink", STR(CONFIG_BT_SINK)},
{"a2dp_dev_name", CONFIG_A2DP_DEV_NAME},
{"a2dp_ctmt", STR(CONFIG_A2DP_CONNECT_TIMEOUT_MS)},
{"a2dp_ctrld", STR(CONFIG_A2DP_CONTROL_DELAY_MS)},
{"a2dp_sink_name", CONFIG_A2DP_SINK_NAME},
{"autoexec", "1"},
#ifdef CONFIG_AIRPLAY_SINK
{"airplay_port", CONFIG_AIRPLAY_PORT},
{"enable_airplay", STR(CONFIG_AIRPLAY_SINK)}
#endif
#endif
};
static bool bNetworkConnected=false; static bool bNetworkConnected=false;
// as an exception _init function don't need include // as an exception _init function don't need include
@@ -80,7 +141,9 @@ extern void target_init(char *target);
const char * str_or_unknown(const char * str) { return (str?str:unknown_string_placeholder); } const char * str_or_unknown(const char * str) { return (str?str:unknown_string_placeholder); }
const char * str_or_null(const char * str) { return (str?str:null_string_placeholder); } const char * str_or_null(const char * str) { return (str?str:null_string_placeholder); }
bool is_recovery_running; bool is_recovery_running;
bool is_network_connected(){
return bNetworkConnected;
}
void cb_connection_got_ip(nm_state_t new_state, int sub_state){ void cb_connection_got_ip(nm_state_t new_state, int sub_state){
const char *hostname; const char *hostname;
static ip4_addr_t ip; static ip4_addr_t ip;
@@ -163,7 +226,7 @@ void set_log_level(char * tag, char * level){
} }
#define DEFAULT_NAME_WITH_MAC(var,defval) char var[strlen(defval)+sizeof(macStr)]; strcpy(var,defval); strcat(var,macStr) #define DEFAULT_NAME_WITH_MAC(var,defval) char var[strlen(defval)+sizeof(macStr)]; strcpy(var,defval); strcat(var,macStr)
void register_default_string_val(const char * key, char * value){ void register_default_string_val(const char * key, const char * value){
char * existing =(char *)config_alloc_get(NVS_TYPE_STR,key ); char * existing =(char *)config_alloc_get(NVS_TYPE_STR,key );
ESP_LOGD(TAG,"Register default called with: %s= %s",key,value ); ESP_LOGD(TAG,"Register default called with: %s= %s",key,value );
if(!existing) { if(!existing) {
@@ -175,7 +238,15 @@ void register_default_string_val(const char * key, char * value){
} }
FREE_AND_NULL(existing); FREE_AND_NULL(existing);
} }
void register_single_default_num_val(const DefaultNumVal *entry) {
char number_buffer[101] = {};
if (entry->is_signed) {
snprintf(number_buffer, sizeof(number_buffer) - 1, "%d", entry->uint_value);
} else {
snprintf(number_buffer, sizeof(number_buffer) - 1, "%u", entry->uint_value);
}
register_default_string_val(entry->key, number_buffer);
}
char * alloc_get_string_with_mac(const char * val) { char * alloc_get_string_with_mac(const char * val) {
uint8_t mac[6]; uint8_t mac[6];
char macStr[LOCAL_MAC_SIZE + 1]; char macStr[LOCAL_MAC_SIZE + 1];
@@ -220,77 +291,25 @@ void register_default_nvs(){
else { else {
register_default_string_val("cspot_config", ""); register_default_string_val("cspot_config", "");
} }
} }
#endif #endif
#ifdef CONFIG_AIRPLAY_SINK #ifdef CONFIG_AIRPLAY_SINK
register_default_with_mac("airplay_name", CONFIG_AIRPLAY_NAME); register_default_with_mac("airplay_name", CONFIG_AIRPLAY_NAME);
register_default_string_val("airplay_port", CONFIG_AIRPLAY_PORT);
register_default_string_val( "enable_airplay", STR(CONFIG_AIRPLAY_SINK));
#endif #endif
#ifdef CONFIG_BT_SINK #ifdef CONFIG_BT_SINK
register_default_string_val( "bt_sink_pin", STR(CONFIG_BT_SINK_PIN));
register_default_string_val( "bt_sink_volume", "127");
register_default_with_mac("bt_name", CONFIG_BT_NAME); register_default_with_mac("bt_name", CONFIG_BT_NAME);
register_default_string_val( "enable_bt_sink", STR(CONFIG_BT_SINK));
register_default_string_val("a2dp_dev_name", CONFIG_A2DP_DEV_NAME);
register_default_string_val("a2dp_ctmt", STR(CONFIG_A2DP_CONNECT_TIMEOUT_MS));
register_default_string_val("a2dp_ctrld", STR(CONFIG_A2DP_CONTROL_DELAY_MS));
register_default_string_val("a2dp_sink_name", CONFIG_A2DP_SINK_NAME);
#endif #endif
register_default_with_mac("host_name", DEFAULT_HOST_NAME); register_default_with_mac("host_name", DEFAULT_HOST_NAME);
register_default_with_mac("ap_ssid", CONFIG_DEFAULT_AP_SSID); register_default_with_mac("ap_ssid", CONFIG_DEFAULT_AP_SSID);
register_default_string_val("autoexec","1");
register_default_with_mac("autoexec1",CONFIG_DEFAULT_COMMAND_LINE " -n " DEFAULT_HOST_NAME); register_default_with_mac("autoexec1",CONFIG_DEFAULT_COMMAND_LINE " -n " DEFAULT_HOST_NAME);
for (int i = 0; i < sizeof(defaultStringVals) / sizeof(DefaultStringVal); ++i) {
register_default_string_val(defaultStringVals[i].key, defaultStringVals[i].value);
}
for (int i = 0; i < sizeof(defaultNumVals) / sizeof(DefaultNumVal); ++i) {
register_single_default_num_val(&defaultNumVals[i]);
}
register_default_string_val("release_url", CONFIG_SQUEEZELITE_ESP32_RELEASE_URL);
register_default_string_val("ap_ip_address",CONFIG_DEFAULT_AP_IP);
register_default_string_val("ap_ip_gateway",CONFIG_DEFAULT_AP_GATEWAY );
register_default_string_val("ap_ip_netmask",CONFIG_DEFAULT_AP_NETMASK);
register_default_string_val("ap_channel",STR(CONFIG_DEFAULT_AP_CHANNEL));
register_default_string_val("ap_pwd", CONFIG_DEFAULT_AP_PASSWORD);
register_default_string_val("bypass_wm", "0");
register_default_string_val("equalizer", "");
register_default_string_val("loudness", "0");
register_default_string_val("actrls_config", "");
register_default_string_val("lms_ctrls_raw", "n");
register_default_string_val("rotary_config", CONFIG_ROTARY_ENCODER);
char number_buffer[101] = {};
snprintf(number_buffer,sizeof(number_buffer)-1,"%u",OTA_FLASH_ERASE_BLOCK);
register_default_string_val( "ota_erase_blk", number_buffer);
snprintf(number_buffer,sizeof(number_buffer)-1,"%u",OTA_STACK_SIZE);
register_default_string_val( "ota_stack", number_buffer);
snprintf(number_buffer,sizeof(number_buffer)-1,"%d",OTA_TASK_PRIOTITY);
register_default_string_val( "ota_prio", number_buffer);
register_default_string_val( "display_config", CONFIG_DISPLAY_CONFIG);
register_default_string_val( "eth_config", CONFIG_ETH_CONFIG);
register_default_string_val( "i2c_config", CONFIG_I2C_CONFIG);
register_default_string_val( "spi_config", CONFIG_SPI_CONFIG);
register_default_string_val( "set_GPIO", CONFIG_SET_GPIO);
register_default_string_val( "sleep_config", "");
register_default_string_val( "led_brightness", "");
register_default_string_val( "spdif_config", "");
register_default_string_val( "dac_config", "");
register_default_string_val( "dac_controlset", "");
register_default_string_val( "jack_mutes_amp", "n");
register_default_string_val("gpio_exp_config", CONFIG_GPIO_EXP_CONFIG);
register_default_string_val( "bat_config", "");
register_default_string_val( "metadata_config", "");
register_default_string_val( "telnet_enable", "");
register_default_string_val( "telnet_buffer", "40000");
register_default_string_val( "telnet_block", "500");
register_default_string_val( "stats", "n");
register_default_string_val( "rel_api", CONFIG_RELEASE_API);
register_default_string_val("pollmx","600");
register_default_string_val("pollmin","15");
register_default_string_val("ethtmout","8");
register_default_string_val("dhcp_tmout","8");
register_default_string_val("target", CONFIG_TARGET);
register_default_string_val("led_vu_config", "");
wait_for_commit(); wait_for_commit();
ESP_LOGD(TAG,"Done setting default values in nvs."); ESP_LOGD(TAG,"Done setting default values in nvs.");
} }

Binary file not shown.

Binary file not shown.

View File

@@ -144,18 +144,18 @@ LxoOkcXsNb/12jOV3iQSDfXDI41AgtFc694KCOjlg+UKizpemE53T5/cq37OqChP
qnlPyb6PYIhua/kgbH84ltba1xEDQ9i4UYfOMiJNZEzEdSfQ498= qnlPyb6PYIhua/kgbH84ltba1xEDQ9i4UYfOMiJNZEzEdSfQ498=
-----END CERTIFICATE----- -----END CERTIFICATE-----
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIIXzCCB0egAwIBAgIQBKU3dDawNcfrgz6Dj4jGVjANBgkqhkiG9w0BAQsFADA8 MIIIOzCCByOgAwIBAgIQDMnYcxFdn1+HZt0ULgDEwTANBgkqhkiG9w0BAQsFADA8
MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g
UlNBIDIwNDggTTAxMB4XDTIzMDcxMDAwMDAwMFoXDTI0MDYyMTIzNTk1OVowGzEZ UlNBIDIwNDggTTAxMB4XDTIzMTAxMDAwMDAwMFoXDTI0MDcxMDIzNTk1OVowGzEZ
MBcGA1UEAxMQczMuYW1hem9uYXdzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP MBcGA1UEAxMQczMuYW1hem9uYXdzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAMhVo8GFFI8V3qJuBvo9Mcp9O2FkASu1No2kmnXcZn6rqV5Z9Rdz ADCCAQoCggEBANbrGvFbxrAM6TKussVOuHpCNsZX1V+jR6TAfzrO8VQWqiz+DCq+
DSTMBkgBz1UNxyOJ4HujSSjgqrDJ0Fv2uZ+xUfwh8wsZagpoMp6D53nOqzZxwmzi LlGFT2is2kRxY+hv2NswgK+Ie4SUdypQDrJ+mKFadmM2UOqIcFepA4EIUESAXZHg
rs7iGbBHZ0TvROel/zUEayjwm1CpEhM6fPGArITcAUcBZ0kaDLrStyijuqaQQasP lHJAv5460i6gp9Lh6imN3jGjC1Ax0rgrfBZA+uzIy8dorBEptIj/YpE4wD4WPHnk
cnjcsTili+vWk4VhPNXKg9lkwQaWmcj/iUENx2l4Fqe6e93CmlqhYPMyf4lH2oiz Y+wCDfMZdm6b6hqsrOkbqBWHH2zSH8TWfnYRguGe3NkLpM4pBNa2lTb1GBeZtm/W
MX7WZdR1w2bMIP/+J1AAuoll2y0CF60/7w+NidmpGQyujOUV2YPFYhJc0mLRyY0c TB3dEAaxcGCu+WQbicI6BxkbzklgxKTHZ2Lc3mL8P5Ca1yWQG3asdUxw0SIkCZVd
btSo589TxMmhGbKwMywKQbXLueAC/CK0fUUCAwEAAaOCBXwwggV4MB8GA1UdIwQY aCzQxqtLlXSxpe4xK2KjOfq2ZM+MZhq/tR0CAwEAAaOCBVgwggVUMB8GA1UdIwQY
MBaAFIG4DmOKiRIY5fo7O1CVn+blkBOFMB0GA1UdDgQWBBSP/UslcNwoVtOJhOQj MBaAFIG4DmOKiRIY5fo7O1CVn+blkBOFMB0GA1UdDgQWBBQi0miDsNb3pJw4EouH
scAlxpUVVjCCAqwGA1UdEQSCAqMwggKfghBzMy5hbWF6b25hd3MuY29tghIqLnMz AR3hoCAaqzCCAokGA1UdEQSCAoAwggJ8ghBzMy5hbWF6b25hd3MuY29tghIqLnMz
LmFtYXpvbmF3cy5jb22CJiouczMuZHVhbHN0YWNrLnVzLWVhc3QtMS5hbWF6b25h LmFtYXpvbmF3cy5jb22CJiouczMuZHVhbHN0YWNrLnVzLWVhc3QtMS5hbWF6b25h
d3MuY29tgiRzMy5kdWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CHCou d3MuY29tgiRzMy5kdWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CHCou
czMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CGnMzLnVzLWVhc3QtMS5hbWF6b25h czMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CGnMzLnVzLWVhc3QtMS5hbWF6b25h
@@ -164,29 +164,28 @@ LWNvbnRyb2wudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CLiouczMtY29udHJvbC5k
dWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CLHMzLWNvbnRyb2wuZHVh dWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CLHMzLWNvbnRyb2wuZHVh
bHN0YWNrLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgigqLnMzLWFjY2Vzc3BvaW50 bHN0YWNrLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgigqLnMzLWFjY2Vzc3BvaW50
LnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgjIqLnMzLWFjY2Vzc3BvaW50LmR1YWxz LnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgjIqLnMzLWFjY2Vzc3BvaW50LmR1YWxz
dGFjay51cy1lYXN0LTEuYW1hem9uYXdzLmNvbYIhKi5zMy51cy1lYXN0LTEudnBj dGFjay51cy1lYXN0LTEuYW1hem9uYXdzLmNvbYInKi5zMy1kZXByZWNhdGVkLnVz
ZS5hbWF6b25hd3MuY29tgicqLnMzLWRlcHJlY2F0ZWQudXMtZWFzdC0xLmFtYXpv LWVhc3QtMS5hbWF6b25hd3MuY29tgiVzMy1kZXByZWNhdGVkLnVzLWVhc3QtMS5h
bmF3cy5jb22CJXMzLWRlcHJlY2F0ZWQudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22C bWF6b25hd3MuY29tghtzMy1leHRlcm5hbC0xLmFtYXpvbmF3cy5jb22CHSouczMt
G3MzLWV4dGVybmFsLTEuYW1hem9uYXdzLmNvbYIdKi5zMy1leHRlcm5hbC0xLmFt ZXh0ZXJuYWwtMS5hbWF6b25hd3MuY29tghtzMy1leHRlcm5hbC0yLmFtYXpvbmF3
YXpvbmF3cy5jb22CG3MzLWV4dGVybmFsLTIuYW1hem9uYXdzLmNvbYIdKi5zMy1l cy5jb22CHSouczMtZXh0ZXJuYWwtMi5hbWF6b25hd3MuY29tMBMGA1UdIAQMMAow
eHRlcm5hbC0yLmFtYXpvbmF3cy5jb20wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQW CAYGZ4EMAQIBMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYI
MBQGCCsGAQUFBwMBBggrBgEFBQcDAjA7BgNVHR8ENDAyMDCgLqAshipodHRwOi8v KwYBBQUHAwIwOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovL2NybC5yMm0wMS5hbWF6
Y3JsLnIybTAxLmFtYXpvbnRydXN0LmNvbS9yMm0wMS5jcmwwEwYDVR0gBAwwCjAI b250cnVzdC5jb20vcjJtMDEuY3JsMHUGCCsGAQUFBwEBBGkwZzAtBggrBgEFBQcw
BgZngQwBAgEwdQYIKwYBBQUHAQEEaTBnMC0GCCsGAQUFBzABhiFodHRwOi8vb2Nz AYYhaHR0cDovL29jc3AucjJtMDEuYW1hem9udHJ1c3QuY29tMDYGCCsGAQUFBzAC
cC5yMm0wMS5hbWF6b250cnVzdC5jb20wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQu hipodHRwOi8vY3J0LnIybTAxLmFtYXpvbnRydXN0LmNvbS9yMm0wMS5jZXIwDAYD
cjJtMDEuYW1hem9udHJ1c3QuY29tL3IybTAxLmNlcjAMBgNVHRMBAf8EAjAAMIIB VR0TAQH/BAIwADCCAX0GCisGAQQB1nkCBAIEggFtBIIBaQFnAHYA7s3QZNXbGs7F
fgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdwDuzdBk1dsazsVct520zROiModGfLzs XLedtM0TojKHRny87N7DUUhZRnEftZsAAAGLG2S5PwAABAMARzBFAiEAxOJvK1tq
3sNRSFlGcR+1mwAAAYlCAMrQAAAEAwBIMEYCIQCJhWcUFTgBlQtPboTv0HorPNkz gzf5d6NPN4PZui5PhQePCg1bH/fVMd7T5ekCIHeOglhFW5BC0TNeHY+cfUOvDONT
l+/o8Fr1hFYfs+8bIQIhAOaCRLr5774k0iflsslqBMmubN3NC+mImezWIaMHPP26 DV4fAVcaWsBXErw9AHUASLDja9qmRzQP5WoC+p0w6xxSActW3SyB2bu/qznYhHMA
AHUA2ra/az+1tiKfm8K7XGvocJFxbLtRhIU0vaQ9MEjX+6sAAAGJQgDK8gAABAMA AAGLG2S5LwAABAMARjBEAiBYu16xOFIzUE9aMrB1vrFkTsMC3veucw9k0Hv4qO2v
RjBEAiBalCI6KSCFXMTY15CgLEHtqeE/vyihg8FWthX4JgPcFwIgWkI//yF+tqBi XAIgTTMRV9sq+ytuTU53XdoKLF33qeUZHGqop7O7xoFEENMAdgDatr9rP7W2Ip+b
Gs3sHuuGvG4v7rytkUM4Dli6sWAYXsYAdgA7U3d1Pi25gE6LMFsG/kA7Z9hPw/TH wrtca+hwkXFsu1GEhTS9pD0wSNf7qwAAAYsbZLlmAAAEAwBHMEUCIQCD6n2r6DVx
vQANLXJv4frUFwAAAYlCAMsyAAAEAwBHMEUCIQDfn+j2sutaXvO5yZ86z6OFgq1u UMUgtfPRi3ieJdlObPzsrc0aGVhl6gCP5QIgbzkLqEOfJ7bozTgYzUO8ZDvAd0te
WhNwM2MnEHfGhO+yCAIgLYi8SX6hZRGRZFxIrV1ekcRSk+9yN8oHNfOQOuGQQOEw cdpZv182ZEQ974wwDQYJKoZIhvcNAQELBQADggEBAHEAZnHOPS7CoRXWTqWbQu5V
DQYJKoZIhvcNAQELBQADggEBAIprc7vYrAerkphosDZ2frlk9gYBnlgTYT0wJXLC 8x2uFNl5jjsbSH68xnviW24ShllvFyHH1iD2R3ov/3Ri8T8TJ0bA14u+3D/iPZk1
4ZTnlhXuMbL5gYmM8T1suPv5p2JphVFEsSS8PlmdQX45mPAlk8lHjHSZJRgL/r1Y BgX2/YdL/0/CptgISLhBtugBk2+MsRry6i7hhbf4/pIyL1uWHUeDuYrW882Xw1ul
7wWYjKB3oHl5N/5UZTtDTtfxtjd/3Vts6citxzhVwGxH+fQspligvb1Sgy8/ojjV uD1wyC1z2CqXZWy0WL0zMV6Yfp/eFnCJ9tj0NoullHGhgk9RTU3qULwuAQmzMqS7
lSz+QwpK2PrxRwvWPt0XImPj+5xPi8MOhRCh32Edtqy5fQkZiG/mYEvMMpq73kv0 XlhmgdzVPDq3s8qCawHDU6yDdT5FAO3SJ23Dj2efM7enBzq0jryfEZn9vTCRJfKI
uWbcjMFN2XbSOSYkjjseVoTBly65MAxFyAFAdg9HMJeJ5hbegpl4PARhgdL8sG3h yCZT56FgMdEqvmQutAV5UCiL1acK8YU2zUQSxuWn+AyDivV4JSOYw8ho1yZrZZI=
jEenWaFiCjwQ4iCPFeGk+vumNkL1c5OaLFZwhoZQ+KLkAQc=
-----END CERTIFICATE----- -----END CERTIFICATE-----

BIN
server_certs/r2m01.cer.31 Normal file

Binary file not shown.

BIN
server_certs/r2m01.cer.32 Normal file

Binary file not shown.

View File

@@ -1,16 +1,16 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIIXzCCB0egAwIBAgIQBKU3dDawNcfrgz6Dj4jGVjANBgkqhkiG9w0BAQsFADA8 MIIIOzCCByOgAwIBAgIQDMnYcxFdn1+HZt0ULgDEwTANBgkqhkiG9w0BAQsFADA8
MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g
UlNBIDIwNDggTTAxMB4XDTIzMDcxMDAwMDAwMFoXDTI0MDYyMTIzNTk1OVowGzEZ UlNBIDIwNDggTTAxMB4XDTIzMTAxMDAwMDAwMFoXDTI0MDcxMDIzNTk1OVowGzEZ
MBcGA1UEAxMQczMuYW1hem9uYXdzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP MBcGA1UEAxMQczMuYW1hem9uYXdzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAMhVo8GFFI8V3qJuBvo9Mcp9O2FkASu1No2kmnXcZn6rqV5Z9Rdz ADCCAQoCggEBANbrGvFbxrAM6TKussVOuHpCNsZX1V+jR6TAfzrO8VQWqiz+DCq+
DSTMBkgBz1UNxyOJ4HujSSjgqrDJ0Fv2uZ+xUfwh8wsZagpoMp6D53nOqzZxwmzi LlGFT2is2kRxY+hv2NswgK+Ie4SUdypQDrJ+mKFadmM2UOqIcFepA4EIUESAXZHg
rs7iGbBHZ0TvROel/zUEayjwm1CpEhM6fPGArITcAUcBZ0kaDLrStyijuqaQQasP lHJAv5460i6gp9Lh6imN3jGjC1Ax0rgrfBZA+uzIy8dorBEptIj/YpE4wD4WPHnk
cnjcsTili+vWk4VhPNXKg9lkwQaWmcj/iUENx2l4Fqe6e93CmlqhYPMyf4lH2oiz Y+wCDfMZdm6b6hqsrOkbqBWHH2zSH8TWfnYRguGe3NkLpM4pBNa2lTb1GBeZtm/W
MX7WZdR1w2bMIP/+J1AAuoll2y0CF60/7w+NidmpGQyujOUV2YPFYhJc0mLRyY0c TB3dEAaxcGCu+WQbicI6BxkbzklgxKTHZ2Lc3mL8P5Ca1yWQG3asdUxw0SIkCZVd
btSo589TxMmhGbKwMywKQbXLueAC/CK0fUUCAwEAAaOCBXwwggV4MB8GA1UdIwQY aCzQxqtLlXSxpe4xK2KjOfq2ZM+MZhq/tR0CAwEAAaOCBVgwggVUMB8GA1UdIwQY
MBaAFIG4DmOKiRIY5fo7O1CVn+blkBOFMB0GA1UdDgQWBBSP/UslcNwoVtOJhOQj MBaAFIG4DmOKiRIY5fo7O1CVn+blkBOFMB0GA1UdDgQWBBQi0miDsNb3pJw4EouH
scAlxpUVVjCCAqwGA1UdEQSCAqMwggKfghBzMy5hbWF6b25hd3MuY29tghIqLnMz AR3hoCAaqzCCAokGA1UdEQSCAoAwggJ8ghBzMy5hbWF6b25hd3MuY29tghIqLnMz
LmFtYXpvbmF3cy5jb22CJiouczMuZHVhbHN0YWNrLnVzLWVhc3QtMS5hbWF6b25h LmFtYXpvbmF3cy5jb22CJiouczMuZHVhbHN0YWNrLnVzLWVhc3QtMS5hbWF6b25h
d3MuY29tgiRzMy5kdWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CHCou d3MuY29tgiRzMy5kdWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CHCou
czMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CGnMzLnVzLWVhc3QtMS5hbWF6b25h czMudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CGnMzLnVzLWVhc3QtMS5hbWF6b25h
@@ -19,29 +19,28 @@ LWNvbnRyb2wudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CLiouczMtY29udHJvbC5k
dWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CLHMzLWNvbnRyb2wuZHVh dWFsc3RhY2sudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22CLHMzLWNvbnRyb2wuZHVh
bHN0YWNrLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgigqLnMzLWFjY2Vzc3BvaW50 bHN0YWNrLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgigqLnMzLWFjY2Vzc3BvaW50
LnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgjIqLnMzLWFjY2Vzc3BvaW50LmR1YWxz LnVzLWVhc3QtMS5hbWF6b25hd3MuY29tgjIqLnMzLWFjY2Vzc3BvaW50LmR1YWxz
dGFjay51cy1lYXN0LTEuYW1hem9uYXdzLmNvbYIhKi5zMy51cy1lYXN0LTEudnBj dGFjay51cy1lYXN0LTEuYW1hem9uYXdzLmNvbYInKi5zMy1kZXByZWNhdGVkLnVz
ZS5hbWF6b25hd3MuY29tgicqLnMzLWRlcHJlY2F0ZWQudXMtZWFzdC0xLmFtYXpv LWVhc3QtMS5hbWF6b25hd3MuY29tgiVzMy1kZXByZWNhdGVkLnVzLWVhc3QtMS5h
bmF3cy5jb22CJXMzLWRlcHJlY2F0ZWQudXMtZWFzdC0xLmFtYXpvbmF3cy5jb22C bWF6b25hd3MuY29tghtzMy1leHRlcm5hbC0xLmFtYXpvbmF3cy5jb22CHSouczMt
G3MzLWV4dGVybmFsLTEuYW1hem9uYXdzLmNvbYIdKi5zMy1leHRlcm5hbC0xLmFt ZXh0ZXJuYWwtMS5hbWF6b25hd3MuY29tghtzMy1leHRlcm5hbC0yLmFtYXpvbmF3
YXpvbmF3cy5jb22CG3MzLWV4dGVybmFsLTIuYW1hem9uYXdzLmNvbYIdKi5zMy1l cy5jb22CHSouczMtZXh0ZXJuYWwtMi5hbWF6b25hd3MuY29tMBMGA1UdIAQMMAow
eHRlcm5hbC0yLmFtYXpvbmF3cy5jb20wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQW CAYGZ4EMAQIBMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYI
MBQGCCsGAQUFBwMBBggrBgEFBQcDAjA7BgNVHR8ENDAyMDCgLqAshipodHRwOi8v KwYBBQUHAwIwOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovL2NybC5yMm0wMS5hbWF6
Y3JsLnIybTAxLmFtYXpvbnRydXN0LmNvbS9yMm0wMS5jcmwwEwYDVR0gBAwwCjAI b250cnVzdC5jb20vcjJtMDEuY3JsMHUGCCsGAQUFBwEBBGkwZzAtBggrBgEFBQcw
BgZngQwBAgEwdQYIKwYBBQUHAQEEaTBnMC0GCCsGAQUFBzABhiFodHRwOi8vb2Nz AYYhaHR0cDovL29jc3AucjJtMDEuYW1hem9udHJ1c3QuY29tMDYGCCsGAQUFBzAC
cC5yMm0wMS5hbWF6b250cnVzdC5jb20wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQu hipodHRwOi8vY3J0LnIybTAxLmFtYXpvbnRydXN0LmNvbS9yMm0wMS5jZXIwDAYD
cjJtMDEuYW1hem9udHJ1c3QuY29tL3IybTAxLmNlcjAMBgNVHRMBAf8EAjAAMIIB VR0TAQH/BAIwADCCAX0GCisGAQQB1nkCBAIEggFtBIIBaQFnAHYA7s3QZNXbGs7F
fgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdwDuzdBk1dsazsVct520zROiModGfLzs XLedtM0TojKHRny87N7DUUhZRnEftZsAAAGLG2S5PwAABAMARzBFAiEAxOJvK1tq
3sNRSFlGcR+1mwAAAYlCAMrQAAAEAwBIMEYCIQCJhWcUFTgBlQtPboTv0HorPNkz gzf5d6NPN4PZui5PhQePCg1bH/fVMd7T5ekCIHeOglhFW5BC0TNeHY+cfUOvDONT
l+/o8Fr1hFYfs+8bIQIhAOaCRLr5774k0iflsslqBMmubN3NC+mImezWIaMHPP26 DV4fAVcaWsBXErw9AHUASLDja9qmRzQP5WoC+p0w6xxSActW3SyB2bu/qznYhHMA
AHUA2ra/az+1tiKfm8K7XGvocJFxbLtRhIU0vaQ9MEjX+6sAAAGJQgDK8gAABAMA AAGLG2S5LwAABAMARjBEAiBYu16xOFIzUE9aMrB1vrFkTsMC3veucw9k0Hv4qO2v
RjBEAiBalCI6KSCFXMTY15CgLEHtqeE/vyihg8FWthX4JgPcFwIgWkI//yF+tqBi XAIgTTMRV9sq+ytuTU53XdoKLF33qeUZHGqop7O7xoFEENMAdgDatr9rP7W2Ip+b
Gs3sHuuGvG4v7rytkUM4Dli6sWAYXsYAdgA7U3d1Pi25gE6LMFsG/kA7Z9hPw/TH wrtca+hwkXFsu1GEhTS9pD0wSNf7qwAAAYsbZLlmAAAEAwBHMEUCIQCD6n2r6DVx
vQANLXJv4frUFwAAAYlCAMsyAAAEAwBHMEUCIQDfn+j2sutaXvO5yZ86z6OFgq1u UMUgtfPRi3ieJdlObPzsrc0aGVhl6gCP5QIgbzkLqEOfJ7bozTgYzUO8ZDvAd0te
WhNwM2MnEHfGhO+yCAIgLYi8SX6hZRGRZFxIrV1ekcRSk+9yN8oHNfOQOuGQQOEw cdpZv182ZEQ974wwDQYJKoZIhvcNAQELBQADggEBAHEAZnHOPS7CoRXWTqWbQu5V
DQYJKoZIhvcNAQELBQADggEBAIprc7vYrAerkphosDZ2frlk9gYBnlgTYT0wJXLC 8x2uFNl5jjsbSH68xnviW24ShllvFyHH1iD2R3ov/3Ri8T8TJ0bA14u+3D/iPZk1
4ZTnlhXuMbL5gYmM8T1suPv5p2JphVFEsSS8PlmdQX45mPAlk8lHjHSZJRgL/r1Y BgX2/YdL/0/CptgISLhBtugBk2+MsRry6i7hhbf4/pIyL1uWHUeDuYrW882Xw1ul
7wWYjKB3oHl5N/5UZTtDTtfxtjd/3Vts6citxzhVwGxH+fQspligvb1Sgy8/ojjV uD1wyC1z2CqXZWy0WL0zMV6Yfp/eFnCJ9tj0NoullHGhgk9RTU3qULwuAQmzMqS7
lSz+QwpK2PrxRwvWPt0XImPj+5xPi8MOhRCh32Edtqy5fQkZiG/mYEvMMpq73kv0 XlhmgdzVPDq3s8qCawHDU6yDdT5FAO3SJ23Dj2efM7enBzq0jryfEZn9vTCRJfKI
uWbcjMFN2XbSOSYkjjseVoTBly65MAxFyAFAdg9HMJeJ5hbegpl4PARhgdL8sG3h yCZT56FgMdEqvmQutAV5UCiL1acK8YU2zUQSxuWn+AyDivV4JSOYw8ho1yZrZZI=
jEenWaFiCjwQ4iCPFeGk+vumNkL1c5OaLFZwhoZQ+KLkAQc=
-----END CERTIFICATE----- -----END CERTIFICATE-----