fix system freezing on telnet activation

This commit is contained in:
Sebastien
2020-02-25 21:40:57 -05:00
parent 47d7baaf5f
commit 0acb0dc3e7
11 changed files with 236 additions and 100 deletions

3
.gitignore vendored
View File

@@ -67,3 +67,6 @@ libs/
/_* /_*
sdkconfig sdkconfig
squeezelite-esp32-jsonblob.zip squeezelite-esp32-jsonblob.zip
/flash_cmd.txt
/writeSequeezeEsp.bat
/writeSequeezeEsp.sh

View File

@@ -596,6 +596,7 @@ CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
CONFIG_FREERTOS_CORETIMER_0=y CONFIG_FREERTOS_CORETIMER_0=y
CONFIG_FREERTOS_HZ=100 CONFIG_FREERTOS_HZ=100
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y

View File

@@ -594,7 +594,7 @@ CONFIG_FMB_TIMER_INDEX=0
CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
CONFIG_FREERTOS_CORETIMER_0=y CONFIG_FREERTOS_CORETIMER_0=y
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
CONFIG_FREERTOS_HZ=100 CONFIG_FREERTOS_HZ=100
CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y

View File

@@ -597,6 +597,7 @@ CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
CONFIG_FREERTOS_CORETIMER_0=y CONFIG_FREERTOS_CORETIMER_0=y
CONFIG_FREERTOS_HZ=100 CONFIG_FREERTOS_HZ=100
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y

View File

@@ -596,6 +596,7 @@ CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
CONFIG_FREERTOS_CORETIMER_0=y CONFIG_FREERTOS_CORETIMER_0=y
CONFIG_FREERTOS_HZ=100 CONFIG_FREERTOS_HZ=100
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y

View File

@@ -596,6 +596,7 @@ CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
CONFIG_FREERTOS_CORETIMER_0=y CONFIG_FREERTOS_CORETIMER_0=y
CONFIG_FREERTOS_HZ=100 CONFIG_FREERTOS_HZ=100
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y

View File

@@ -590,6 +590,7 @@ CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
CONFIG_FREERTOS_CORETIMER_0=y CONFIG_FREERTOS_CORETIMER_0=y
CONFIG_FREERTOS_HZ=100 CONFIG_FREERTOS_HZ=100
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y

113
build_flash_cmd.sh Normal file
View File

