From d4576bbdd43c20b12b6335f20a5169431c540fd7 Mon Sep 17 00:00:00 2001 From: Sebastien Date: Fri, 21 Feb 2020 15:16:54 -0500 Subject: [PATCH] httpd implementation - wip --- .cproject | 232 +++++++++--------- .gitmodules | 3 + .project | 6 + .pydevproject | 5 + .settings/language.settings.xml | 8 +- .settings/org.eclipse.cdt.core.prefs | 22 +- Makefile | 8 +- components/codecs/component.mk | 2 +- components/config/config.c | 4 +- components/config/config.h | 2 +- esp-dsp => components/esp-dsp | 0 components/raop/component.mk | 2 + components/services/messaging.c | 149 ++++++++--- components/services/messaging.h | 23 +- components/services/services.c | 2 + components/squeezelite-ota/squeezelite-ota.c | 44 ++-- components/squeezelite-ota/squeezelite-ota.h | 2 - components/telnet/telnet.c | 25 +- components/wifi-manager/code.js | 1 + .../wifi-manager/http_server_handlers.c | 2 +- components/wifi-manager/wifi_manager.c | 23 +- components/wifi-manager/wifi_manager.h | 14 +- eclipse_make_wrapper.py | 112 +++++++++ main/esp_app_main.c | 4 +- main/platform_esp32.h | 19 ++ 25 files changed, 493 insertions(+), 221 deletions(-) create mode 100644 .pydevproject rename esp-dsp => components/esp-dsp (100%) create mode 100644 eclipse_make_wrapper.py diff --git a/.cproject b/.cproject index be379242..22fe7e14 100644 --- a/.cproject +++ b/.cproject @@ -203,7 +203,7 @@ - + @@ -225,57 +225,33 @@ - + - + @@ -297,21 +287,15 @@ - + - - - - - - - + - + @@ -329,47 +313,37 @@ - + - + - + - + @@ -493,6 +481,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -511,12 +559,6 @@ - - - - - - @@ -535,48 +577,24 @@ - - - - - - - - - - - - - - - - - - - - - - - - @@ -607,12 +625,6 @@ - - - - - - diff --git a/.gitmodules b/.gitmodules index 9f498e78..cf487bdd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,6 @@ [submodule "esp-dsp"] path = esp-dsp url = https://github.com/philippe44/esp-dsp +[submodule "components/esp-dsp"] + path = components/esp-dsp + url = https://github.com/philippe44/esp-dsp.git diff --git a/.project b/.project index 18d4dbf1..28fa00fd 100644 --- a/.project +++ b/.project @@ -6,6 +6,11 @@ esp-idf + + org.python.pydev.PyDevBuilder + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder clean,full,incremental, @@ -24,5 +29,6 @@ org.eclipse.cdt.core.ccnature org.eclipse.cdt.managedbuilder.core.managedBuildNature org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + org.python.pydev.pythonNature diff --git a/.pydevproject b/.pydevproject new file mode 100644 index 00000000..2b045655 --- /dev/null +++ b/.pydevproject @@ -0,0 +1,5 @@ + + + Default + python interpreter + diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml index 5c545a49..0f39020e 100644 --- a/.settings/language.settings.xml +++ b/.settings/language.settings.xml @@ -57,7 +57,7 @@ - + @@ -73,7 +73,7 @@ - + @@ -81,9 +81,9 @@ - + - + diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs index 7a6fc1e3..bba7e926 100644 --- a/.settings/org.eclipse.cdt.core.prefs +++ b/.settings/org.eclipse.cdt.core.prefs @@ -24,6 +24,26 @@ environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/PATH/op environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/PATH/value=C\:/msys2/opt/xtensa-esp32-elf/bin;C\:/jdk-12.0.2/bin/server;C\:/jdk-12.0.2/bin;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;C\:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C\:\\Program Files\\NVIDIA Corporation\\NVIDIA NvDLISR;C\:\\jdk-12.0.2\\bin;C\:\\Program Files\\PuTTY\\;C\:\\Program Files (x86)\\HP\\IdrsOCR_15.2.10.1114\\;C\:\\eclipse environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/append=true environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1476804786/appendContributed=true +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/BATCH_BUILD/delimiter=\: +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/BATCH_BUILD/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/BATCH_BUILD/value=1 +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/EXTRA_CPPFLAGS/delimiter=; +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/EXTRA_CPPFLAGS/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/EXTRA_CPPFLAGS/value=-DRECOVERY_APPLICATION\=0 +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/IDF_PATH/delimiter=\: +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/IDF_PATH/operation=replace +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/IDF_PATH/value=c\:/msys32/opt/esp-idf +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/PATH/delimiter=\: +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/PATH/operation=replace +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/PATH/value=c\:\\msys32\\opt\\openocd-esp32\\bin;c\:\\msys32\\opt\\xtensa-esp32-elf\\bin\\;c\:\\msys32\\mingw32\\bin;C\:\\msys32\\usr\\bin;c\:\\Python27;C\:\\msys32\\usr\\bin\\vendor_perl;C\:\\msys32\\usr\\bin\\core_perl +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/PROJECT_NAME/delimiter=\: +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/PROJECT_NAME/operation=replace +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/PROJECT_NAME/value=squeezelite +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/PROJECT_VER/delimiter=\: +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/PROJECT_VER/operation=append +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/PROJECT_VER/value=custom +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/append=true +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.1876142873/appendContributed=true environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/BATCH_BUILD/delimiter=\: environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/BATCH_BUILD/operation=append environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291.395881736/BATCH_BUILD/value=1 @@ -48,7 +68,7 @@ environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.16039962 environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/BATCH_BUILD/operation=append environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/BATCH_BUILD/value=1 environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/EXTRA_CPPFLAGS/delimiter=; -environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/EXTRA_CPPFLAGS/operation=replace +environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/EXTRA_CPPFLAGS/operation=append environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/EXTRA_CPPFLAGS/value=-DRECOVERY_APPLICATION\=1 environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/IDF_PATH/delimiter=\: environment/project/cdt.managedbuild.toolchain.gnu.cross.base.293933348.1603996291/IDF_PATH/operation=replace diff --git a/Makefile b/Makefile index 9af345d6..1886763a 100644 --- a/Makefile +++ b/Makefile @@ -10,12 +10,12 @@ #recovery: PROJECT_NAME:=recovery.$(PROJECT_CONFIG_TARGET) -#recovery: CPPFLAGS+=-DRECOVERY_APPLICATION=1 +#recovery: EXTRA_CPPFLAGS+=-DRECOVERY_APPLICATION=1 PROJECT_NAME?=squeezelite -CPPFLAGS+= -Wno-error=maybe-uninitialized \ - -I$(PROJECT_PATH)/main -EXTRA_COMPONENT_DIRS := esp-dsp +EXTRA_CPPFLAGS+= -Wno-error=maybe-uninitialized \ + -I$(PROJECT_PATH)/main + include $(IDF_PATH)/make/project.mk # for future gcc version, this could be needed: CPPFLAGS+= -Wno-error=format-overflow -Wno-error=stringop-truncation diff --git a/components/codecs/component.mk b/components/codecs/component.mk index 99e87521..fb83f6be 100644 --- a/components/codecs/component.mk +++ b/components/codecs/component.mk @@ -21,6 +21,6 @@ COMPONENT_ADD_LDFLAGS=-l$(COMPONENT_NAME) \ #$(COMPONENT_PATH)/lib/libesp-tremor.a #$(COMPONENT_PATH)/lib/libesp-ogg-container.a - +COMPONENT_ADD_INCLUDEDIRS := /inc diff --git a/components/config/config.c b/components/config/config.c index def9c9d2..34d2839a 100644 --- a/components/config/config.c +++ b/components/config/config.c @@ -71,7 +71,7 @@ void config_set_entry_changed_flag(cJSON * entry, cJSON_bool flag); #if RECOVERY_APPLICATION==0 static void * malloc_fn(size_t sz){ - void * ptr = heap_caps_malloc(sz, MALLOC_CAP_SPIRAM); + void * ptr = heap_caps_malloc(sz, MALLOC_CAP_SPIRAM |MALLOC_CAP_8BIT); if(ptr==NULL){ ESP_LOGE(TAG,"malloc_fn: unable to allocate memory!"); } @@ -681,7 +681,7 @@ char * config_alloc_get_json(bool bFormatted){ config_unlock(); return json_buffer; } -esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, void * value){ +esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, const void * value){ esp_err_t result = ESP_OK; if(!config_lock(LOCK_MAX_WAIT/portTICK_PERIOD_MS)){ ESP_LOGE(TAG, "Unable to lock config after %d ms",LOCK_MAX_WAIT); diff --git a/components/config/config.h b/components/config/config.h index b6c192ce..70210499 100644 --- a/components/config/config.h +++ b/components/config/config.h @@ -39,6 +39,6 @@ void config_set_default(nvs_type_t type, const char *key, void * default_value, void * config_alloc_get(nvs_type_t nvs_type, const char *key) ; bool wait_for_commit(); char * config_alloc_get_json(bool bFormatted); -esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, void * value); +esp_err_t config_set_value(nvs_type_t nvs_type, const char *key, const void * value); nvs_type_t config_get_item_type(cJSON * entry); void * config_safe_alloc_get_entry_value(nvs_type_t nvs_type, cJSON * entry); diff --git a/esp-dsp b/components/esp-dsp similarity index 100% rename from esp-dsp rename to components/esp-dsp diff --git a/components/raop/component.mk b/components/raop/component.mk index 55f53715..93f7da76 100644 --- a/components/raop/component.mk +++ b/components/raop/component.mk @@ -11,3 +11,5 @@ CFLAGS += -fstack-usage\ -I$(PROJECT_PATH)/components/tools \ -I$(PROJECT_PATH)/components/codecs/inc/alac \ -I$(PROJECT_PATH)/main/ +COMPONENT_ADD_INCLUDEDIRS := . +COMPONENT_SRCDIRS := . \ No newline at end of file diff --git a/components/services/messaging.c b/components/services/messaging.c index 8144b1eb..047a18a0 100644 --- a/components/services/messaging.c +++ b/components/services/messaging.c @@ -19,56 +19,107 @@ */ const static char tag[] = "messaging"; - +typedef struct { + struct messaging_list_t * next; + char * subscriber_name; + size_t max_count; + RingbufHandle_t buf_handle; +} messaging_list_t; static messaging_list_t top; + + +messaging_list_t * get_struct_ptr(messaging_handle_t handle){ + return (messaging_list_t *)handle; +} +messaging_handle_t get_handle_ptr(messaging_list_t * handle){ + return (messaging_handle_t )handle; +} RingbufHandle_t messaging_create_ring_buffer(uint8_t max_count){ RingbufHandle_t buf_handle = NULL; - StaticRingbuffer_t *buffer_struct = (StaticRingbuffer_t *)heap_caps_malloc(sizeof(StaticRingbuffer_t), MALLOC_CAP_SPIRAM); + StaticRingbuffer_t *buffer_struct = malloc(sizeof(StaticRingbuffer_t)); if (buffer_struct != NULL) { size_t buf_size = (size_t )(sizeof(single_message_t)+8)*(size_t )(max_count>0?max_count:5); // no-split buffer requires an additional 8 bytes - uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(buf_size, MALLOC_CAP_SPIRAM); + uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(buf_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (buffer_storage== NULL) { - ESP_LOGE(tag,"Failed to allocate memory for messaging ring buffer !"); + ESP_LOGE(tag,"buff alloc failed"); } else { buf_handle = xRingbufferCreateStatic(buf_size, RINGBUF_TYPE_NOSPLIT, buffer_storage, buffer_struct); - if (buf_handle == NULL) { - ESP_LOGE(tag,"Failed to create messaging ring buffer !"); - } } } else { - ESP_LOGE(tag,"Failed to create ring buffer for messaging!"); + ESP_LOGE(tag,"ringbuf alloc failed"); } return buf_handle; } +void messaging_fill_messages(messaging_list_t * target_subscriber){ + single_message_t * message=NULL; + UBaseType_t uxItemsWaiting; -RingbufHandle_t messaging_register_subscriber(uint8_t max_count, char * name){ + vRingbufferGetInfo(top.buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting); + for(size_t i=0;inext){ - cur = cur->next; + cur = get_struct_ptr(cur->next); } - cur->next=heap_caps_malloc(sizeof(messaging_list_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + cur->next=heap_caps_malloc(sizeof(messaging_list_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if(!cur->next){ - ESP_LOGE(tag,"Failed to allocate messaging subscriber entry!"); + ESP_LOGE(tag,"subscriber alloc failed"); return NULL; } memset(cur->next,0x00,sizeof(messaging_list_t)); - cur = cur->next; + cur = get_struct_ptr(cur->next); + cur->max_count=max_count; + cur->subscriber_name=strdup(name); cur->buf_handle = messaging_create_ring_buffer(max_count); - strncpy(cur->subscriber_name,name,sizeof(cur->subscriber_name)); - + if(cur->buf_handle){ + messaging_fill_messages(cur); + } return cur->buf_handle; } -esp_err_t messaging_service_init(){ +void messaging_service_init(){ + size_t max_count=15; top.buf_handle = messaging_create_ring_buffer(max_count); if(!top.buf_handle){ ESP_LOGE(tag, "messaging service init failed."); } - strncpy(top.subscriber_name,"messaging"); - return (top.buf_handle!=NULL); + else { + top.max_count = max_count; + top.subscriber_name = strdup("messaging"); + } + return; } +const char * messaging_get_type_desc(messaging_types msg_type){ + switch (msg_type) { + CASE_TO_STR(MESSAGING_INFO); + CASE_TO_STR(MESSAGING_WARNING); + CASE_TO_STR(MESSAGING_ERROR); + default: + return "Unknown"; + break; + } +} +const char * messaging_get_class_desc(messaging_classes msg_class){ + switch (msg_class) { + CASE_TO_STR(MESSAGING_CLASS_OTA); + CASE_TO_STR(MESSAGING_CLASS_SYSTEM); + default: + return "Unknown"; + break; + } +} cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle){ single_message_t * message=NULL; @@ -81,12 +132,13 @@ cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle){ message = (single_message_t *)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(50)); //Check received data if (message== NULL) { - ESP_LOGE(tag,"Failed to receive message from buffer!"); + ESP_LOGE(tag,"received null ptr"); } else { json_message = cJSON_CreateObject(); cJSON_AddStringToObject(json_message, "message", message->message); - cJSON_AddStringToObject(json_message, "type", message->message); + cJSON_AddStringToObject(json_message, "type", messaging_get_type_desc(message->type)); + cJSON_AddStringToObject(json_message, "class", messaging_get_class_desc(message->msg_class)); cJSON_AddNumberToObject(json_message,"sent_time",message->sent_time); cJSON_AddNumberToObject(json_message,"current_time",esp_timer_get_time() / 1000); cJSON_AddItemToArray(json_messages,json_message); @@ -95,19 +147,55 @@ cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle){ } return json_messages; } - -void messaging_release_message(RingbufHandle_t buf_handle, single_message_t * message){ - +single_message_t * messaging_retrieve_message(RingbufHandle_t buf_handle){ + single_message_t * message=NULL; + single_message_t * message_copy=NULL; + size_t item_size; + UBaseType_t uxItemsWaiting; + vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting); + if(uxItemsWaiting>0){ + message = (single_message_t *)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(50)); + if(item_size!=sizeof(single_message_t)){ + ESP_LOGE(tag,"Invalid message length!"); + } + else { + message_copy = heap_caps_malloc(item_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if(message_copy){ + memcpy(message_copy,message,item_size); + } + } + vRingbufferReturnItem(buf_handle, (void *)message); + } + return message_copy; } -esp_err_t messageing_post_to_queue(messaging_list_t * subscriber, single_message_t * message){ - UBaseType_t res = xRingbufferSend(subscriber->buf_handle, message, sizeof(message), pdMS_TO_TICKS(1000)); + +esp_err_t messaging_post_to_queue(messaging_handle_t subscriber_handle, single_message_t * message, size_t message_size){ + UBaseType_t uxItemsWaiting=0; + size_t item_size=0; + messaging_list_t * subscriber=get_struct_ptr(subscriber_handle); + if(!subscriber->buf_handle){ + ESP_LOGE(tag,"post failed: null buffer for %s", str_or_unknown(subscriber->subscriber_name)); + return ESP_FAIL; + } + vRingbufferGetInfo(subscriber->buf_handle,NULL,NULL,NULL,NULL,&uxItemsWaiting); + if(uxItemsWaiting>=subscriber->max_count){ + ESP_LOGW(tag,"messaged dropped for %s",str_or_unknown(subscriber->subscriber_name)); + single_message_t * dummy = (single_message_t *)xRingbufferReceive(subscriber->buf_handle, &item_size, pdMS_TO_TICKS(50)); + if (dummy== NULL) { + ESP_LOGE(tag,"receive from buffer failed"); + } + else { + vRingbufferReturnItem(subscriber->buf_handle, (void *)dummy); + } + } + UBaseType_t res = xRingbufferSend(subscriber->buf_handle, message, message_size, pdMS_TO_TICKS(1000)); if (res != pdTRUE) { - ESP_LOGE(tag,"Failed to post message to subscriber %s",subscriber->subscriber_name); + ESP_LOGE(tag,"post to %s failed",str_or_unknown(subscriber->subscriber_name)); return ESP_FAIL; } return ESP_OK; } -void messaging_post_message(messaging_types type, char *fmt, ...){ +void messaging_post_message(messaging_types type,messaging_classes msg_class, char *fmt, ...){ single_message_t message={}; messaging_list_t * cur=⊤ va_list va; @@ -115,10 +203,11 @@ void messaging_post_message(messaging_types type, char *fmt, ...){ vsnprintf(message.message, sizeof(message.message), fmt, va); va_end(va); message.type = type; + message.msg_class = msg_class; message.sent_time = esp_timer_get_time() / 1000; - while(cur->next){ - messageing_post_to_queue(cur, &message); - cur = cur->next; + while(cur){ + messaging_post_to_queue(get_handle_ptr(cur), &message, sizeof(single_message_t)); + cur = get_struct_ptr(cur->next); } return; diff --git a/components/services/messaging.h b/components/services/messaging.h index 54fb5109..fb0ca0a0 100644 --- a/components/services/messaging.h +++ b/components/services/messaging.h @@ -7,19 +7,24 @@ typedef enum { MESSAGING_WARNING, MESSAGING_ERROR } messaging_types; -typedef struct { - void * next; - char subscriber_name[21]; - RingbufHandle_t buf_handle; -} messaging_list_t; +typedef enum { + MESSAGING_CLASS_OTA, + MESSAGING_CLASS_SYSTEM +} messaging_classes; + +typedef struct messaging_list_t *messaging_handle_t; typedef struct { time_t sent_time; messaging_types type; - char message[101]; + messaging_classes msg_class; + char message[151]; } single_message_t; cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle); -RingbufHandle_t messaging_register_subscriber(uint8_t max_count, char * name); - -void messaging_post_message(messaging_types type, char * fmt, ...); +messaging_handle_t messaging_register_subscriber(uint8_t max_count, char * name); +esp_err_t messaging_post_to_queue(messaging_handle_t subscriber_handle, single_message_t * message, size_t message_size); +void messaging_post_message(messaging_types type,messaging_classes msg_class, char * fmt, ...); +cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle); +single_message_t * messaging_retrieve_message(RingbufHandle_t buf_handle); +void messaging_service_init(); diff --git a/components/services/services.c b/components/services/services.c index 193a2b22..f138cd88 100644 --- a/components/services/services.c +++ b/components/services/services.c @@ -16,6 +16,7 @@ #include "monitor.h" #include "globdefs.h" #include "accessors.h" +#include "messaging.h" extern void battery_svc_init(void); extern void monitor_svc_init(void); @@ -52,6 +53,7 @@ void set_power_gpio(int gpio, char *value) { */ void services_init(void) { messaging_service_init(); + messaging_post_message(MESSAGING_INFO,MESSAGING_CLASS_SYSTEM, "Initializing services"); gpio_install_isr_service(0); #ifdef CONFIG_I2C_LOCKED diff --git a/components/squeezelite-ota/squeezelite-ota.c b/components/squeezelite-ota/squeezelite-ota.c index 62b91d7c..37164f24 100644 --- a/components/squeezelite-ota/squeezelite-ota.c +++ b/components/squeezelite-ota/squeezelite-ota.c @@ -83,26 +83,36 @@ void _printMemStats(){ heap_caps_get_free_size(MALLOC_CAP_SPIRAM), heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM)); } -void sendMessaging(messaging_types type,char * fmt, ...){ - va_list args; - va_start(args, fmt); - messaging_post_message(type, fmt, args); - va_end(args); - _printMemStats(); -} -const char * ota_get_status(){ - if(!ota_status.bInitialized) - { - memset(ota_status.status_text, 0x00,sizeof(ota_status.status_text)); - ota_status.bInitialized = true; - } - return ota_status.status_text; -} uint8_t ota_get_pct_complete(){ return ota_status.total_image_len==0?0: (uint8_t)((float)ota_status.actual_image_len/(float)ota_status.total_image_len*100.0f); } +void sendMessaging(messaging_types type,const char * fmt, ...){ + va_list args; + cJSON * msg = cJSON_CreateObject(); + size_t str_len=0; + char * msg_str=NULL; + + va_start(args, fmt); + str_len = vsnprintf(NULL,0,fmt,args); + if(str_len>0){ + msg_str = malloc(str_len); + vsnprintf(msg_str,str_len,fmt,args); + } + va_end(args); + + cJSON_AddStringToObject(msg,"ota_dsc",msg_str); + free(msg_str); + cJSON_AddNumberToObject(msg,"ota_pct", ota_get_pct_complete() ); + char * json_msg = cJSON_PrintUnformatted(msg); + messaging_post_message(type, MESSAGING_CLASS_OTA, json_msg); + free(json_msg); + cJSON_free(msg); + _printMemStats(); +} + + static void __attribute__((noreturn)) task_fatal_error(void) { ESP_LOGE(TAG, "Exiting task due to fatal error..."); @@ -206,7 +216,7 @@ esp_err_t init_config(ota_thread_parms_t * p_ota_thread_parms){ ota_config.skip_cert_common_name_check = false; ota_config.url = strdup(ota_status.current_url); ota_config.max_redirection_count = 3; - ota_write_data = heap_caps_malloc(ota_config.buffer_size+1 , MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + ota_write_data = heap_caps_malloc(ota_config.buffer_size+1 , MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); //ota_write_data = malloc(ota_config.buffer_size+1); if(ota_write_data== NULL){ ESP_LOGE(TAG,"Error allocating the ota buffer"); @@ -324,7 +334,7 @@ static esp_err_t _http_handle_response_code(esp_http_client_handle_t http_client } ESP_LOGD(TAG, "Redirection done, checking if we need to read the data. "); if (process_again(status_code)) { - char * local_buff = heap_caps_malloc(ota_config.buffer_size+1, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + char * local_buff = heap_caps_malloc(ota_config.buffer_size+1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); //char * local_buff = malloc(ota_config.buffer_size+1); if(local_buff==NULL){ ESP_LOGE(TAG,"Failed to allocate internal memory buffer for http processing"); diff --git a/components/squeezelite-ota/squeezelite-ota.h b/components/squeezelite-ota/squeezelite-ota.h index 2ae4dc43..8629404f 100644 --- a/components/squeezelite-ota/squeezelite-ota.h +++ b/components/squeezelite-ota/squeezelite-ota.h @@ -37,7 +37,5 @@ #define OTA_TASK_PRIOTITY 6 esp_err_t start_ota(const char * bin_url, char * bin_buffer, uint32_t length); -const char * ota_get_status(); -uint8_t ota_get_pct_complete(); diff --git a/components/telnet/telnet.c b/components/telnet/telnet.c index 552c678e..3b4f900e 100644 --- a/components/telnet/telnet.c +++ b/components/telnet/telnet.c @@ -69,7 +69,7 @@ static ssize_t stdout_write(int fd, const void * data, size_t size); static char *eventToString(telnet_event_type_t type); static void handle_telnet_conn(); static void process_logs( UBaseType_t bytes); - +static bool bMirrorToUART=false; struct telnetUserData { int sockfd; telnet_t *tnHandle; @@ -79,11 +79,14 @@ struct telnetUserData { void init_telnet(){ char *val= get_nvs_value_alloc(NVS_TYPE_STR, "telnet_enable"); - if (!val || strlen(val) == 0 || !strcasestr("YX",val) ) { + if (!val || strlen(val) == 0 || !strcasestr("YXD",val) ) { ESP_LOGI(tag,"Telnet support disabled"); if(val) free(val); return; } + bMirrorToUART = strcasestr("D",val)!=NULL; + + FREE_AND_NULL(val); val=get_nvs_value_alloc(NVS_TYPE_STR, "telnet_block"); if(val){ send_chunk=atol(val); @@ -100,8 +103,8 @@ void init_telnet(){ vSemaphoreCreateBinary( xSemaphore ); // Redirect the output to our telnet handler as soon as possible - StaticRingbuffer_t *buffer_struct = (StaticRingbuffer_t *)heap_caps_malloc(sizeof(StaticRingbuffer_t), MALLOC_CAP_SPIRAM); - uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(sizeof(uint8_t)*log_buf_size, MALLOC_CAP_SPIRAM); + StaticRingbuffer_t *buffer_struct = (StaticRingbuffer_t *)heap_caps_malloc(sizeof(StaticRingbuffer_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(sizeof(uint8_t)*log_buf_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); buf_handle = xRingbufferCreateStatic(log_buf_size, RINGBUF_TYPE_BYTEBUF, buffer_storage, buffer_struct); if (buf_handle == NULL) { ESP_LOGE(tag,"Failed to create ring buffer for telnet!"); @@ -117,7 +120,9 @@ void init_telnet(){ .close = &stdout_close, .read = &stdout_read, }; - uart_fd=open("/dev/uart/0", O_RDWR); + if(bMirrorToUART){ + uart_fd=open("/dev/uart/0", O_RDWR); + } ESP_ERROR_CHECK(esp_vfs_register("/dev/pkspstdout", &vfs, NULL)); freopen("/dev/pkspstdout", "w", stdout); freopen("/dev/pkspstdout", "w", stderr); @@ -125,7 +130,7 @@ void init_telnet(){ } void start_telnet(void * pvParameter){ static bool isStarted=false; - StaticTask_t *xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + StaticTask_t *xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); StackType_t *xStack = malloc(TELNET_STACK_SIZE); if(!isStarted && bIsEnabled) { @@ -228,7 +233,9 @@ void process_received_data(const char * buffer, size_t size){ command[size]='\0'; if(command[0]!='\r' && command[0]!='\n'){ // echo the command buffer out to uart and run - write(uart_fd, command, size); + if(bMirrorToUART){ + write(uart_fd, command, size); + } run_command((char *)command); } free(command); @@ -317,7 +324,7 @@ static void handle_telnet_conn() { struct telnetUserData *pTelnetUserData = (struct telnetUserData *)malloc(sizeof(struct telnetUserData)); tnHandle = telnet_init(my_telopts, handle_telnet_events, 0, pTelnetUserData); - pTelnetUserData->rxbuf = (char *) heap_caps_malloc(TELNET_RX_BUF, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + pTelnetUserData->rxbuf = (char *) heap_caps_malloc(TELNET_RX_BUF, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); pTelnetUserData->tnHandle = tnHandle; pTelnetUserData->sockfd = partnerSocket; @@ -374,7 +381,7 @@ static ssize_t stdout_write(int fd, const void * data, size_t size) { // We could not obtain the semaphore and can therefore not access // the shared resource safely. } - return write(uart_fd, data, size); + return bMirrorToUART?write(uart_fd, data, size):true; } static ssize_t stdout_read(int fd, void* data, size_t size) { diff --git a/components/wifi-manager/code.js b/components/wifi-manager/code.js index 8cf4f0d5..9228e1fe 100644 --- a/components/wifi-manager/code.js +++ b/components/wifi-manager/code.js @@ -648,6 +648,7 @@ function refreshAPHTML(data){ function getMessages() { $.getJSON("/messages.json", function(data) { data.forEach(function(msg) { + message: "{"ota_dsc":"Erasing flash complete","ota_pct":0}" }); }) diff --git a/components/wifi-manager/http_server_handlers.c b/components/wifi-manager/http_server_handlers.c index 25e9279f..b983cf47 100644 --- a/components/wifi-manager/http_server_handlers.c +++ b/components/wifi-manager/http_server_handlers.c @@ -50,9 +50,9 @@ function to process requests, decode URLs, serve files, etc. etc. #include "esp_vfs.h" #include "lwip/ip_addr.h" #include "messaging.h" +#include "platform_esp32.h" #define HTTP_STACK_SIZE (5*1024) -#define FREE_AND_NULL(p) if(p!=NULL){ free(p); p=NULL;} const char str_na[]="N/A"; #define STR_OR_NA(s) s?s:str_na /* @brief tag used for ESP serial console messages */ diff --git a/components/wifi-manager/wifi_manager.c b/components/wifi-manager/wifi_manager.c index 4fabda05..084ff142 100644 --- a/components/wifi-manager/wifi_manager.c +++ b/components/wifi-manager/wifi_manager.c @@ -75,7 +75,7 @@ Contains the freeRTOS task and all necessary support #endif #define STR_OR_BLANK(p) p==NULL?"":p -#define FREE_AND_NULL(p) if(p!=NULL){ free(p); p=NULL;} + /* objects used to manipulate the main queue of events */ QueueHandle_t wifi_manager_queue; SemaphoreHandle_t wifi_manager_json_mutex = NULL; @@ -89,7 +89,7 @@ char *ip_info_json = NULL; char * release_url=NULL; cJSON * ip_info_cjson=NULL; wifi_config_t* wifi_manager_config_sta = NULL; -static update_reason_code_t last_update_reason_code=0; + static int32_t total_connected_time=0; static int64_t last_connected=0; @@ -208,9 +208,6 @@ bool isGroupBitSet(uint8_t bit){ EventBits_t uxBits= xEventGroupGetBits(wifi_manager_event_group); return (uxBits & bit); } -void wifi_manager_refresh_ota_json(){ - wifi_manager_send_message(EVENT_REFRESH_OTA, NULL); -} void wifi_manager_scan_async(){ wifi_manager_send_message(ORDER_START_WIFI_SCAN, NULL); @@ -455,8 +452,6 @@ cJSON * wifi_manager_get_basic_info(cJSON **old){ cJSON_AddItemToObject(root, "version", cJSON_CreateString(desc->version)); if(release_url !=NULL) cJSON_AddItemToObject(root, "release_url", cJSON_CreateString(release_url)); cJSON_AddNumberToObject(root,"recovery", RECOVERY_APPLICATION ); - cJSON_AddItemToObject(root, "ota_dsc", cJSON_CreateString(ota_get_status())); - cJSON_AddNumberToObject(root,"ota_pct", ota_get_pct_complete() ); cJSON_AddItemToObject(root, "Jack", cJSON_CreateString(jack_inserted_svc() ? "1" : "0")); cJSON_AddNumberToObject(root,"Voltage", battery_value_svc()); cJSON_AddNumberToObject(root,"disconnect_count", num_disconnect ); @@ -485,12 +480,6 @@ void wifi_manager_generate_ip_info_json(update_reason_code_t update_reason_code) wifi_config_t *config = wifi_manager_get_wifi_sta_config(); ip_info_cjson = wifi_manager_get_basic_info(&ip_info_cjson); - if(update_reason_code == UPDATE_OTA) { - update_reason_code = last_update_reason_code; - } - else { - last_update_reason_code = update_reason_code; - } cJSON_AddNumberToObject(ip_info_cjson, "urc", update_reason_code); if(config){ cJSON_AddItemToObject(ip_info_cjson, "ssid", cJSON_CreateString((char *)config->sta.ssid)); @@ -1144,12 +1133,6 @@ void wifi_manager( void * pvParameters ){ ESP_LOGD(TAG, "Done Invoking SCAN DONE callback"); } break; - case EVENT_REFRESH_OTA: - if(wifi_manager_lock_json_buffer( portMAX_DELAY )){ - wifi_manager_generate_ip_info_json( UPDATE_OTA ); - wifi_manager_unlock_json_buffer(); - } - break; case ORDER_START_WIFI_SCAN: ESP_LOGD(TAG, "MESSAGE: ORDER_START_WIFI_SCAN"); @@ -1445,7 +1428,7 @@ void wifi_manager( void * pvParameters ){ if(cb_ptr_arr[msg.code]) (*cb_ptr_arr[msg.code])(NULL); break; case UPDATE_CONNECTION_OK: - /* refresh JSON with the new ota data */ + /* refresh JSON */ if(wifi_manager_lock_json_buffer( portMAX_DELAY )){ /* generate the connection info with success */ wifi_manager_generate_ip_info_json( UPDATE_CONNECTION_OK ); diff --git a/components/wifi-manager/wifi_manager.h b/components/wifi-manager/wifi_manager.h index 459a48c2..9aa12da6 100644 --- a/components/wifi-manager/wifi_manager.h +++ b/components/wifi-manager/wifi_manager.h @@ -198,12 +198,11 @@ typedef enum message_code_t { EVENT_STA_DISCONNECTED = 12, EVENT_SCAN_DONE = 13, EVENT_STA_GOT_IP = 14, - EVENT_REFRESH_OTA = 15, - ORDER_RESTART_OTA = 16, - ORDER_RESTART_RECOVERY = 17, - ORDER_RESTART_OTA_URL = 18, - ORDER_RESTART = 19, - MESSAGE_CODE_COUNT = 20 /* important for the callback array */ + ORDER_RESTART_OTA = 15, + ORDER_RESTART_RECOVERY = 16, + ORDER_RESTART_OTA_URL = 17, + ORDER_RESTART = 18, + MESSAGE_CODE_COUNT = 19 /* important for the callback array */ }message_code_t; @@ -226,8 +225,7 @@ typedef enum update_reason_code_t { UPDATE_CONNECTION_OK = 0, UPDATE_FAILED_ATTEMPT = 1, UPDATE_USER_DISCONNECT = 2, - UPDATE_LOST_CONNECTION = 3, - UPDATE_OTA=4 + UPDATE_LOST_CONNECTION = 3 }update_reason_code_t; typedef enum connection_request_made_by_code_t{ diff --git a/eclipse_make_wrapper.py b/eclipse_make_wrapper.py new file mode 100644 index 00000000..f18048e8 --- /dev/null +++ b/eclipse_make_wrapper.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +# +# Wrapper to run make and preprocess any paths in the output from MSYS Unix-style paths +# to Windows paths, for Eclipse +from __future__ import print_function, division +import sys +import subprocess +import os.path +import os +import re +import glob +from test import test_cmd_line + +#UNIX_PATH_RE = re.compile(r'(([a-zA-Z]{1}[:]{1}){0,1}[/\\][^\s\'\"\t\[\(]+)+') +UNIX_PATH_RE = re.compile(r'(([a-zA-Z]{1}[:]{1}){0,1}[/\\][^\s\'\"\t\[\(]+(?![^\\/]*$)[/\\]?)') +INCLUDE_PATH_RE = re.compile(r'-I[\s"]{0,}(.+?)["]{0,}(?=\s-\S)') +INCLUDE_PATH_ADJ_RE = re.compile(r'^([/]opt[/]esp-idf[/]){1}(.*)') +INCLUDE_PATH_ADJ2_RE = re.compile(r'^([/]c[/]){1}(.*)') + +paths = {} +names = [] +idf_path= os.environ.get('IDF_PATH').replace("/", "\\") +cwd_path= os.environ.get('CWD') +pwd_path= os.environ.get('PWD') + +def check_path(path): + try: + return paths[path] + except KeyError: + pass + paths[path] = path + winpath =path + if not os.path.exists(winpath): + # cache as failed, replace with success if it works + if re.match(INCLUDE_PATH_ADJ2_RE, path) is not None: + winpath = INCLUDE_PATH_ADJ2_RE.sub(r'c:/\2',path) #replace /c/ + try: + winpath = subprocess.check_output(["cygpath", "-w", winpath]).strip() + except subprocess.CalledProcessError: + return path # something went wrong running cygpath, assume this is not a path! + if not os.path.exists(winpath): + if not os.path.exists(winpath): + winpath=idf_path + '\\' + re.sub(r'^[/\\]opt[/\\](esp-idf[/\\]){0,}', '', path, 1) + try: + winpath = subprocess.check_output(["cygpath", "-w", winpath]).strip() + except subprocess.CalledProcessError: + return path # something went wrong running cygpath, assume this is not a path! + if not os.path.exists(winpath): + return path # not actually a valid path + + winpath = winpath.replace("/", "\\") # make consistent with forward-slashes used elsewhere + paths[path] = winpath + + + #print("In path: {0}, out path: {1}".format(path,winpath) ) + return winpath +def fix_paths(filename): + if re.match(r'.*[\\](.*$)',filename) is not None: + filename = re.findall(r'.*[\\](.*$)',filename)[0].replace("\\", "/") + + return filename.rstrip() + +def print_paths(path_list, file_name, source_file): + + new_path_list = list(set(path_list)) + new_path_list.sort() + last_n = '' + cmd_line='xtensa-esp32-elf-gcc ' + for n in new_path_list: + if re.match(INCLUDE_PATH_ADJ_RE, n) is not None: + n = INCLUDE_PATH_ADJ_RE.sub(idf_path+r"\2",n ) + if re.match(INCLUDE_PATH_ADJ2_RE, n) is not None: + n = INCLUDE_PATH_ADJ2_RE.sub(r'c:/\2',n) + if last_n != n: + cmd_line = cmd_line + ' -I ' + n.rstrip() + last_n = n + if source_file: + cmd_line = cmd_line + ' -c ' + fix_paths(source_file) + cmd_line = cmd_line + ' -o ' + fix_paths(file_name) + print(cmd_line) +def extract_includes(): + + for filename in [y for x in os.walk('build') for y in glob.glob(os.path.join(x[0], '*.d'))]: + lines = [] + source='' + with open(filename) as file_in: + for line in file_in: + if re.match(r'\S*(?=/[^/]*\.[h][p]?)',line) is not None: + lines.extend(re.findall(r'\S*(?=/[^/]*\.[h][p]?)/',line)) + if re.match(r'\S*(?=\.[cC][pP]{0,})[^\\\s]*',line) is not None: + source = re.findall(r'\S*(?=\.[cC][pP]{0,})[^\\\s]*',line)[0] + + print_paths(lines,filename,source ) + +def main(): + cwd_path=check_path(os.getcwd()) + os.environ['CWD']= cwd_path + os.environ['PWD']= cwd_path + idf_path= os.environ.get('IDF_PATH').replace("/", "\\") + cwd_path= os.environ.get('CWD') + pwd_path= os.environ.get('PWD') + print('Running custom script make in {}, IDF_PATH={}, CWD={}, PWD={}'.format(cwd_path,idf_path,cwd_path,pwd_path)) + + make = subprocess.Popen(["make"] + sys.argv[1:] + ["BATCH_BUILD=1"], stdout=subprocess.PIPE) + for line in iter(make.stdout.readline, ''): + line = re.sub(UNIX_PATH_RE, lambda m: check_path(m.group(0)), line) + names.extend(INCLUDE_PATH_RE.findall(line)) + print(line.rstrip()) + sys.exit(make.wait()) + +if __name__ == "__main__": + main() diff --git a/main/esp_app_main.c b/main/esp_app_main.c index 3d2f35cb..b9db45bb 100644 --- a/main/esp_app_main.c +++ b/main/esp_app_main.c @@ -51,7 +51,7 @@ static const char certs_namespace[] = "certificates"; static const char certs_key[] = "blob"; static const char certs_version[] = "version"; - +const char unknown_string_placeholder[] = "unknown"; EventGroupHandle_t wifi_event_group; bool bypass_wifi_manager=false; @@ -69,7 +69,7 @@ extern const uint8_t server_cert_pem_end[] asm("_binary_github_pem_end"); // as an exception _init function don't need include extern void services_init(void); extern void display_init(char *welcome); - +const char * str_or_unknown(const char * str) { return (str?str:unknown_string_placeholder); } /* brief this is an exemple of a callback that you can setup in your own app to get notified of wifi manager event */ void cb_connection_got_ip(void *pvParameter){ ESP_LOGI(TAG, "I have a connection!"); diff --git a/main/platform_esp32.h b/main/platform_esp32.h index 0291154c..545086a0 100644 --- a/main/platform_esp32.h +++ b/main/platform_esp32.h @@ -37,3 +37,22 @@ typedef enum { ERROR } message_severity_t; extern void set_status_message(message_severity_t severity, const char * message); +#ifndef STR_OR_ALT +#define STR_OR_ALT(str,alt) (str?str:alt) +#endif + +extern const char unknown_string_placeholder[]; +extern const char * str_or_unknown(const char * str); + +#ifndef FREE_AND_NULL +#define FREE_AND_NULL(x) if(x) { free(x); x=NULL; } +#endif +#ifndef QUOTE +#define QUOTE(name) #name +#endif +#ifndef STR +#define STR(macro) QUOTE(macro) +#endif +#ifndef CASE_TO_STR +#define CASE_TO_STR(x) case x: return STR(x); break; +#endif