mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-07 20:17:04 +03:00
taming the memory monster
This commit is contained in:
2
Makefile
2
Makefile
@@ -13,7 +13,7 @@
|
|||||||
#recovery: EXTRA_CPPFLAGS+=-DRECOVERY_APPLICATION=1
|
#recovery: EXTRA_CPPFLAGS+=-DRECOVERY_APPLICATION=1
|
||||||
|
|
||||||
PROJECT_NAME?=squeezelite
|
PROJECT_NAME?=squeezelite
|
||||||
EXTRA_CPPFLAGS+= -I$(PROJECT_PATH)/main
|
EXTRA_CPPFLAGS+= -I$(PROJECT_PATH)/main -I$(IDF_PATH)/components/esp_http_server/src -I$(IDF_PATH)/components/esp_http_server/src/port/esp32 -I$(IDF_PATH)/components/esp_http_server/src/util
|
||||||
#/-Wno-error=maybe-uninitialized
|
#/-Wno-error=maybe-uninitialized
|
||||||
include $(IDF_PATH)/make/project.mk
|
include $(IDF_PATH)/make/project.mk
|
||||||
|
|
||||||
|
|||||||
@@ -106,8 +106,7 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
|
|||||||
if(!wait_for_commit()){
|
if(!wait_for_commit()){
|
||||||
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
||||||
}
|
}
|
||||||
ESP_LOGW(TAG, "Restarting after tx complete");
|
vTaskDelay(750/ portTICK_PERIOD_MS);
|
||||||
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
|
|
||||||
esp_restart();
|
esp_restart();
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@@ -117,8 +116,7 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
|
|||||||
if(!wait_for_commit()){
|
if(!wait_for_commit()){
|
||||||
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
||||||
}
|
}
|
||||||
ESP_LOGW(TAG, "Restarting after tx complete");
|
vTaskDelay(750/ portTICK_PERIOD_MS);
|
||||||
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
|
|
||||||
esp_restart();
|
esp_restart();
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
@@ -166,8 +164,7 @@ esp_err_t guided_boot(esp_partition_subtype_t partition_subtype)
|
|||||||
if(!wait_for_commit()){
|
if(!wait_for_commit()){
|
||||||
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
||||||
}
|
}
|
||||||
ESP_LOGW(TAG, "Restarting after tx complete");
|
vTaskDelay(750/ portTICK_PERIOD_MS);
|
||||||
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
|
|
||||||
esp_restart();
|
esp_restart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,8 +178,7 @@ static int restart(int argc, char **argv)
|
|||||||
if(!wait_for_commit()){
|
if(!wait_for_commit()){
|
||||||
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
||||||
}
|
}
|
||||||
ESP_LOGW(TAG, "Restarting after tx complete");
|
vTaskDelay(750/ portTICK_PERIOD_MS);
|
||||||
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
|
|
||||||
esp_restart();
|
esp_restart();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -193,9 +189,7 @@ void simple_restart()
|
|||||||
if(!wait_for_commit()){
|
if(!wait_for_commit()){
|
||||||
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
ESP_LOGW(TAG,"Unable to commit configuration. ");
|
||||||
}
|
}
|
||||||
|
vTaskDelay(750/ portTICK_PERIOD_MS);
|
||||||
ESP_LOGW(TAG, "Restarting after tx complete");
|
|
||||||
uart_wait_tx_done(UART_NUM_1, 500 / portTICK_RATE_MS);
|
|
||||||
esp_restart();
|
esp_restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ typedef struct {
|
|||||||
RingbufHandle_t buf_handle;
|
RingbufHandle_t buf_handle;
|
||||||
} messaging_list_t;
|
} messaging_list_t;
|
||||||
static messaging_list_t top;
|
static messaging_list_t top;
|
||||||
|
#define MSG_LENGTH_AVG 201
|
||||||
|
|
||||||
messaging_list_t * get_struct_ptr(messaging_handle_t handle){
|
messaging_list_t * get_struct_ptr(messaging_handle_t handle){
|
||||||
return (messaging_list_t *)handle;
|
return (messaging_list_t *)handle;
|
||||||
@@ -35,12 +35,14 @@ messaging_list_t * get_struct_ptr(messaging_handle_t handle){
|
|||||||
messaging_handle_t get_handle_ptr(messaging_list_t * handle){
|
messaging_handle_t get_handle_ptr(messaging_list_t * handle){
|
||||||
return (messaging_handle_t )handle;
|
return (messaging_handle_t )handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
RingbufHandle_t messaging_create_ring_buffer(uint8_t max_count){
|
RingbufHandle_t messaging_create_ring_buffer(uint8_t max_count){
|
||||||
RingbufHandle_t buf_handle = NULL;
|
RingbufHandle_t buf_handle = NULL;
|
||||||
StaticRingbuffer_t *buffer_struct = malloc(sizeof(StaticRingbuffer_t));
|
StaticRingbuffer_t *buffer_struct = malloc(sizeof(StaticRingbuffer_t));
|
||||||
if (buffer_struct != NULL) {
|
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
|
size_t buf_size = (size_t )(sizeof(single_message_t)+8+MSG_LENGTH_AVG)*(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 | MALLOC_CAP_8BIT);
|
buf_size = buf_size - (buf_size % 4);
|
||||||
|
uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(buf_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_32BIT);
|
||||||
if (buffer_storage== NULL) {
|
if (buffer_storage== NULL) {
|
||||||
ESP_LOGE(tag,"buff alloc failed");
|
ESP_LOGE(tag,"buff alloc failed");
|
||||||
}
|
}
|
||||||
@@ -62,9 +64,9 @@ void messaging_fill_messages(messaging_list_t * target_subscriber){
|
|||||||
message= messaging_retrieve_message(top.buf_handle);
|
message= messaging_retrieve_message(top.buf_handle);
|
||||||
if(message){
|
if(message){
|
||||||
//re-post to original queue so it is available to future subscribers
|
//re-post to original queue so it is available to future subscribers
|
||||||
messaging_post_to_queue(get_handle_ptr(&top), message, sizeof(single_message_t));
|
messaging_post_to_queue(get_handle_ptr(&top), message, message->msg_size);
|
||||||
// post to new subscriber
|
// post to new subscriber
|
||||||
messaging_post_to_queue(get_handle_ptr(target_subscriber) , message, sizeof(single_message_t));
|
messaging_post_to_queue(get_handle_ptr(target_subscriber) , message, message->msg_size);
|
||||||
FREE_AND_NULL(message);
|
FREE_AND_NULL(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,6 +118,7 @@ const char * messaging_get_class_desc(messaging_classes msg_class){
|
|||||||
switch (msg_class) {
|
switch (msg_class) {
|
||||||
CASE_TO_STR(MESSAGING_CLASS_OTA);
|
CASE_TO_STR(MESSAGING_CLASS_OTA);
|
||||||
CASE_TO_STR(MESSAGING_CLASS_SYSTEM);
|
CASE_TO_STR(MESSAGING_CLASS_SYSTEM);
|
||||||
|
CASE_TO_STR(MESSAGING_CLASS_STATS);
|
||||||
default:
|
default:
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
break;
|
break;
|
||||||
@@ -156,14 +159,9 @@ single_message_t * messaging_retrieve_message(RingbufHandle_t buf_handle){
|
|||||||
vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting);
|
vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting);
|
||||||
if(uxItemsWaiting>0){
|
if(uxItemsWaiting>0){
|
||||||
message = (single_message_t *)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(50));
|
message = (single_message_t *)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(50));
|
||||||
if(item_size!=sizeof(single_message_t)){
|
message_copy = heap_caps_malloc(item_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||||
ESP_LOGE(tag,"Invalid message length!");
|
if(message_copy){
|
||||||
}
|
memcpy(message_copy,message,item_size);
|
||||||
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);
|
vRingbufferReturnItem(buf_handle, (void *)message);
|
||||||
}
|
}
|
||||||
@@ -171,15 +169,22 @@ single_message_t * messaging_retrieve_message(RingbufHandle_t buf_handle){
|
|||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t messaging_post_to_queue(messaging_handle_t subscriber_handle, single_message_t * message, size_t message_size){
|
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;
|
size_t item_size=0;
|
||||||
messaging_list_t * subscriber=get_struct_ptr(subscriber_handle);
|
messaging_list_t * subscriber=get_struct_ptr(subscriber_handle);
|
||||||
if(!subscriber->buf_handle){
|
if(!subscriber->buf_handle){
|
||||||
ESP_LOGE(tag,"post failed: null buffer for %s", str_or_unknown(subscriber->subscriber_name));
|
ESP_LOGE(tag,"post failed: null buffer for %s", str_or_unknown(subscriber->subscriber_name));
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
vRingbufferGetInfo(subscriber->buf_handle,NULL,NULL,NULL,NULL,&uxItemsWaiting);
|
void * pItem=NULL;
|
||||||
if(uxItemsWaiting>=subscriber->max_count){
|
int passes=0;
|
||||||
|
UBaseType_t res=pdFALSE;
|
||||||
|
while(passes++<3){
|
||||||
|
res = xRingbufferSendAcquire(subscriber->buf_handle, &pItem, message_size, pdMS_TO_TICKS(100));
|
||||||
|
if(res == pdTRUE && pItem){
|
||||||
|
memcpy(pItem,message,message_size);
|
||||||
|
xRingbufferSendComplete(subscriber->buf_handle, pItem);
|
||||||
|
break;
|
||||||
|
}
|
||||||
ESP_LOGD(tag,"messaged dropped for %s",str_or_unknown(subscriber->subscriber_name));
|
ESP_LOGD(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));
|
single_message_t * dummy = (single_message_t *)xRingbufferReceive(subscriber->buf_handle, &item_size, pdMS_TO_TICKS(50));
|
||||||
if (dummy== NULL) {
|
if (dummy== NULL) {
|
||||||
@@ -189,7 +194,6 @@ esp_err_t messaging_post_to_queue(messaging_handle_t subscriber_handle, single_m
|
|||||||
vRingbufferReturnItem(subscriber->buf_handle, (void *)dummy);
|
vRingbufferReturnItem(subscriber->buf_handle, (void *)dummy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UBaseType_t res = xRingbufferSend(subscriber->buf_handle, message, message_size, pdMS_TO_TICKS(1000));
|
|
||||||
if (res != pdTRUE) {
|
if (res != pdTRUE) {
|
||||||
ESP_LOGE(tag,"post to %s failed",str_or_unknown(subscriber->subscriber_name));
|
ESP_LOGE(tag,"post to %s failed",str_or_unknown(subscriber->subscriber_name));
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
@@ -197,19 +201,27 @@ esp_err_t messaging_post_to_queue(messaging_handle_t subscriber_handle, single_m
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
void messaging_post_message(messaging_types type,messaging_classes msg_class, char *fmt, ...){
|
void messaging_post_message(messaging_types type,messaging_classes msg_class, char *fmt, ...){
|
||||||
single_message_t message={};
|
single_message_t * message=NULL;
|
||||||
|
size_t msg_size=0;
|
||||||
|
size_t ln =0;
|
||||||
messaging_list_t * cur=⊤
|
messaging_list_t * cur=⊤
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
vsnprintf(message.message, sizeof(message.message), fmt, va);
|
ln = vsnprintf(NULL, 0, fmt, va)+1;
|
||||||
|
msg_size = sizeof(single_message_t)+ln;
|
||||||
|
message = (single_message_t *)heap_caps_malloc(msg_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||||
|
vsprintf(message->message, fmt, va);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
message.type = type;
|
message->msg_size = msg_size;
|
||||||
message.msg_class = msg_class;
|
message->type = type;
|
||||||
message.sent_time = esp_timer_get_time() / 1000;
|
message->msg_class = msg_class;
|
||||||
|
message->sent_time = esp_timer_get_time() / 1000;
|
||||||
|
ESP_LOGI(tag,"Post: %s",message->message);
|
||||||
while(cur){
|
while(cur){
|
||||||
messaging_post_to_queue(get_handle_ptr(cur), &message, sizeof(single_message_t));
|
messaging_post_to_queue(get_handle_ptr(cur), message, msg_size);
|
||||||
cur = get_struct_ptr(cur->next);
|
cur = get_struct_ptr(cur->next);
|
||||||
}
|
}
|
||||||
|
FREE_AND_NULL(message);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ typedef enum {
|
|||||||
} messaging_types;
|
} messaging_types;
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MESSAGING_CLASS_OTA,
|
MESSAGING_CLASS_OTA,
|
||||||
MESSAGING_CLASS_SYSTEM
|
MESSAGING_CLASS_SYSTEM,
|
||||||
|
MESSAGING_CLASS_STATS
|
||||||
} messaging_classes;
|
} messaging_classes;
|
||||||
|
|
||||||
typedef struct messaging_list_t *messaging_handle_t;
|
typedef struct messaging_list_t *messaging_handle_t;
|
||||||
@@ -18,7 +19,8 @@ typedef struct {
|
|||||||
time_t sent_time;
|
time_t sent_time;
|
||||||
messaging_types type;
|
messaging_types type;
|
||||||
messaging_classes msg_class;
|
messaging_classes msg_class;
|
||||||
char message[151];
|
size_t msg_size;
|
||||||
|
char message[];
|
||||||
} single_message_t;
|
} single_message_t;
|
||||||
|
|
||||||
cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle);
|
cJSON * messaging_retrieve_messages(RingbufHandle_t buf_handle);
|
||||||
|
|||||||
@@ -21,6 +21,9 @@
|
|||||||
#include "globdefs.h"
|
#include "globdefs.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "accessors.h"
|
#include "accessors.h"
|
||||||
|
#include "messaging.h"
|
||||||
|
#include "cJSON.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
#define MONITOR_TIMER (10*1000)
|
#define MONITOR_TIMER (10*1000)
|
||||||
|
|
||||||
@@ -49,10 +52,12 @@ static void task_stats( void ) {
|
|||||||
TaskStatus_t *tasks;
|
TaskStatus_t *tasks;
|
||||||
uint32_t total, n;
|
uint32_t total, n;
|
||||||
} current, previous;
|
} current, previous;
|
||||||
|
cJSON * top=cJSON_CreateObject();
|
||||||
|
cJSON * tlist=cJSON_CreateArray();
|
||||||
current.n = uxTaskGetNumberOfTasks();
|
current.n = uxTaskGetNumberOfTasks();
|
||||||
current.tasks = malloc( current.n * sizeof( TaskStatus_t ) );
|
current.tasks = malloc( current.n * sizeof( TaskStatus_t ) );
|
||||||
current.n = uxTaskGetSystemState( current.tasks, current.n, ¤t.total );
|
current.n = uxTaskGetSystemState( current.tasks, current.n, ¤t.total );
|
||||||
|
cJSON_AddNumberToObject(top,"ntasks",current.n);
|
||||||
|
|
||||||
static EXT_RAM_ATTR char scratch[128+1];
|
static EXT_RAM_ATTR char scratch[128+1];
|
||||||
*scratch = '\0';
|
*scratch = '\0';
|
||||||
@@ -66,6 +71,20 @@ static void task_stats( void ) {
|
|||||||
n += sprintf(scratch + n, "%16s %2u%% s:%5u", current.tasks[i].pcTaskName,
|
n += sprintf(scratch + n, "%16s %2u%% s:%5u", current.tasks[i].pcTaskName,
|
||||||
100 * (current.tasks[i].ulRunTimeCounter - previous.tasks[j].ulRunTimeCounter) / elapsed,
|
100 * (current.tasks[i].ulRunTimeCounter - previous.tasks[j].ulRunTimeCounter) / elapsed,
|
||||||
current.tasks[i].usStackHighWaterMark);
|
current.tasks[i].usStackHighWaterMark);
|
||||||
|
cJSON * t=cJSON_CreateObject();
|
||||||
|
cJSON_AddNumberToObject(t,"cpu",100 * (current.tasks[i].ulRunTimeCounter - previous.tasks[j].ulRunTimeCounter) / elapsed);
|
||||||
|
cJSON_AddNumberToObject(t,"minstk",current.tasks[i].usStackHighWaterMark);
|
||||||
|
cJSON_AddNumberToObject(t,"bprio",current.tasks[i].uxBasePriority);
|
||||||
|
cJSON_AddNumberToObject(t,"cprio",current.tasks[i].uxCurrentPriority);
|
||||||
|
cJSON_AddStringToObject(t,"nme",current.tasks[i].pcTaskName);
|
||||||
|
cJSON_AddNumberToObject(t,"st",current.tasks[i].eCurrentState);
|
||||||
|
cJSON_AddNumberToObject(t,"num",current.tasks[i].xTaskNumber);
|
||||||
|
cJSON_AddItemToArray(tlist,t);
|
||||||
|
char * topsts = cJSON_PrintUnformatted(t);
|
||||||
|
if(topsts){
|
||||||
|
ESP_LOGI(TAG,"task detail: %s",topsts);
|
||||||
|
FREE_AND_NULL(topsts);
|
||||||
|
}
|
||||||
if (i % 3 == 2 || i == current.n - 1) {
|
if (i % 3 == 2 || i == current.n - 1) {
|
||||||
ESP_LOGI(TAG, "%s", scratch);
|
ESP_LOGI(TAG, "%s", scratch);
|
||||||
n = 0;
|
n = 0;
|
||||||
@@ -77,13 +96,32 @@ static void task_stats( void ) {
|
|||||||
#else
|
#else
|
||||||
for (int i = 0, n = 0; i < current.n; i ++) {
|
for (int i = 0, n = 0; i < current.n; i ++) {
|
||||||
n += sprintf(scratch + n, "%16s s:%5u\t", current.tasks[i].pcTaskName, current.tasks[i].usStackHighWaterMark);
|
n += sprintf(scratch + n, "%16s s:%5u\t", current.tasks[i].pcTaskName, current.tasks[i].usStackHighWaterMark);
|
||||||
|
cJSON * t=cJSON_CreateObject();
|
||||||
|
cJSON_AddNumberToObject(t,"minstk",current.tasks[i].usStackHighWaterMark);
|
||||||
|
cJSON_AddNumberToObject(t,"bprio",current.tasks[i].uxBasePriority);
|
||||||
|
cJSON_AddNumberToObject(t,"cprio",current.tasks[i].uxCurrentPriority);
|
||||||
|
cJSON_AddStringToObject(t,"nme",current.tasks[i].pcTaskName);
|
||||||
|
cJSON_AddStringToObject(t,"st",current.tasks[i].eCurrentState);
|
||||||
|
cJSON_AddNumberToObject(t,"num",current.tasks[i].xTaskNumber);
|
||||||
|
cJSON_AddItemToArray(tlist,t);
|
||||||
|
char * topsts = cJSON_PrintUnformatted(t);
|
||||||
|
if(topsts){
|
||||||
|
ESP_LOGI(TAG,"task detail: %s",topsts);
|
||||||
|
FREE_AND_NULL(topsts);
|
||||||
|
}
|
||||||
if (i % 3 == 2 || i == current.n - 1) {
|
if (i % 3 == 2 || i == current.n - 1) {
|
||||||
ESP_LOGI(TAG, "%s", scratch);
|
ESP_LOGI(TAG, "%s", scratch);
|
||||||
n = 0;
|
n = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
cJSON_AddItemToObject(top,"tasks",tlist);
|
||||||
|
char * top_a= cJSON_PrintUnformatted(top);
|
||||||
|
if(top_a){
|
||||||
|
messaging_post_message(MESSAGING_INFO, MESSAGING_CLASS_STATS,top_a);
|
||||||
|
FREE_AND_NULL(top_a);
|
||||||
|
}
|
||||||
|
cJSON_free(top);
|
||||||
if (previous.tasks) free(previous.tasks);
|
if (previous.tasks) free(previous.tasks);
|
||||||
previous = current;
|
previous = current;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -616,7 +616,7 @@ void ota_task(void *pvParameter)
|
|||||||
{
|
{
|
||||||
esp_err_t err = ESP_OK;
|
esp_err_t err = ESP_OK;
|
||||||
int data_read = 0;
|
int data_read = 0;
|
||||||
GDS_TextSetFont(display,2,&Font_droid_sans_fallback_15x17,-2);
|
GDS_TextSetFont(display,2,GDS_GetHeight(display)>32?&Font_droid_sans_fallback_15x17:&Font_droid_sans_fallback_11x13,-2);
|
||||||
GDS_ClearExt(display, true);
|
GDS_ClearExt(display, true);
|
||||||
GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Firmware update");
|
GDS_TextLine(display, 1, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Firmware update");
|
||||||
GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Initializing");
|
GDS_TextLine(display, 2, GDS_TEXT_LEFT, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, "Initializing");
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ void init_telnet(){
|
|||||||
void start_telnet(void * pvParameter){
|
void start_telnet(void * pvParameter){
|
||||||
static bool isStarted=false;
|
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_INTERNAL|MALLOC_CAP_8BIT));
|
||||||
StackType_t *xStack = heap_caps_malloc(TELNET_STACK_SIZE,(MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT));
|
StackType_t *xStack = heap_caps_malloc(TELNET_STACK_SIZE,(MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT));
|
||||||
|
|
||||||
if(!isStarted && bIsEnabled) {
|
if(!isStarted && bIsEnabled) {
|
||||||
xTaskCreateStatic( (TaskFunction_t) &telnet_task, "telnet", TELNET_STACK_SIZE, NULL, ESP_TASK_MAIN_PRIO , xStack, xTaskBuffer);
|
xTaskCreateStatic( (TaskFunction_t) &telnet_task, "telnet", TELNET_STACK_SIZE, NULL, ESP_TASK_MAIN_PRIO , xStack, xTaskBuffer);
|
||||||
|
|||||||
93
components/wifi-manager/_esp_http_server.h
Normal file
93
components/wifi-manager/_esp_http_server.h
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef __ESP_HTTP_SERVER_H_
|
||||||
|
#define __ESP_HTTP_SERVER_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
|
#include <http_parser.h>
|
||||||
|
#include <sdkconfig.h>
|
||||||
|
#include <esp_err.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Starts the web server
|
||||||
|
*
|
||||||
|
* Create an instance of HTTP server and allocate memory/resources for it
|
||||||
|
* depending upon the specified configuration.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* @code{c}
|
||||||
|
*
|
||||||
|
* //Function for starting the webserver
|
||||||
|
* httpd_handle_t start_webserver(void)
|
||||||
|
* {
|
||||||
|
* // Generate default configuration
|
||||||
|
* httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||||
|
*
|
||||||
|
* // Empty handle to http_server
|
||||||
|
* httpd_handle_t server = NULL;
|
||||||
|
*
|
||||||
|
* // Start the httpd server
|
||||||
|
* if (httpd_start(&server, &config) == ESP_OK) {
|
||||||
|
* // Register URI handlers
|
||||||
|
* httpd_register_uri_handler(server, &uri_get);
|
||||||
|
* httpd_register_uri_handler(server, &uri_post);
|
||||||
|
* }
|
||||||
|
* // If server failed to start, handle will be NULL
|
||||||
|
* return server;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @param[in] config Configuration for new instance of the server
|
||||||
|
* @param[out] handle Handle to newly created instance of the server. NULL on error
|
||||||
|
* @return
|
||||||
|
* - ESP_OK : Instance created successfully
|
||||||
|
* - ESP_ERR_INVALID_ARG : Null argument(s)
|
||||||
|
* - ESP_ERR_HTTPD_ALLOC_MEM : Failed to allocate memory for instance
|
||||||
|
* - ESP_ERR_HTTPD_TASK : Failed to launch server task
|
||||||
|
*/
|
||||||
|
esp_err_t __httpd_start(httpd_handle_t *handle, const httpd_config_t *config);
|
||||||
|
static inline int __httpd_os_thread_create_static(TaskHandle_t *thread,
|
||||||
|
const char *name, uint16_t stacksize, int prio,
|
||||||
|
void (*thread_routine)(void *arg), void *arg,
|
||||||
|
BaseType_t core_id)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
StaticTask_t *xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT));
|
||||||
|
StackType_t *xStack = heap_caps_malloc(stacksize,(MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT));
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
*thread = xTaskCreateStaticPinnedToCore(thread_routine, name, stacksize, arg, prio, xStack,xTaskBuffer,core_id);
|
||||||
|
if (*thread) {
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ! _ESP_HTTP_SERVER_H_ */
|
||||||
373
components/wifi-manager/_esp_httpd_main.c
Normal file
373
components/wifi-manager/_esp_httpd_main.c
Normal file
@@ -0,0 +1,373 @@
|
|||||||
|
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <esp_log.h>
|
||||||
|
#include <esp_err.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <esp_http_server.h>
|
||||||
|
#include <_esp_http_server.h>
|
||||||
|
#include "../src/esp_httpd_priv.h"
|
||||||
|
#include "../src/util/ctrl_sock.h"
|
||||||
|
|
||||||
|
static const char *TAG = "_httpd";
|
||||||
|
|
||||||
|
|
||||||
|
struct httpd_ctrl_data {
|
||||||
|
enum httpd_ctrl_msg {
|
||||||
|
HTTPD_CTRL_SHUTDOWN,
|
||||||
|
HTTPD_CTRL_WORK,
|
||||||
|
} hc_msg;
|
||||||
|
httpd_work_fn_t hc_work;
|
||||||
|
void *hc_work_arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static esp_err_t _httpd_server_init(struct httpd_data *hd)
|
||||||
|
{
|
||||||
|
int fd = socket(PF_INET6, SOCK_STREAM, 0);
|
||||||
|
if (fd < 0) {
|
||||||
|
ESP_LOGE(TAG, LOG_FMT("error in socket (%d)"), errno);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct in6_addr inaddr_any = IN6ADDR_ANY_INIT;
|
||||||
|
struct sockaddr_in6 serv_addr = {
|
||||||
|
.sin6_family = PF_INET6,
|
||||||
|
.sin6_addr = inaddr_any,
|
||||||
|
.sin6_port = htons(hd->config.server_port)
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Enable SO_REUSEADDR to allow binding to the same
|
||||||
|
* address and port when restarting the server */
|
||||||
|
int enable = 1;
|
||||||
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) {
|
||||||
|
/* This will fail if CONFIG_LWIP_SO_REUSE is not enabled. But
|
||||||
|
* it does not affect the normal working of the HTTP Server */
|
||||||
|
ESP_LOGW(TAG, LOG_FMT("error enabling SO_REUSEADDR (%d)"), errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = bind(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
|
||||||
|
if (ret < 0) {
|
||||||
|
ESP_LOGE(TAG, LOG_FMT("error in bind (%d)"), errno);
|
||||||
|
close(fd);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = listen(fd, hd->config.backlog_conn);
|
||||||
|
if (ret < 0) {
|
||||||
|
ESP_LOGE(TAG, LOG_FMT("error in listen (%d)"), errno);
|
||||||
|
close(fd);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ctrl_fd = cs_create_ctrl_sock(hd->config.ctrl_port);
|
||||||
|
if (ctrl_fd < 0) {
|
||||||
|
ESP_LOGE(TAG, LOG_FMT("error in creating ctrl socket (%d)"), errno);
|
||||||
|
close(fd);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int msg_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (msg_fd < 0) {
|
||||||
|
ESP_LOGE(TAG, LOG_FMT("error in creating msg socket (%d)"), errno);
|
||||||
|
close(fd);
|
||||||
|
close(ctrl_fd);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hd->listen_fd = fd;
|
||||||
|
hd->ctrl_fd = ctrl_fd;
|
||||||
|
hd->msg_fd = msg_fd;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _httpd_process_ctrl_msg(struct httpd_data *hd)
|
||||||
|
{
|
||||||
|
struct httpd_ctrl_data msg;
|
||||||
|
int ret = recv(hd->ctrl_fd, &msg, sizeof(msg), 0);
|
||||||
|
if (ret <= 0) {
|
||||||
|
ESP_LOGW(TAG, LOG_FMT("error in recv (%d)"), errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ret != sizeof(msg)) {
|
||||||
|
ESP_LOGW(TAG, LOG_FMT("incomplete msg"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (msg.hc_msg) {
|
||||||
|
case HTTPD_CTRL_WORK:
|
||||||
|
if (msg.hc_work) {
|
||||||
|
ESP_LOGD(TAG, LOG_FMT("work"));
|
||||||
|
(*msg.hc_work)(msg.hc_work_arg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HTTPD_CTRL_SHUTDOWN:
|
||||||
|
ESP_LOGD(TAG, LOG_FMT("shutdown"));
|
||||||
|
hd->hd_td.status = THREAD_STOPPING;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t _httpd_accept_conn(struct httpd_data *hd, int listen_fd)
|
||||||
|
{
|
||||||
|
/* If no space is available for new session, close the least recently used one */
|
||||||
|
if (hd->config.lru_purge_enable == true) {
|
||||||
|
if (!httpd_is_sess_available(hd)) {
|
||||||
|
/* Queue asynchronous closure of the least recently used session */
|
||||||
|
return httpd_sess_close_lru(hd);
|
||||||
|
/* Returning from this allowes the main server thread to process
|
||||||
|
* the queued asynchronous control message for closing LRU session.
|
||||||
|
* Since connection request hasn't been addressed yet using accept()
|
||||||
|
* therefore _httpd_accept_conn() will be called again, but this time
|
||||||
|
* with space available for one session
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in addr_from;
|
||||||
|
socklen_t addr_from_len = sizeof(addr_from);
|
||||||
|
int new_fd = accept(listen_fd, (struct sockaddr *)&addr_from, &addr_from_len);
|
||||||
|
if (new_fd < 0) {
|
||||||
|
ESP_LOGW(TAG, LOG_FMT("error in accept (%d)"), errno);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
ESP_LOGD(TAG, LOG_FMT("newfd = %d"), new_fd);
|
||||||
|
|
||||||
|
struct timeval tv;
|
||||||
|
/* Set recv timeout of this fd as per config */
|
||||||
|
tv.tv_sec = hd->config.recv_wait_timeout;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
setsockopt(new_fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));
|
||||||
|
|
||||||
|
/* Set send timeout of this fd as per config */
|
||||||
|
tv.tv_sec = hd->config.send_wait_timeout;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
setsockopt(new_fd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof(tv));
|
||||||
|
|
||||||
|
if (ESP_OK != httpd_sess_new(hd, new_fd)) {
|
||||||
|
ESP_LOGW(TAG, LOG_FMT("session creation failed"));
|
||||||
|
close(new_fd);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
ESP_LOGD(TAG, LOG_FMT("complete"));
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
/* Manage in-coming connection or data requests */
|
||||||
|
static esp_err_t _httpd_server(struct httpd_data *hd)
|
||||||
|
{
|
||||||
|
fd_set read_set;
|
||||||
|
FD_ZERO(&read_set);
|
||||||
|
if (hd->config.lru_purge_enable || httpd_is_sess_available(hd)) {
|
||||||
|
/* Only listen for new connections if server has capacity to
|
||||||
|
* handle more (or when LRU purge is enabled, in which case
|
||||||
|
* older connections will be closed) */
|
||||||
|
FD_SET(hd->listen_fd, &read_set);
|
||||||
|
}
|
||||||
|
FD_SET(hd->ctrl_fd, &read_set);
|
||||||
|
|
||||||
|
int tmp_max_fd;
|
||||||
|
httpd_sess_set_descriptors(hd, &read_set, &tmp_max_fd);
|
||||||
|
int maxfd = MAX(hd->listen_fd, tmp_max_fd);
|
||||||
|
tmp_max_fd = maxfd;
|
||||||
|
maxfd = MAX(hd->ctrl_fd, tmp_max_fd);
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, LOG_FMT("doing select maxfd+1 = %d"), maxfd + 1);
|
||||||
|
int active_cnt = select(maxfd + 1, &read_set, NULL, NULL, NULL);
|
||||||
|
if (active_cnt < 0) {
|
||||||
|
ESP_LOGE(TAG, LOG_FMT("error in select (%d)"), errno);
|
||||||
|
httpd_sess_delete_invalid(hd);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Case0: Do we have a control message? */
|
||||||
|
if (FD_ISSET(hd->ctrl_fd, &read_set)) {
|
||||||
|
ESP_LOGD(TAG, LOG_FMT("processing ctrl message"));
|
||||||
|
_httpd_process_ctrl_msg(hd);
|
||||||
|
if (hd->hd_td.status == THREAD_STOPPING) {
|
||||||
|
ESP_LOGD(TAG, LOG_FMT("stopping thread"));
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Case1: Do we have any activity on the current data
|
||||||
|
* sessions? */
|
||||||
|
int fd = -1;
|
||||||
|
while ((fd = httpd_sess_iterate(hd, fd)) != -1) {
|
||||||
|
if (FD_ISSET(fd, &read_set) || (httpd_sess_pending(hd, fd))) {
|
||||||
|
ESP_LOGD(TAG, LOG_FMT("processing socket %d"), fd);
|
||||||
|
if (httpd_sess_process(hd, fd) != ESP_OK) {
|
||||||
|
ESP_LOGD(TAG, LOG_FMT("closing socket %d"), fd);
|
||||||
|
close(fd);
|
||||||
|
/* Delete session and update fd to that
|
||||||
|
* preceding the one being deleted */
|
||||||
|
fd = httpd_sess_delete(hd, fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Case2: Do we have any incoming connection requests to
|
||||||
|
* process? */
|
||||||
|
if (FD_ISSET(hd->listen_fd, &read_set)) {
|
||||||
|
ESP_LOGD(TAG, LOG_FMT("processing listen socket %d"), hd->listen_fd);
|
||||||
|
if (_httpd_accept_conn(hd, hd->listen_fd) != ESP_OK) {
|
||||||
|
ESP_LOGW(TAG, LOG_FMT("error accepting new connection"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _httpd_close_all_sessions(struct httpd_data *hd)
|
||||||
|
{
|
||||||
|
int fd = -1;
|
||||||
|
while ((fd = httpd_sess_iterate(hd, fd)) != -1) {
|
||||||
|
ESP_LOGD(TAG, LOG_FMT("cleaning up socket %d"), fd);
|
||||||
|
httpd_sess_delete(hd, fd);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* The main HTTPD thread */
|
||||||
|
static void _httpd_thread(void *arg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct httpd_data *hd = (struct httpd_data *) arg;
|
||||||
|
hd->hd_td.status = THREAD_RUNNING;
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, LOG_FMT("web server started"));
|
||||||
|
while (1) {
|
||||||
|
ret = _httpd_server(hd);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, LOG_FMT("web server exiting"));
|
||||||
|
close(hd->msg_fd);
|
||||||
|
cs_free_ctrl_sock(hd->ctrl_fd);
|
||||||
|
_httpd_close_all_sessions(hd);
|
||||||
|
close(hd->listen_fd);
|
||||||
|
hd->hd_td.status = THREAD_STOPPED;
|
||||||
|
httpd_os_thread_delete();
|
||||||
|
}
|
||||||
|
static struct httpd_data *__httpd_create(const httpd_config_t *config)
|
||||||
|
{
|
||||||
|
/* Allocate memory for httpd instance data */
|
||||||
|
struct httpd_data *hd = calloc(1, sizeof(struct httpd_data));
|
||||||
|
if (!hd) {
|
||||||
|
ESP_LOGE(TAG, LOG_FMT("Failed to allocate memory for HTTP server instance"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
hd->hd_calls = calloc(config->max_uri_handlers, sizeof(httpd_uri_t *));
|
||||||
|
if (!hd->hd_calls) {
|
||||||
|
ESP_LOGE(TAG, LOG_FMT("Failed to allocate memory for HTTP URI handlers"));
|
||||||
|
free(hd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
hd->hd_sd = calloc(config->max_open_sockets, sizeof(struct sock_db));
|
||||||
|
if (!hd->hd_sd) {
|
||||||
|
ESP_LOGE(TAG, LOG_FMT("Failed to allocate memory for HTTP session data"));
|
||||||
|
free(hd->hd_calls);
|
||||||
|
free(hd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
struct httpd_req_aux *ra = &hd->hd_req_aux;
|
||||||
|
ra->resp_hdrs = calloc(config->max_resp_headers, sizeof(struct resp_hdr));
|
||||||
|
if (!ra->resp_hdrs) {
|
||||||
|
ESP_LOGE(TAG, LOG_FMT("Failed to allocate memory for HTTP response headers"));
|
||||||
|
free(hd->hd_sd);
|
||||||
|
free(hd->hd_calls);
|
||||||
|
free(hd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
hd->err_handler_fns = calloc(HTTPD_ERR_CODE_MAX, sizeof(httpd_err_handler_func_t));
|
||||||
|
if (!hd->err_handler_fns) {
|
||||||
|
ESP_LOGE(TAG, LOG_FMT("Failed to allocate memory for HTTP error handlers"));
|
||||||
|
free(ra->resp_hdrs);
|
||||||
|
free(hd->hd_sd);
|
||||||
|
free(hd->hd_calls);
|
||||||
|
free(hd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* Save the configuration for this instance */
|
||||||
|
hd->config = *config;
|
||||||
|
return hd;
|
||||||
|
}
|
||||||
|
static void _httpd_delete(struct httpd_data *hd)
|
||||||
|
{
|
||||||
|
struct httpd_req_aux *ra = &hd->hd_req_aux;
|
||||||
|
/* Free memory of httpd instance data */
|
||||||
|
free(hd->err_handler_fns);
|
||||||
|
free(ra->resp_hdrs);
|
||||||
|
free(hd->hd_sd);
|
||||||
|
|
||||||
|
/* Free registered URI handlers */
|
||||||
|
httpd_unregister_all_uri_handlers(hd);
|
||||||
|
free(hd->hd_calls);
|
||||||
|
free(hd);
|
||||||
|
}
|
||||||
|
esp_err_t __httpd_start(httpd_handle_t *handle, const httpd_config_t *config)
|
||||||
|
{
|
||||||
|
if (handle == NULL || config == NULL) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanity check about whether LWIP is configured for providing the
|
||||||
|
* maximum number of open sockets sufficient for the server. Though,
|
||||||
|
* this check doesn't guarantee that many sockets will actually be
|
||||||
|
* available at runtime as other processes may use up some sockets.
|
||||||
|
* Note that server also uses 3 sockets for its internal use :
|
||||||
|
* 1) listening for new TCP connections
|
||||||
|
* 2) for sending control messages over UDP
|
||||||
|
* 3) for receiving control messages over UDP
|
||||||
|
* So the total number of required sockets is max_open_sockets + 3
|
||||||
|
*/
|
||||||
|
if (CONFIG_LWIP_MAX_SOCKETS < config->max_open_sockets + 3) {
|
||||||
|
ESP_LOGE(TAG, "Configuration option max_open_sockets is too large (max allowed %d)\n\t"
|
||||||
|
"Either decrease this or configure LWIP_MAX_SOCKETS to a larger value",
|
||||||
|
CONFIG_LWIP_MAX_SOCKETS - 3);
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct httpd_data *hd = __httpd_create(config);
|
||||||
|
if (hd == NULL) {
|
||||||
|
/* Failed to allocate memory */
|
||||||
|
return ESP_ERR_HTTPD_ALLOC_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_httpd_server_init(hd) != ESP_OK) {
|
||||||
|
_httpd_delete(hd);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
httpd_sess_init(hd);
|
||||||
|
if (__httpd_os_thread_create_static(&hd->hd_td.handle, "httpd",
|
||||||
|
hd->config.stack_size,
|
||||||
|
hd->config.task_priority,
|
||||||
|
_httpd_thread, hd,
|
||||||
|
hd->config.core_id) != ESP_OK) {
|
||||||
|
/* Failed to launch task */
|
||||||
|
_httpd_delete(hd);
|
||||||
|
return ESP_ERR_HTTPD_TASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
*handle = (httpd_handle_t *)hd;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -24,6 +24,14 @@ var nvs_type_t = {
|
|||||||
NVS_TYPE_ANY : 0xff /*!< Must be last */
|
NVS_TYPE_ANY : 0xff /*!< Must be last */
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
var task_state_t = {
|
||||||
|
0 : "eRunning", /*!< A task is querying the state of itself, so must be running. */
|
||||||
|
1 : "eReady", /*!< The task being queried is in a read or pending ready list. */
|
||||||
|
2 : "eBlocked", /*!< The task being queried is in the Blocked state. */
|
||||||
|
3 : "eSuspended", /*!< The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */
|
||||||
|
4 : "eDeleted"
|
||||||
|
|
||||||
|
}
|
||||||
var releaseURL = 'https://api.github.com/repos/sle118/squeezelite-esp32/releases';
|
var releaseURL = 'https://api.github.com/repos/sle118/squeezelite-esp32/releases';
|
||||||
var recovery = false;
|
var recovery = false;
|
||||||
var enableAPTimer = true;
|
var enableAPTimer = true;
|
||||||
@@ -649,7 +657,9 @@ function refreshAPHTML(data){
|
|||||||
function getMessages() {
|
function getMessages() {
|
||||||
$.getJSON("/messages.json", function(data) {
|
$.getJSON("/messages.json", function(data) {
|
||||||
data.forEach(function(msg) {
|
data.forEach(function(msg) {
|
||||||
var msg_age = msg["current_time"] - msg["sent_time"];
|
var msg_age = msg["current_time"] - msg["sent_time"];
|
||||||
|
var msg_time = new Date( );
|
||||||
|
msg_time.setTime( msg_time .getTime() - msg_age );
|
||||||
switch (msg["class"]) {
|
switch (msg["class"]) {
|
||||||
case "MESSAGING_CLASS_OTA":
|
case "MESSAGING_CLASS_OTA":
|
||||||
//message: "{"ota_dsc":"Erasing flash complete","ota_pct":0}"
|
//message: "{"ota_dsc":"Erasing flash complete","ota_pct":0}"
|
||||||
@@ -668,6 +678,15 @@ function getMessages() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "MESSAGING_CLASS_STATS":
|
||||||
|
// for task states, check structure : task_state_t
|
||||||
|
var stats_data = JSON.parse(msg["message"]);
|
||||||
|
console.log(msg_time + " - Number of tasks on the ESP32: " + stats_data["ntasks"]);
|
||||||
|
var stats_tasks = stats_data["tasks"];
|
||||||
|
stats_tasks.forEach(function(task) {
|
||||||
|
console.log(msg_time + " - " + task["nme"] + ' - '+ task["cpu"]);
|
||||||
|
});
|
||||||
|
break;
|
||||||
case "MESSAGING_CLASS_SYSTEM":
|
case "MESSAGING_CLASS_SYSTEM":
|
||||||
showMessage(msg["message"], msg["type"],msg_age);
|
showMessage(msg["message"], msg["type"],msg_age);
|
||||||
lastMsg = msg;
|
lastMsg = msg;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
# please read the SDK documents if you need to do this.
|
# please read the SDK documents if you need to do this.
|
||||||
#
|
#
|
||||||
COMPONENT_EMBED_FILES := style.css code.js index.html bootstrap.min.css.gz jquery.min.js.gz popper.min.js.gz bootstrap.min.js.gz
|
COMPONENT_EMBED_FILES := style.css code.js index.html bootstrap.min.css.gz jquery.min.js.gz popper.min.js.gz bootstrap.min.js.gz
|
||||||
COMPONENT_ADD_INCLUDEDIRS := .
|
COMPONENT_ADD_INCLUDEDIRS := . $(IDF_PATH)/components/esp_http_server/src $(IDF_PATH)/components/esp_http_server/src/port/esp32 $(IDF_PATH)/components/esp_http_server/src/util
|
||||||
CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_INFO
|
CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_INFO
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "http_server_handlers.h"
|
#include "http_server_handlers.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_http_server.h"
|
#include "esp_http_server.h"
|
||||||
|
#include "_esp_http_server.h"
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -112,6 +113,7 @@ void register_regular_handlers(httpd_handle_t server){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
esp_err_t http_server_start()
|
esp_err_t http_server_start()
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Initializing HTTP Server");
|
ESP_LOGI(TAG, "Initializing HTTP Server");
|
||||||
@@ -131,7 +133,7 @@ esp_err_t http_server_start()
|
|||||||
// config.open_fn
|
// config.open_fn
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Starting HTTP Server");
|
ESP_LOGI(TAG, "Starting HTTP Server");
|
||||||
esp_err_t err= httpd_start(&_server, &config);
|
esp_err_t err= __httpd_start(&_server, &config);
|
||||||
if(err != ESP_OK){
|
if(err != ESP_OK){
|
||||||
ESP_LOGE_LOC(TAG,"Start server failed");
|
ESP_LOGE_LOC(TAG,"Start server failed");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
set(COMPONENT_ADD_INCLUDEDIRS . )
|
set(COMPONENT_ADD_INCLUDEDIRS . ${IDF_PATH}/components/esp_http_server/src ${IDF_PATH}/components/esp_http_server/src/port/esp32 ${IDF_PATH}/components/esp_http_server/src/util)
|
||||||
|
|
||||||
set(COMPONENT_SRCS "esp_app_main.c" "platform_esp32.c" "cmd_wifi.c" "console.c" "nvs_utilities.c" "cmd_squeezelite.c" "config.c")
|
set(COMPONENT_SRCS "esp_app_main.c" "platform_esp32.c" "cmd_wifi.c" "console.c" "nvs_utilities.c" "cmd_squeezelite.c" "config.c")
|
||||||
set(REQUIRES esp_common)
|
set(REQUIRES esp_common)
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "audio_controls.h"
|
#include "audio_controls.h"
|
||||||
#include "telnet.h"
|
#include "telnet.h"
|
||||||
|
#include "messaging.h"
|
||||||
|
|
||||||
static const char certs_namespace[] = "certificates";
|
static const char certs_namespace[] = "certificates";
|
||||||
static const char certs_key[] = "blob";
|
static const char certs_key[] = "blob";
|
||||||
@@ -73,12 +74,14 @@ const char * str_or_unknown(const char * str) { return (str?str:unknown_string_p
|
|||||||
/* brief this is an exemple of a callback that you can setup in your own app to get notified of wifi manager event */
|
/* brief this is an exemple of a callback that you can setup in your own app to get notified of wifi manager event */
|
||||||
void cb_connection_got_ip(void *pvParameter){
|
void cb_connection_got_ip(void *pvParameter){
|
||||||
ESP_LOGI(TAG, "I have a connection!");
|
ESP_LOGI(TAG, "I have a connection!");
|
||||||
|
messaging_post_message(MESSAGING_INFO,MESSAGING_CLASS_SYSTEM,"Wifi connected");
|
||||||
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
|
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
|
||||||
bWifiConnected=true;
|
bWifiConnected=true;
|
||||||
led_unpush(LED_GREEN);
|
led_unpush(LED_GREEN);
|
||||||
}
|
}
|
||||||
void cb_connection_sta_disconnected(void *pvParameter){
|
void cb_connection_sta_disconnected(void *pvParameter){
|
||||||
led_blink_pushed(LED_GREEN, 250, 250);
|
led_blink_pushed(LED_GREEN, 250, 250);
|
||||||
|
messaging_post_message(MESSAGING_WARNING,MESSAGING_CLASS_SYSTEM,"Wifi disconnected");
|
||||||
bWifiConnected=false;
|
bWifiConnected=false;
|
||||||
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
|
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
|
||||||
}
|
}
|
||||||
@@ -427,4 +430,5 @@ void app_main()
|
|||||||
#endif
|
#endif
|
||||||
free(fwurl);
|
free(fwurl);
|
||||||
}
|
}
|
||||||
|
messaging_post_message(MESSAGING_INFO,MESSAGING_CLASS_SYSTEM,"System started");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user