@@ -0,0 +1,113 @@
#!/bin/bash
echo
echo =================================================================
echo Build flash command
echo =================================================================
# Location of partitions.csv relative to this script
partitionsCsv="../partitions.csv"
# File to output readme instructions to
outputReadme="./flash_cmd.txt"
# File to output bash script to
outputBashScript="./writeSequeezeEsp.sh"
# File to output bat script to
outputBatScript="./writeSequeezeEsp.bat"
# The name of partitions to ignore from partitions.csv
paritionsToIgnore=(
"nvs"
"phy_init"
"storage"
"coredump"
"settings"
)
# Function that maps partition name to actual bin file
# defaults to "[PARTION_NAME_FROM_CSV].bin"
function partitionNameToBinFile {
if [[ "$1" == "otadata" ]]; then
echo "ota_data_initial.bin"
elif [[ "$1" == "ota_0" || "$1" == "factory" ]]; then
echo "squeezelite.bin"
else
echo $1.bin
fi
}
# write parameters for esptool.py
writeParameters="$writeParameters write_flash"
writeParameters="$writeParameters --flash_mode dio --flash_freq 80m --flash_size detect"
# bootloader.bin and partitions.bin not in partitions.csv so manually add here
partitionsParameters=" 0x1000 bootloader/bootloader.bin"
partitionsParameters="$partitionsParameters 0x8000 partitions.bin"
# ==============================================================================
# Loop over partitions.csv and add partition bins and offsets to partitionsParameters
for line in $($IDF_PATH/components/partition_table/gen_esp32part.py --quiet build/partitions.bin | grep '^[^#]')
do
partitionName=$(echo $line | awk -F',' '{printf "%s", $1}' )
partitionOffset=$(echo $line |awk -F',' '{printf "%s", $4}' )
partitionFile=$(partitionNameToBinFile $partitionName)
if [[ " ${paritionsToIgnore[@]} " =~ " ${partitionName} " ]]; then
continue
fi
partitionsParameters="$partitionsParameters $partitionOffset $partitionFile"
echo "$partitionsParameters"
done
# Write README Instructions
if [ ! -f "$outputReadme" ]; then
touch $outputReadme
fi
echo "" >> $outputReadme
echo "====LINUX====" >> $outputReadme
echo "To flash sequeezelite run the following script:" >> $outputReadme
echo "$outputBashScript [PORT_HERE] [BAUD_RATE]" >> $outputReadme
echo "e.g. $outputBashScript /dev/ttyUSB0 115200" >> $outputReadme
echo "" >> $outputReadme
echo "====WINDOWS====" >> $outputReadme
echo "To flash sequeezelite run the following script:" >> $outputReadme
echo "$outputBatScript [PORT_HERE] [BAUD_RATE]" >> $outputReadme
echo "e.g. $outputBatScript COM11 115200" >> $outputReadme
echo "" >> $outputReadme
echo "If you don't know how to run the BAT file with arguments then you can" >> $outputReadme
echo "edit the bat file in Notepad. Open the file up and edit the following:" >> $outputReadme
echo "Change 'set port=%1' to 'set port=[PORT_HERE]'. E.g. 'set port=COM11'" >> $outputReadme
echo "Change 'set baud=%2' to 'set baud=[BAUD_RATE]'. E.g. 'set baud=115200'" >> $outputReadme
echo "" >> $outputReadme
echo "====MANUAL====" >> $outputReadme
echo "Python esptool.py --port [PORT_HERE] --baud [BAUD_RATE] $writeParameters $partitionsParameters" >> $outputReadme
# Write Linux BASH File
if [ ! -f "$outputBashScript" ]; then
touch $outputBashScript
fi
echo "#!/bin/bash" >> $outputBashScript
echo >> $outputBashScript
echo "port=\$1" >> $outputBashScript
echo "baud=\$2" >> $outputBashScript
linuxFlashCommand="Python esptool.py --port \$port --baud \$baud"
echo "$linuxFlashCommand $writeParameters $partitionsParameters" >> $outputBashScript
# Write Windows BAT File
if [ ! -f "$outputBatScript" ]; then
touch $outputBatScript
fi
echo "echo off" >> $outputBatScript
echo "" >> $outputBatScript
echo "set port=%1" >> $outputBatScript
echo "set baud=%2" >> $outputBatScript
windowsFlashCommand="Python esptool.py --port %port% --baud %baud%"
echo "$windowsFlashCommand $writeParameters $partitionsParameters" >> $outputBatScript

View File

