Compare commits

...

8 Commits

Author SHA1 Message Date
github-actions
0a653bf374 Update prebuilt objects [skip actions] 2023-10-19 00:09:58 +00:00
philippe44
2a77d09f11 fix Spotify queue modifications - release 2023-10-18 17:07:29 -07:00
philippe44
d03678ea81 misc changes (see PR) (#340)
* misc changes (see PR)

* macro only parsing
2023-10-16 21:50:50 -04:00
github-actions
5019b5bf0f Update prebuilt objects [skip actions] 2023-10-13 16:21:39 +00:00
Sebastien L
3f1a7265b1 Use DEFINES for parsing - release
fixes https://github.com/sle118/squeezelite-esp32/issues/332
2023-10-13 12:19:21 -04:00
philippe44
338eea33d1 Update README.md 2023-10-11 15:43:03 -07:00
philippe44
ffb79e1e8c Update README.md 2023-10-11 15:36:21 -07:00
github-actions
1fe515b18d Update prebuilt objects [skip actions] 2023-10-11 18:46:48 +00:00
39 changed files with 165 additions and 182 deletions

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.
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
{ <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
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
**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 `<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.

View File

@@ -77,7 +77,7 @@ void Batch::push() {
char* json_str = to_json_str();
ESP_LOGV(TAG, "Metrics payload: %s", json_str);
time_t start_time = millis();
uint32_t start_time = gettime_ms();
status_code = metrics_http_post_request(json_str, _url);
@@ -85,7 +85,7 @@ void Batch::push() {
_events.clear();
}
FREE_AND_NULL(json_str)
ESP_LOGD(TAG, "Total duration for metrics call: %lu. ", millis() - start_time);
ESP_LOGD(TAG, "Total duration for metrics call: %lu. ", gettime_ms() - start_time);
}
void Batch::build_guid() {

View File

@@ -45,7 +45,7 @@ class Event {
}
private:
char* _name = nullptr;
time_t _time;
uint32_t _time;
cJSON* _json = nullptr;
};

View File

@@ -31,7 +31,7 @@ extern bool is_network_connected();
#define MAX_HTTP_RECV_BUFFER 512
static bool metrics_usage_gen = false;
static time_t metrics_usage_gen_time = 0;
static uint32_t metrics_usage_gen_time = 0;
#ifndef METRICS_API_KEY
#pragma message "Metrics API key needs to be passed from the environment"
#define METRICS_API_KEY "ZZZ"
@@ -56,7 +56,7 @@ static void metrics_timer_cb(void* timer_id) {
batch.push();
}
}
if (millis() > metrics_usage_gen_time && !metrics_usage_gen) {
if (gettime_ms() > metrics_usage_gen_time && !metrics_usage_gen) {
metrics_usage_gen = true;
ESP_LOGV(TAG, "Generate command list to pull features");
cJSON* cmdlist = get_cmd_list();
@@ -75,7 +75,7 @@ void metrics_init() {
}
// set a 20 seconds delay before generating the
// features so the system has time to boot
metrics_usage_gen_time = millis() + 20000;
metrics_usage_gen_time = gettime_ms() + 20000;
}
void metrics_event_playback(const char* source) {

View File

@@ -538,7 +538,7 @@ bool config_set_group_bit(int bit_num,bool flag){
return result;
}
void config_set_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size) {
void config_set_default(nvs_type_t type, const char *key, const void * default_value, size_t blob_size) {
if(!config_lock(LOCK_MAX_WAIT/portTICK_PERIOD_MS)){
ESP_LOGE(TAG, "Unable to lock config");
return;
@@ -791,43 +791,6 @@ cJSON* cjson_update_number(cJSON** root, const char* key, int value) {
}
return *root;
}
bool config_parse_param_int(const char * config,const char * param, char delimiter,int * value){
const char *p;
if(!value){
return false;
}
if ((p = strcasestr(config, param)) && (p = strchr(p, delimiter))) {
*value = atoi(p+1);
return true;
}
return false;
}
bool config_parse_param_float(const char * config,const char * param, char delimiter,double * value){
const char *p;
if(!value){
return false;
}
if ((p = strcasestr(config, param)) && (p = strchr(p, delimiter))) {
*value = atof(p+1);
return true;
}
return false;
}
bool config_parse_param_str(const char *source, const char *param, char delimiter, char *value, size_t value_size) {
char *p;
if ((p = strstr(source, param)) && (p = strchr(p, delimiter))) {
while (*++p == ' '); // Skip spaces
// Read the value into the buffer, making sure not to overflow
snprintf(value, value_size, "%s", p);
char *end = strchr(value, ',');
if (end) {
*end = '\0'; // Null-terminate at the comma, if found
}
return true;
}
return false;
}
IMPLEMENT_SET_DEFAULT(uint8_t,NVS_TYPE_U8);
IMPLEMENT_SET_DEFAULT(int8_t,NVS_TYPE_I8);

View File

@@ -8,12 +8,7 @@
#ifdef __cplusplus
extern "C" {
#endif
#define PARSE_WITH_FUNC 1
#ifdef PARSE_WITH_FUNC
#define PARSE_PARAM(S,P,C,V) config_parse_param_int(S,P,C,(int*)&V)
#define PARSE_PARAM_STR(S,P,C,V,I) config_parse_param_str(S,P,C,V,I)
#define PARSE_PARAM_FLOAT(S,P,C,V) config_parse_param_float(S,P,C,&V)
#else
#define PARSE_PARAM(S,P,C,V) do { \
char *__p; \
if ((__p = strcasestr(S, P)) && (__p = strchr(__p, C))) V = atoi(__p+1); \
@@ -31,7 +26,7 @@ extern "C" {
sscanf(__p,"%" #I "[^,]", V); \
} \
} while (0)
#endif
#define DECLARE_SET_DEFAULT(t) void config_set_default_## t (const char *key, t value);
#define DECLARE_GET_NUM(t) esp_err_t config_get_## t (const char *key, t * value);
#ifndef FREE_RESET
@@ -55,9 +50,6 @@ bool config_has_changes();
void config_commit_to_nvs();
void config_start_timer();
void config_init();
bool config_parse_param_int(const char * config,const char * param, char delimiter,int * value);
bool config_parse_param_float(const char * config,const char * param, char delimiter,double * value);
bool config_parse_param_str(const char *source, const char *param, char delimiter, char *value, size_t value_size);
void * config_alloc_get_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size);
void * config_alloc_get_str(const char *key, char *lead, char *fallback);
cJSON * config_alloc_get_cjson(const char *key);
@@ -65,7 +57,7 @@ esp_err_t config_set_cjson_str_and_free(const char *key, cJSON *value);
esp_err_t config_set_cjson(const char *key, cJSON *value, bool free_cjson);
void config_get_uint16t_from_str(const char *key, uint16_t *value, uint16_t default_value);
void config_delete_key(const char *key);
void config_set_default(nvs_type_t type, const char *key, void * default_value, size_t blob_size);
void config_set_default(nvs_type_t type, const char *key, const void * default_value, size_t blob_size);
void * config_alloc_get(nvs_type_t nvs_type, const char *key) ;
bool wait_for_commit();
char * config_alloc_get_json(bool bFormatted);

View File

@@ -61,11 +61,13 @@ static struct {
struct arg_end* end;
} i2cset_args;
#if CONFIG_WITH_CONFIG_UI
static struct {
struct arg_int* chip_address;
struct arg_int* size;
struct arg_end* end;
} i2cdump_args;
#endif
static struct {
struct arg_int* port;
@@ -559,13 +561,14 @@ static int do_i2cconfig_cmd(int argc, char** argv) {
nerrors += is_output_gpio(i2cconfig_args.sda, f, &conf.sda_io_num, true);
nerrors += is_output_gpio(i2cconfig_args.scl, f, &conf.scl_io_num, true);
#ifdef CONFIG_SQUEEZEAMP
#ifdef CONFIG_I2C_LOCKED
if (i2c_port == I2C_NUM_0) {
i2c_port = I2C_NUM_1;
fprintf(f, "can't use i2c port 0 on SqueezeAMP. Changing to port 1.\n");
fprintf(f, "can't use i2c port 0 when locked by config. Changing to port 1.\n");
}
#endif
if (!nerrors) {
fprintf(f, "Uninstalling i2c driver from port %u if needed\n", i2c_port);
if (is_i2c_started(i2c_port)) {
@@ -601,6 +604,7 @@ static int do_i2cconfig_cmd(int argc, char** argv) {
return nerrors;
}
#if CONFIG_WITH_CONFIG_UI
static int do_i2cdump_cmd(int argc, char** argv) {
int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&i2cdump_args);
if (nerrors != 0) {
@@ -690,7 +694,7 @@ static int do_i2cdump_cmd(int argc, char** argv) {
FREE_AND_NULL(buf);
return 0;
}
#if CONFIG_WITH_CONFIG_UI
static int do_i2cset_cmd(int argc, char** argv) {
int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&i2cset_args);
if (nerrors != 0) {
@@ -738,6 +742,7 @@ static int do_i2cset_cmd(int argc, char** argv) {
return 0;
}
#endif
static int do_i2cget_cmd(int argc, char** argv) {
int nerrors = arg_parse_msg(argc, argv, (struct arg_hdr**)&i2cget_args);
if (nerrors != 0) {
@@ -811,7 +816,9 @@ static int do_i2cget_cmd(int argc, char** argv) {
return 0;
}
esp_err_t cmd_i2ctools_scan_bus(FILE* f, int sda, int scl) {
#ifdef CONFIG_WITH_CONFIG_UI
uint8_t matches[128] = {};
#endif
int last_match = 0;
esp_err_t ret = ESP_OK;
@@ -861,8 +868,9 @@ esp_err_t cmd_i2ctools_scan_bus(FILE* f, int sda, int scl) {
if (ret == ESP_OK) {
#ifndef CONFIG_WITH_CONFIG_UI
fprintf(f, "%02x ", i);
#endif
#else
matches[++last_match - 1] = i;
#endif
}
#ifndef CONFIG_WITH_CONFIG_UI
else if (ret == ESP_ERR_TIMEOUT) {
@@ -888,8 +896,10 @@ esp_err_t cmd_i2ctools_scan_bus(FILE* f, int sda, int scl) {
return 0;
}
static int do_i2cdetect_cmd(int argc, char** argv) {
#ifdef CONFIG_WITH_CONFIG_UI
uint8_t matches[128] = {};
int last_match = 0;
#endif
esp_err_t ret = ESP_OK;
i2c_port_t loc_i2c_port = i2c_port;
// if (i2cset_args.port->count && i2c_get_port(i2cset_args.port->ival[0], &loc_i2c_port) !=
@@ -925,7 +935,9 @@ static int do_i2cdetect_cmd(int argc, char** argv) {
i2c_cmd_link_delete(cmd);
if (ret == ESP_OK) {
fprintf(f, "%02x ", address);
#ifdef CONFIG_WITH_CONFIG_UI
matches[++last_match - 1] = address;
#endif
} else if (ret == ESP_ERR_TIMEOUT) {
fprintf(f, "UU ");
} else {
@@ -1082,7 +1094,7 @@ static void register_i2cset(void) {
cmd_to_json(&i2cset_cmd);
ESP_ERROR_CHECK(esp_console_cmd_register(&i2cset_cmd));
}
#endif
static void register_i2cdump(void) {
i2cdump_args.chip_address =
arg_int1("c", "chip", "<chip_addr>", "Specify the address of the chip on that bus");
@@ -1096,6 +1108,7 @@ static void register_i2cdump(void) {
cmd_to_json(&i2cdump_cmd);
ESP_ERROR_CHECK(esp_console_cmd_register(&i2cdump_cmd));
}
#endif
cJSON* i2config_cb() {
cJSON* values = cJSON_CreateObject();

View File

@@ -67,8 +67,10 @@ static void register_heap();
static void register_dump_heap();
static void register_version();
static void register_restart();
#if CONFIG_WITH_CONFIG_UI
static void register_deep_sleep();
static void register_light_sleep();
#endif
static void register_factory_boot();
static void register_restart_ota();
static void register_set_services();
@@ -556,6 +558,7 @@ static void register_tasks()
/** 'deep_sleep' command puts the chip into deep sleep mode */
#if CONFIG_WITH_CONFIG_UI
static struct {
struct arg_int *wakeup_time;
struct arg_int *wakeup_gpio_num;
@@ -619,6 +622,8 @@ static void register_deep_sleep()
};
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
}
#endif
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;
@@ -737,6 +742,8 @@ static void register_set_services(){
cmd_to_json_with_cb(&cmd,&set_services_cb);
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
}
#if CONFIG_WITH_CONFIG_UI
static struct {
struct arg_int *wakeup_time;
struct arg_int *wakeup_gpio_num;
@@ -828,4 +835,4 @@ static void register_light_sleep()
};
ESP_ERROR_CHECK( esp_console_cmd_register(&cmd) );
}
#endif

View File

@@ -53,6 +53,7 @@ private:
std::atomic<states> state;
std::string credentials;
bool zeroConf;
std::atomic<bool> flushed = false, notify = true;
int startOffset, volume = 0, bitrate = 160;
httpd_handle_t serverHandle;
@@ -60,6 +61,7 @@ private:
cspot_cmd_cb_t cmdHandler;
cspot_data_cb_t dataHandler;
std::string lastTrackId;
cspot::TrackInfo trackInfo;
std::shared_ptr<cspot::LoginBlob> blob;
std::unique_ptr<cspot::SpircHandler> spirc;
@@ -206,11 +208,13 @@ void cspotPlayer::eventHandler(std::unique_ptr<cspot::SpircHandler::Event> event
trackStatus = TRACK_INIT;
// memorize position for when track's beginning will be detected
startOffset = std::get<int>(event->data);
notify = !flushed;
flushed = false;
// Spotify servers do not send volume at connection
spirc->setRemoteVolume(volume);
cmdHandler(CSPOT_START, 44100);
CSPOT_LOG(info, "(re)start playing");
CSPOT_LOG(info, "(re)start playing at %d", startOffset);
break;
}
case cspot::SpircHandler::EventType::PLAY_PAUSE: {
@@ -219,16 +223,14 @@ void cspotPlayer::eventHandler(std::unique_ptr<cspot::SpircHandler::Event> event
break;
}
case cspot::SpircHandler::EventType::TRACK_INFO: {
auto 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;
trackInfo = std::get<cspot::TrackInfo>(event->data);
break;
}
case cspot::SpircHandler::EventType::FLUSH:
flushed = true;
__attribute__ ((fallthrough));
case cspot::SpircHandler::EventType::NEXT:
case cspot::SpircHandler::EventType::PREV:
case cspot::SpircHandler::EventType::FLUSH: {
case cspot::SpircHandler::EventType::PREV: {
cmdHandler(CSPOT_FLUSH);
break;
}
@@ -411,8 +413,13 @@ void cspotPlayer::runTask() {
uint32_t started;
cmdHandler(CSPOT_QUERY_STARTED, &started);
if (started) {
CSPOT_LOG(info, "next track's audio has reached DAC");
spirc->notifyAudioReachedPlayback();
CSPOT_LOG(info, "next track's audio has reached DAC (offset %d)", startOffset);
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;
}
} 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");
playbackState->syncWithRemote();
trackQueue->updateTracks(playbackState->remoteFrame.state.position_ms,
false);
// 1st track is the current one, but update the position
trackQueue->updateTracks(
playbackState->remoteFrame.state.position_ms +
ctx->timeProvider->getSyncedTimestamp() -
playbackState->innerFrame.state.position_measured_at,
false);
this->notify();
sendEvent(EventType::FLUSH);

View File

@@ -11,8 +11,6 @@
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_task.h"
#include "esp_tls.h"
#include "esp_http_client.h"
@@ -24,7 +22,6 @@
#error CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS must be at least 2
#endif
#include "cJSON.h"
const static char TAG[] = "tools";
/****************************************************************************************
@@ -328,13 +325,6 @@ static esp_err_t http_event_handler(esp_http_client_event_t *evt) {
return ESP_OK;
}
time_t millis() {
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
}
void dump_json_content(const char* prefix, cJSON* json, int level) {
if (!json) {
ESP_LOG_LEVEL(level,TAG, "%s: empty!", prefix);

View File

@@ -9,10 +9,9 @@
*/
#pragma once
#include "cJSON.h"
#include "time.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "cJSON.h"
#ifdef __cplusplus
extern "C" {
@@ -56,6 +55,13 @@ void* clone_obj_psram(void * source, size_t source_sz);
char* strdup_psram(const char * source);
const char* str_or_unknown(const char * str);
const char* str_or_null(const char * str);
void dump_json_content(const char* prefix, cJSON* json, int level);
#ifndef gettime_ms
// body is provided somewhere else...
uint32_t _gettime_ms_(void);
#define gettime_ms _gettime_ms_
#endif
typedef void (*http_download_cb_t)(uint8_t* data, size_t len, void *context);
void http_download(char *url, size_t max, http_download_cb_t callback, void *context);
@@ -74,9 +80,6 @@ void vTaskDeleteEXTRAM(TaskHandle_t xTask);
extern const char unknown_string_placeholder[];
time_t millis();
void dump_json_content(const char* prefix, cJSON* json, int level);
#ifdef __cplusplus
}
#endif

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -64,6 +64,8 @@ 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;
@@ -196,6 +198,7 @@ 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 rf: boolean;
declare function refreshStatus(): void;

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/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/js/index.b02584.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/index.1b8c7b.bundle.js.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/node_vendors.1b8c7b.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 _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_b02584_bundle_js_gz_start[] asm("_binary_index_b02584_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 _node_vendors_b02584_bundle_js_gz_start[] asm("_binary_node_vendors_b02584_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 _index_1b8c7b_bundle_js_gz_start[] asm("_binary_index_1b8c7b_bundle_js_gz_start");
extern const uint8_t _index_1b8c7b_bundle_js_gz_end[] asm("_binary_index_1b8c7b_bundle_js_gz_end");
extern const uint8_t _node_vendors_1b8c7b_bundle_js_gz_start[] asm("_binary_node_vendors_1b8c7b_bundle_js_gz_start");
extern const uint8_t _node_vendors_1b8c7b_bundle_js_gz_end[] asm("_binary_node_vendors_1b8c7b_bundle_js_gz_end");
const char * resource_lookups[] = {
"/css/index.1ab179394339385e0a02.css.gz",
"/favicon-32x32.png",
"/index.html.gz",
"/js/index.b02584.bundle.js.gz",
"/js/node_vendors.b02584.bundle.js.gz",
"/js/index.1b8c7b.bundle.js.gz",
"/js/node_vendors.1b8c7b.bundle.js.gz",
""
};
const uint8_t * resource_map_start[] = {
_index_1ab179394339385e0a02_css_gz_start,
_favicon_32x32_png_start,
_index_html_gz_start,
_index_b02584_bundle_js_gz_start,
_node_vendors_b02584_bundle_js_gz_start
_index_1b8c7b_bundle_js_gz_start,
_node_vendors_1b8c7b_bundle_js_gz_start
};
const uint8_t * resource_map_end[] = {
_index_1ab179394339385e0a02_css_gz_end,
_favicon_32x32_png_end,
_index_html_gz_end,
_index_b02584_bundle_js_gz_end,
_node_vendors_b02584_bundle_js_gz_end
_index_1b8c7b_bundle_js_gz_end,
_node_vendors_1b8c7b_bundle_js_gz_end
};

View File

@@ -1,6 +1,6 @@
/***********************************
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.1b8c7b.bundle.js.gz,dist/js/node_vendors.1b8c7b.bundle.js.gz
***********************************/
#pragma once
#include <inttypes.h>

View File

@@ -233,8 +233,8 @@ void register_default_string_val(const char * key, const char * value){
char * existing =(char *)config_alloc_get(NVS_TYPE_STR,key );
ESP_LOGD(TAG,"Register default called with: %s= %s",key,value );
if(!existing) {
ESP_LOGI(TAG,"Registering default value for key %s, value %s",key,value );
config_set_default(NVS_TYPE_STR, key,value, 0);
ESP_LOGI(TAG,"Registering default value for key %s, value %s", key, value );
config_set_default(NVS_TYPE_STR, key, value, 0);
}
else {
ESP_LOGD(TAG,"Value found for %s: %s",key,existing );

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

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

BIN
server_certs/r2m01.cer.33 Normal file

Binary file not shown.

View File

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