@@ -50,7 +50,7 @@
const static char tag[] = "telnet"; const static char tag[] = "telnet";
static int uart_fd=0; static int uart_fd=0;
RingbufHandle_t buf_handle; RingbufHandle_t buf_handle;
SemaphoreHandle_t xSemaphore = NULL; //static SemaphoreHandle_t xSemaphore = NULL;
static size_t send_chunk=300; static size_t send_chunk=300;
static size_t log_buf_size=2000; //32-bit aligned size static size_t log_buf_size=2000; //32-bit aligned size
static bool bIsEnabled=false; static bool bIsEnabled=false;
@@ -68,7 +68,7 @@ static int stdout_fstat(int fd, struct stat * st);
static ssize_t stdout_write(int fd, const void * data, size_t size); static ssize_t stdout_write(int fd, const void * data, size_t size);
static char *eventToString(telnet_event_type_t type); static char *eventToString(telnet_event_type_t type);
static void handle_telnet_conn(); static void handle_telnet_conn();
static void process_logs( UBaseType_t bytes); static void process_logs( UBaseType_t bytes, bool is_write_op);
static bool bMirrorToUART=false; static bool bMirrorToUART=false;
struct telnetUserData { struct telnetUserData {
int sockfd; int sockfd;
@@ -76,7 +76,9 @@ struct telnetUserData {
char * rxbuf; char * rxbuf;
}; };
bool is_serial_suppressed(){
return !bIsEnabled || !bMirrorToUART ;
}
void init_telnet(){ void init_telnet(){
char *val= get_nvs_value_alloc(NVS_TYPE_STR, "telnet_enable"); char *val= get_nvs_value_alloc(NVS_TYPE_STR, "telnet_enable");
if (!val || strlen(val) == 0 || !strcasestr("YXD",val) ) { if (!val || strlen(val) == 0 || !strcasestr("YXD",val) ) {
@@ -100,11 +102,12 @@ void init_telnet(){
log_buf_size=log_buf_size>0?log_buf_size:4000; log_buf_size=log_buf_size>0?log_buf_size:4000;
} }
// Create the semaphore to guard a shared resource. // Create the semaphore to guard a shared resource.
vSemaphoreCreateBinary( xSemaphore ); //vSemaphoreCreateBinary( xSemaphore );
// Redirect the output to our telnet handler as soon as possible // 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 | MALLOC_CAP_8BIT); StaticRingbuffer_t *buffer_struct = (StaticRingbuffer_t *)malloc(sizeof(StaticRingbuffer_t) );
uint8_t *buffer_storage = (uint8_t *)heap_caps_malloc(sizeof(uint8_t)*log_buf_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); // All non-split ring buffer must have their memory alignment set to 32 bits.
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); buf_handle = xRingbufferCreateStatic(log_buf_size, RINGBUF_TYPE_BYTEBUF, buffer_storage, buffer_struct);
if (buf_handle == NULL) { if (buf_handle == NULL) {
ESP_LOGE(tag,"Failed to create ring buffer for telnet!"); ESP_LOGE(tag,"Failed to create ring buffer for telnet!");
@@ -119,7 +122,9 @@ void init_telnet(){
.fstat = &stdout_fstat, .fstat = &stdout_fstat,
.close = &stdout_close, .close = &stdout_close,
.read = &stdout_read, .read = &stdout_read,
}; };
if(bMirrorToUART){ if(bMirrorToUART){
uart_fd=open("/dev/uart/0", O_RDWR); uart_fd=open("/dev/uart/0", O_RDWR);
} }
@@ -130,11 +135,11 @@ 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_SPIRAM | MALLOC_CAP_8BIT); StaticTask_t *xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT));
StackType_t *xStack = malloc(TELNET_STACK_SIZE); StackType_t *xStack = heap_caps_malloc(TELNET_STACK_SIZE,(MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT));
if(!isStarted && bIsEnabled) { if(!isStarted && bIsEnabled) {
xTaskCreateStatic( (TaskFunction_t) &telnet_task, "telnet", TELNET_STACK_SIZE, NULL, ESP_TASK_PRIO_MIN + 1, xStack, xTaskBuffer); xTaskCreateStatic( (TaskFunction_t) &telnet_task, "telnet", TELNET_STACK_SIZE, NULL, ESP_TASK_MAIN_PRIO , xStack, xTaskBuffer);
isStarted=true; isStarted=true;
} }
} }
@@ -275,23 +280,23 @@ static void handle_telnet_events(
} // myhandle_telnet_events } // myhandle_telnet_events
static void process_logs(UBaseType_t count){ static void process_logs( UBaseType_t bytes, bool is_write_op){
//Receive an item from no-split ring buffer //Receive an item from no-split ring buffer
size_t item_size; size_t item_size;
UBaseType_t uxItemsWaiting; UBaseType_t uxItemsWaiting;
UBaseType_t uxBytesToSend=count; UBaseType_t uxBytesToSend=bytes;
vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting); vRingbufferGetInfo(buf_handle, NULL, NULL, NULL, NULL, &uxItemsWaiting);
if(count == 0){ bool is_space_available = ((log_buf_size-uxItemsWaiting)>=bytes && log_buf_size>uxItemsWaiting);
// this sends the entire buffer to the remote client if( is_space_available && (is_write_op || partnerSocket == 0) ){
uxBytesToSend = uxItemsWaiting; // there's still some room left in the buffer, and we're either
} // processing a write operation or telnet isn't connected yet.
if( partnerSocket ==0 && (uxItemsWaiting*100 / log_buf_size) <75){
// We still have some room in the ringbuffer and there's no telnet
// connection yet, so bail out for now.
//printf("%s() Log buffer used %u of %u bytes used\n", __FUNCTION__, uxItemsWaiting, log_buf_size);
return; return;
} }
if(is_write_op && !is_space_available && uxBytesToSend==0){
// flush at least the size of a full chunk
uxBytesToSend = send_chunk;
}
while(uxBytesToSend>0){ while(uxBytesToSend>0){
char *item = (char *)xRingbufferReceiveUpTo(buf_handle, &item_size, pdMS_TO_TICKS(50), uxBytesToSend); char *item = (char *)xRingbufferReceiveUpTo(buf_handle, &item_size, pdMS_TO_TICKS(50), uxBytesToSend);
@@ -327,12 +332,12 @@ static void handle_telnet_conn() {
struct telnetUserData *pTelnetUserData = (struct telnetUserData *)malloc(sizeof(struct telnetUserData)); struct telnetUserData *pTelnetUserData = (struct telnetUserData *)malloc(sizeof(struct telnetUserData));
tnHandle = telnet_init(my_telopts, handle_telnet_events, 0, pTelnetUserData); tnHandle = telnet_init(my_telopts, handle_telnet_events, 0, pTelnetUserData);
pTelnetUserData->rxbuf = (char *) heap_caps_malloc(TELNET_RX_BUF, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); pTelnetUserData->rxbuf = (char *) heap_caps_malloc(TELNET_RX_BUF, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
pTelnetUserData->tnHandle = tnHandle; pTelnetUserData->tnHandle = tnHandle;
pTelnetUserData->sockfd = partnerSocket; pTelnetUserData->sockfd = partnerSocket;
// flush all the log buffer on connect // flush all the log buffer on connect
process_logs(0); process_logs(log_buf_size, false);
while(1) { while(1) {
//ESP_LOGD(tag, "waiting for data"); //ESP_LOGD(tag, "waiting for data");
@@ -349,7 +354,7 @@ static void handle_telnet_conn() {
partnerSocket = 0; partnerSocket = 0;
return; return;
} }
process_logs(send_chunk); process_logs(send_chunk, false);
taskYIELD(); taskYIELD();
} }
@@ -358,37 +363,24 @@ static void handle_telnet_conn() {
// ******************* stdout/stderr Redirection to ringbuffer // ******************* stdout/stderr Redirection to ringbuffer
static ssize_t stdout_write(int fd, const void * data, size_t size) { static ssize_t stdout_write(int fd, const void * data, size_t size) {
if (xSemaphoreTake(xSemaphore, (TickType_t) 10) == pdTRUE) { // #1 Write to ringbuffer
// #1 Write to ringbuffer if (buf_handle == NULL) {
if (buf_handle == NULL) { printf("%s() ABORT. file handle _log_remote_fp is NULL\n",
printf("%s() ABORT. file handle _log_remote_fp is NULL\n", __FUNCTION__);
__FUNCTION__);
} else {
//Send an item
UBaseType_t res = xRingbufferSend(buf_handle, data, size,
pdMS_TO_TICKS(100));
if (res != pdTRUE) {
// flush some entries
process_logs(size);
res = xRingbufferSend(buf_handle, data, size,
pdMS_TO_TICKS(100));
if (res != pdTRUE) {
printf("%s() ABORT. Unable to store log entry in buffer\n",
__FUNCTION__);
}
}
}
xSemaphoreGive(xSemaphore);
} else { } else {
// We could not obtain the semaphore and can therefore not access // flush the buffer if needed
// the shared resource safely. process_logs(size, true);
//Send an item
UBaseType_t res = xRingbufferSend(buf_handle, data, size, pdMS_TO_TICKS(10));
assert(res == pdTRUE);
} }
return bMirrorToUART?write(uart_fd, data, size):true; return bMirrorToUART?write(uart_fd, data, size):size;
} }
static ssize_t stdout_read(int fd, void* data, size_t size) { static ssize_t stdout_read(int fd, void* data, size_t size) {
return read(fd, data, size); //return read(fd, data, size);
return 0;
} }
static int stdout_open(const char * path, int flags, int mode) { static int stdout_open(const char * path, int flags, int mode) {

View File

@@ -1,3 +1,4 @@
void init_telnet(); void init_telnet();
void start_telnet(void * pvParameter); void start_telnet(void * pvParameter);
extern bool is_serial_suppressed();

View File

@@ -25,6 +25,7 @@
#include "cmd_decl.h" #include "cmd_decl.h"
#include "console.h" #include "console.h"
#include "wifi_manager.h" #include "wifi_manager.h"
#include "telnet.h"
#include "cmd_squeezelite.h" #include "cmd_squeezelite.h"
#include "config.h" #include "config.h"
@@ -156,8 +157,19 @@ void initialize_console() {
void console_start() { void console_start() {
initialize_console(); if(!is_serial_suppressed()){
initialize_console();
}
else {
/* Initialize the console */
esp_console_config_t console_config = { .max_cmdline_args = 22,
.max_cmdline_length = 600,
#if CONFIG_LOG_COLORS
.hint_color = atoi(LOG_COLOR_CYAN)
#endif
};
ESP_ERROR_CHECK(esp_console_init(&console_config));
}
/* Register commands */ /* Register commands */
esp_console_register_help_command(); esp_console_register_help_command();
register_system(); register_system();
@@ -171,54 +183,64 @@ void console_start() {
#error "Unknown build configuration" #error "Unknown build configuration"
#endif #endif
register_i2ctools(); register_i2ctools();
printf("\n" if(!is_serial_suppressed()){
#if RECOVERY_APPLICATION printf("\n"
"****************************************************************\n" #if RECOVERY_APPLICATION
"RECOVERY APPLICATION\n" "****************************************************************\n"
"This mode is used to flash Squeezelite into the OTA partition\n" "RECOVERY APPLICATION\n"
"****\n\n" "This mode is used to flash Squeezelite into the OTA partition\n"
#endif "****\n\n"
"Type 'help' to get the list of commands.\n" #endif
"Use UP/DOWN arrows to navigate through command history.\n" "Type 'help' to get the list of commands.\n"
"Press TAB when typing command name to auto-complete.\n" "Use UP/DOWN arrows to navigate through command history.\n"
"\n" "Press TAB when typing command name to auto-complete.\n"
#if !RECOVERY_APPLICATION "\n"
"To automatically execute lines at startup:\n" #if !RECOVERY_APPLICATION
"\tSet NVS variable autoexec (U8) = 1 to enable, 0 to disable automatic execution.\n" "To automatically execute lines at startup:\n"
"\tSet NVS variable autoexec[1~9] (string)to a command that should be executed automatically\n" "\tSet NVS variable autoexec (U8) = 1 to enable, 0 to disable automatic execution.\n"
#endif "\tSet NVS variable autoexec[1~9] (string)to a command that should be executed automatically\n"
"\n" #endif
"\n"); "\n"
"\n");
/* Figure out if the terminal supports escape sequences */ /* Figure out if the terminal supports escape sequences */
int probe_status = linenoiseProbe(); int probe_status = linenoiseProbe();
if (probe_status) { /* zero indicates success */ if (probe_status) { /* zero indicates success */
printf("\n****************************\n" printf("\n****************************\n"
"Your terminal application does not support escape sequences.\n" "Your terminal application does not support escape sequences.\n"
"Line editing and history features are disabled.\n" "Line editing and history features are disabled.\n"
"On Windows, try using Putty instead.\n" "On Windows, try using Putty instead.\n"
"****************************\n"); "****************************\n");
linenoiseSetDumbMode(1); linenoiseSetDumbMode(1);
#if CONFIG_LOG_COLORS #if CONFIG_LOG_COLORS
/* Since the terminal doesn't support escape sequences, /* Since the terminal doesn't support escape sequences,
* don't use color codes in the prompt. * don't use color codes in the prompt.
*/ */
prompt = "squeezelite-esp32> "; prompt = "squeezelite-esp32> ";
#endif //CONFIG_LOG_COLORS #endif //CONFIG_LOG_COLORS
}
esp_pthread_cfg_t cfg = esp_pthread_get_default_config();
cfg.thread_name= "console";
cfg.inherit_cfg = true;
#if RECOVERY_APPLICATION
cfg.stack_size = 4096 ;
#endif
esp_pthread_set_cfg(&cfg);
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&thread_console, &attr, console_thread, NULL);
pthread_attr_destroy(&attr);
} }
esp_pthread_cfg_t cfg = esp_pthread_get_default_config(); else {
cfg.thread_name= "console"; #if !RECOVERY_APPLICATION
cfg.inherit_cfg = true; // process autoexec locally, as we're not going to start the console thread
#if RECOVERY_APPLICATION process_autoexec();
cfg.stack_size = 4096 ;
#endif #endif
esp_pthread_set_cfg(&cfg); }
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&thread_console, &attr, console_thread, NULL);
pthread_attr_destroy(&attr);
} }
void run_command(char * line){ void run_command(char * line){
/* Try to run the command */ /* Try to run the command */
@@ -226,14 +248,14 @@ void run_command(char * line){
esp_err_t err = esp_console_run(line, &ret); esp_err_t err = esp_console_run(line, &ret);
if (err == ESP_ERR_NOT_FOUND) { if (err == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG,"Unrecognized command: %s\n", line); ESP_LOGE(TAG,"Unrecognized command: %s", line);
} else if (err == ESP_ERR_INVALID_ARG) { } else if (err == ESP_ERR_INVALID_ARG) {
// command was empty // command was empty
} else if (err == ESP_OK && ret != ESP_OK) { } else if (err == ESP_OK && ret != ESP_OK) {
ESP_LOGW(TAG,"Command returned non-zero error code: 0x%x (%s)\n", ret, ESP_LOGW(TAG,"Command returned non-zero error code: 0x%x (%s)", ret,
esp_err_to_name(err)); esp_err_to_name(err));
} else if (err != ESP_OK) { } else if (err != ESP_OK) {
ESP_LOGE(TAG,"Internal error: %s\n", esp_err_to_name(err)); ESP_LOGE(TAG,"Internal error: %s", esp_err_to_name(err));
} }
} }
static void * console_thread() { static void * console_thread() {