ESP32 Regex search for all iterations - c++

I am using Bluetooth and receiving a CSS gradient string like this:
(90deg, rgba(66, 68, 90, 1) 0%,rgba(72, 79, 164, 1) 100%)
I am using regex to pull out the "90" for the angle:
regex r_dir("([0-9]{2,3}deg)");
smatch m_dir;
regex_search(data, m_dir, r_dir);
string temp = m_dir[0].str();
int dir = atoi(temp.replace(temp.find("deg"), 3, "").c_str());
This works fine and I am able to get "90". I also need to pull out the colours (and their percentage). Unfortunately there is not built in function to return all matches in a string so I used an example I found online:
regex r_col("(rgba\\(([0-9]{1,3}(, |,|)){4}\\) [0-9]{1,3}%)");
sregex_iterator iter(data.begin(), data.end(), r_col);
sregex_iterator end;
while(iter != end)
{
Serial.println("fff");
for(unsigned i = 0; i < iter->size(); ++i)
{
Serial.println( (*iter)[i].str().c_str());
}
//Serial.println((*iter)[0].str().c_str());
++iter;
}
However not only does this not work, but it causes a crash on my ESP:
Guru Meditation Error: Core 0 panic'ed (Unhandled debug exception)
Debug exception reason: Stack canary watchpoint triggered (Btc_task)
Core 0 register dump:
PC : 0x400d38af PS : 0x00060e36 A0 : 0x800d399d A1 : 0x3ffcd5f0
A2 : 0x3ffcf110 A3 : 0x00000001 A4 : 0x3ffe1218 A5 : 0x3ffe53f4
A6 : 0x3ffc5868 A7 : 0x3ffe0e5f A8 : 0x3ffe0e5e A9 : 0x3f401aa4
A10 : 0x3ffcf110 A11 : 0x00000001 A12 : 0x0000007f A13 : 0x3ffe5354
A14 : 0x3ffc5868 A15 : 0x00000000 SAR : 0x00000010 EXCCAUSE: 0x00000001
EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff
Backtrace: 0x400d38af:0x3ffcd5f0 0x400d399a:0x3ffcd660 0x400d399a:0x3ffcd6d0 0x400d3b6d:0x3ffcd740 0x400d3856:0x3ffcd760 0x400d399a:0x3ffcd7d0 0x400d3b6d:0x3ffcd840 0x400d3856:0x3ffcd860 0x400d399a:0x3ffcd8d0 0x400d399a:0x3ffcd940 0x400d399a:0x3ffcd9b0 0x400d38cd:0x3ffcda20 0x400d38cd:0x3ffcda90 0x400d3ac1:0x3ffcdb00 0x400d3899:0x3ffcdb70 0x400d3ac1:0x3ffcdbe0 0x400d399a:0x3ffcdc50 0x400d3899:0x3ffcdcc0 0x400d38cd:0x3ffcdd30 0x400d38cd:0x3ffcdda0 0x400d399a:0x3ffcde10 0x400d399a:0x3ffcde80 0x400d3a69:0x3ffcdef0 0x400d3a69:0x3ffcdf60 0x400d3899:0x3ffcdfd0 0x400d399a:0x3ffce040 0x400d3b6d:0x3ffce0b0 0x400d3856:0x3ffce0d0 0x400d399a:0x3ffce140 0x400d3b6d:0x3ffce1b0 0x400d3856:0x3ffce1d0 0x400d399a:0x3ffce240 0x400d3899:0x3ffce2b0 0x400d38cd:0x3ffce320 0x400d38cd:0x3ffce390 0x400d399a:0x3ffce400 0x400d399a:0x3ffce470 0x400d3a69:0x3ffce4e0 0x400d3a69:0x3ffce550 0x400d3899:0x3ffce5c0 0x400d3ac1:0x3ffce630 0x400d399a:0x3ffce6a0 0x400d3b6d:0x3ffce710 0x400d3856:0x3ffce730 0x400d399a:0x3ffce7a0 0x400d3899:0x3ffce810 0x400d38cd:0x3ffce880 0x400d38cd:0x3ffce8f0 0x400d399a:0x3ffce960 0x400d399a:0x3ffce9d0 0x400d3a69:0x3ffcea40
Rebooting...
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5828
entry 0x400806ac
This is caused by (*iter)[i] although I don't know why. I found this GitHub issue on it but that's about it.
I've tried Regexp, specifically the example on iterating over a string. The example caused my ESP to crash however this example I found on an SO post causes no crash it just finds no matches:
ms.Target ((char *)data.c_str());
unsigned int count = ms.MatchCount ("(rgba\\(([0-9]{1,3}(, |,|)){4}\\) [0-9]{1,3}%)");
Serial.print ("Found ");
Serial.print (count);
Serial.println (" matches.");
for (int j = 0; j < count; j++)
{
Serial.print ("Capture number: ");
Serial.println (j, DEC);
Serial.print ("Text: '");
Serial.print (ms.GetCapture ((char *)data.c_str(), j));
Serial.println ("'");
}
with the output being:
Found 0 matches.
Does anyone know to match all occurrences on an ESP?

When using prototyping boards there is a through back of limited memory, moreover C is also limited to core dependencies.
I've fire up my NodeMcu board with ESP32 to test your approach.
Just use a simpler way of substring() to take directly the value from your string.
Instead of using regex use the following substring() -once your css doesn't change its key attributes but only values-. Then you can store the result inside variables and make your logic.
#include <iostream> // std::cout
int main ()
{
std::string css ("(90deg, rgba(66, 68, 90, 1) 0%,rgba(72, 79, 164, 1) 100%)");
std::cout << "DEG: " << css.substr(1,2) << '\n';
return 0;
}
Give it a try!

Related

Esp32: Guru Meditation Error: Core 1 panic'ed (StoreProhibited). Exception was unhandled

I am trying to figure out why this error is popping up in the serial monitor. I tried to figure out which area of the code is the problem. I am pretty sure that it is this one, because if I remove it the code runs. There are some more ModeClasses but they are almost the same. The only difference is the run function. But I don't think that this is the problem. Display class and Clock class I tried individually and they worked.
That's the error message:
//error message
Backtrace:0x40086071:0x3ffb27700x400d215d:0x3ffb2780 0x400d1262:0x3ffb27a0 0x400d12ef:0x3ffb27c0 0x400d13fe:0x3ffb2800 0x400d4019:0x3ffb2820
ELF file SHA256: 0000000000000000
Rebooting...
*!��␄Z�*␁����M�␎�Guru Meditation Error: Core 1 panic'ed (StoreProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x40086074 PS : 0x00060b30 A0 : 0x800d2160 A1 : 0x3ffb2770
A2 : 0x00000000 A3 : 0x00000000 A4 : 0x00000400 A5 : 0x00000000
A6 : 0x00ff0000 A7 : 0x00000040 A8 : 0x800d2dd4 A9 : 0x3ffb2740
A10 : 0x3ffb27d5 A11 : 0x00000000 A12 : 0x0000000a A13 : 0x00000001
A14 : 0x00060320 A15 : 0x00000001 SAR : 0x00000002 EXCCAUSE: 0x0000001d
EXCVADDR: 0x00000000 LBEG : 0x40086074 LEND : 0x4008607f LCOUNT : 0x0000003f
// thats the ModeClock.h file
#ifndef MODE_CLOCK_H
#define MODE_CLOCK_H
#include <Arduino.h>
#include "Mode.h"
#include "Clock.h"
#include "Display.h"
class ModeClock : public Mode
{
private:
Clock clock;
Display display;
public:
ModeClock(Clock c, Display d)
{
clock = c;
display = d;
}
void run() override;
};
#endif
Here is the .cpp file for the .h file
#include "ModeDate.h"
void ModeDate::run()
{
display.displayText(clock.getClockDate());
Serial.print(clock.getClockDate());
}
And here also the class Mode that is getting inherited by.
#define MODE_H
#ifdef MODE_H
class Mode
{
private:
/* data */
public:
void virtual run() = 0;
};
#endif
I read that it could come from trying to access an invalid memory address. That could happen if you use a pointer wrong. But I'm not using any pointer. Please help me I don't know how to get on with it! I'm really thankful for every tip.

Getting Guru Meditation Error when using DallasTemperature with Wifi.h on esp32

I'm getting this error, when trying to use Wifi + DallasTemperature && OneWire on my esp32. Temperature sensor is Gravity DS18B20.
When I don't use Wifi it works fine.
This is an error code
09:41:17.049 -> Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
09:41:17.082 ->
09:41:17.082 -> Core 1 register dump:
09:41:17.082 -> PC : 0x400d3b40 PS : 0x00060433 A0 : 0x800d4488 A1 : 0x3ffb2710
09:41:17.082 -> A2 : 0x3f40af28 A3 : 0x0000001c A4 : 0x0a4c4c55 A5 : 0x3ff49000
09:41:17.082 -> A6 : 0x00000020 A7 : 0x00000000 A8 : 0x800d3b15 A9 : 0x3ffb26d0
09:41:17.082 -> A10 : 0x00060420 A11 : 0x3ffc2cac A12 : 0x3ffc2ca4 A13 : 0xb33fffff
09:41:17.082 -> A14 : 0x00000001 A15 : 0x00000001 SAR : 0x00000020 EXCCAUSE: 0x0000001c
09:41:17.115 -> EXCVADDR: 0x0a4c4c55 LBEG : 0x400df328 LEND : 0x400df332 LCOUNT : 0x00000000
09:41:17.115 ->
09:41:17.115 ->
09:41:17.115 -> Backtrace:0x400d3b3d:0x3ffb27100x400d4485:0x3ffb2750 0x400d476c:0x3ffb2780 0x400d2782:0x3ffb27b0 0x400d53b7:0x3ffb2820
Here I have it decoded
Decoding 5 results
0x400d3b3d: OneWire::reset() at /home/suomi/Arduino/libraries/OneWire/util/OneWire_direct_gpio.h line 165
: (inlined by) OneWire::reset() at /home/suomi/Arduino/libraries/OneWire/OneWire.cpp line 172
0x400d4485: OneWire::search(unsigned char*, bool) at /home/suomi/Arduino/libraries/OneWire/OneWire.cpp line 388
0x400d476c: DallasTemperature::begin() at /home/suomi/Arduino/libraries/DallasTemperature/DallasTemperature.cpp line 113
0x400d2782: setup() at /home/suomi/Arduino/sketch_sep18a/sketch_sep18a.ino line 53
0x400d53b7: loopTask(void*) at /home/suomi/.arduino15/packages/esp32/hardware/esp32/2.0.0/cores/esp32/main.cpp line 38
also with backtracked lines in the files mentioned above
1. ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_io_desc[pin].mux);
2. DIRECT_MODE_INPUT(reg, mask);
3.if (!reset()) {
4.while (_wire->search(deviceAddress)) {
5.sensors.begin();
6.void loopTask(void *pvParameters)
{
setup();
And my executed code
#include <OneWire.h>
#include <DallasTemperature.h>
#include <WiFi.h>
// Wifi Settings
#define WIFI_NETWORK "name"
#define WIFI_PASSWORD "pass"
#define WIFI_TIMOUT_MS 20000
const int oneWireBus = 32;
OneWire oneWire(oneWireBus);
DallasTemperature sensors(&oneWire);
int status;
int connectToWiFi() {
Serial.println(" ");
Serial.print("Connencting to WiFi");
Serial.print(" ");
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_NETWORK, WIFI_PASSWORD);
unsigned long startAttemptTime = millis();
while(WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < WIFI_TIMOUT_MS) {
Serial.print(".");
delay(700);
}
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Failed connect to WiFi!");
return 0;
}
else {
Serial.print("Connected to WiFi");
Serial.println(WIFI_NETWORK);
Serial.println(WiFi.localIP());
return 1;
}
}
void setup() {
status = connectToWiFi();
Serial.begin(115200);
sensors.begin();
void loop() {
}
I'm not very good in c++, could someone please help me? LoadProhibited: It looks like it trying to access a memory that it shouldn't?
It's been a long time since I used Arduino libs on ESP32. Maybe Serial.begin() should be called before connectToWifi() because you call Serial methods before initializing it.

Cannot write to serial

I am using the ESP32 DevKitC-v1 (clone) with FreeRTOS and attempting to write bytes to the serial port.
My code (below) causes the following exception:
Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x400ea8fe PS : 0x00060730 A0 : 0x800eb825 A1 : 0x3ffdfdf0
A2 : 0x00000001 A3 : 0x00000055 A4 : 0x00000001 A5 : 0x00000000
A6 : 0x00000002 A7 : 0xff000000 A8 : 0x00000000 A9 : 0x60010000
A10 : 0x00000055 A11 : 0x00000001 A12 : 0x3ffdfd54 A13 : 0x3ffd1068
A14 : 0x00000000 A15 : 0x00000000 SAR : 0x00000004 EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000055 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff
Backtrace: 0x400ea8fe:0x3ffdfdf0 0x400eb822:0x3ffdfe10 0x400ebf0d:0x3ffdfe50 0x400e1511:0x3ffdfe80
Rebooting...
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:6372
load:0x40078000,len:11276
load:0x40080000,len:6084
entry 0x4008032c
I have been able to find limited information regarding FreeRTOS and UART operations, I apologise in advance however if I have missed something obvious. I have been trying to self resolve the issue for about 3 days now.
My code:
#define ECHO_TEST_TXD (GPIO_NUM_17)
#define ECHO_TEST_RXD (GPIO_NUM_16)
#define ECHO_TEST_RTS (UART_PIN_NO_CHANGE)
#define ECHO_TEST_CTS (UART_PIN_NO_CHANGE)
static void prvSerialRelayMQTTCommand()
{
const TickType_t xFiveSeconds = pdMS_TO_TICKS( 5000UL );
/* Configure parameters of an UART driver,
* communication pins and install the driver */
uart_config_t uart_config = {
.baud_rate = 9600,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(UART_NUM_2, &uart_config);
uart_set_pin(UART_NUM_2, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS);
uart_driver_install(UART_NUM_2, BUF_SIZE * 2, 0, 0, NULL, 0);
while (1) {
uart_write_bytes(UART_NUM_2, 0b00000000, 1);
vTaskDelay(xFiveSeconds);
uart_write_bytes(UART_NUM_2, 0b00000001, 1);
vTaskDelay(xFiveSeconds);
uart_write_bytes(UART_NUM_2, 0b00000011, 1);
vTaskDelay(xFiveSeconds);
uart_write_bytes(UART_NUM_2, 0b00000111, 1);
vTaskDelay(xFiveSeconds);
uart_write_bytes(UART_NUM_2, 0b00001111, 1);
vTaskDelay(xFiveSeconds);
}
}
Invalid pointer arguments
The second argument to uart_write_bytes() should be a const char * (see reference). You are passing it an invalid pointer.
Change
uart_write_bytes(UART_NUM_2, 0b00000000, 1);
to
char c = '\0';
uart_write_bytes(UART_NUM_2, &c, 1);
and similarly for the other calls.
However, this isn't necessarily your only problem.
Stack size for FreeRTOS task
A LoadProhibited error occurs when the ESP32 attempts to read or write an invalid memory address. The relevant address is stored in the EXCVADDR register - which in this case we can see is 0x00000055. This means that your calls to uart_write_bytes() (even though invalid) are not the cause of the reset - because you did not pass the address 0x00000055 in any of the calls.
I suspect your problem is that you are not allocating a large enough stack for your FreeRTOS task. If you create a task with a stack size of configMINIMAL_STACK_SIZE, for example, that might not be enough for using the UART. A stack overflow would also result in a LoadProhibited error.
The stack size is the third parameter passed to xTaskCreate(). Try verifying that it is at least 1024, and increase as needed.

C++ Read file stream from terminal line by line with only one command

Short: I want to read data from the terminal into a variable and compare it with a string.
Long: I am using a TI AM3358 development board from GOEMBED which runs embedded linux. I use this kit to read data from a canbus. To read the data from the canbus into the terminal I use socketcan.
When I run the following command into the terminal I get a datastream of can messages from the bus.
candump can0
I wrote some code which execute the above command and returns the output.
string GetCmdOutput(const char * cmd)
{
char buffer[128];
string result = "";
string different;
FILE* pipe = popen(cmd,"r");
int counter=0;
if(!pipe) throw runtime_error("popen() failed!");
try {
if(fgets(buffer,128,pipe) !=NULL){
while(counter<1){
result +=buffer;
counter++;
}
}
}catch(...){
pclose(pipe);
throw;
}
pclose(pipe);
return result;
}
In int main() I run the following code which compares the terminal output to a string:
string dump = "candump can0";
const char *senddump;
senddump = dump.c_str();
string newOutput;
int senddata = 0;
int i = 0;
int x = 0;
int amountS = 0;
int y = 0;
string datas;
while(i<1)
{
newOutput = GetCmdOutput(senddump);
cout<<newOutput + "\n";
if(newOutput==" can0 000 [2] 01 12\n")
{
canWrite(busn,baudrate, sendID, dlcn,data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]);
}
}
The code itself works, but I miss a lot of data from the canbus. I think the reason for this is that I always need to reinitialize the canbus (cmd --> candump can0).
Now my question is: How to change my code that I only need to run the command "candump can0" ones and that the code always compares the next messafes to the string. If this is possible, I think I will gain already a lot of perfomance.
If you have other commands or other options to improve the performancy, pleas do not hesitate to give constructive critisisme. (I'm not a professional! I try to learn)
/ EDIT 1 /
The following datastream is how it is outputted into the terminal
can0 712 [1] 05
can0 192 [6] 1C 0F 19 00 00 00
can0 70B [1] 00
can0 70B [1] 85
can0 703 [1] 00
can0 707 [1] 00
can0 709 [1] 00
Thanks in advance,
Kind regards,
TMO
If there is continual output from candump you could simply pipe the output to your program like this:
$ candump can0 | myprogram
Where myprogram.cpp looks a bit like this:
#include <iostream>
#include <string>
int main()
{
std::string message;
while(std::getline(std::cin, message))
{
// process message here ... eg. ...
if(message == "can0 000 [2] 01 12")
{
// do something specific ...
}
}
}

Create an Arduino ESP8266 library

I would like to create a Arduino library for an ESP8266or ESP32 microcontroller. I wrote a test library which running on an Arduino Nano board with no problem. Here the library cpp file:
#include "Test.h"
Test::Test(){
}
uint32_t Test::libTest(strcttest* t){
uint32_t w;
w = t->a;
return w;
}
Here's the the header file :
#include <Arduino.h>
typedef struct {
uint32_t a;
uint32_t b;
}strcttest;
class Test
{
public:
Test();
uint32_t libTest(strcttest* t);
private:
};
And last but not least the Arduino ino file:
#include <Test.h>
//Instante Test
Test t;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("Start");
}
void loop() {
// put your main code here, to run repeatedly:
//Create structure
strcttest *tt;
tt->a=1;
tt->b=2;
//Output result
Serial.println (t.libTest(tt));
delay(1000);
}
Every compile fine with an Arduino Nano board as well as with ESP8266/ESP32 boards. When I run it on the Nano Board i get the expected result:
Start
1
1
1
1
1
1
1
1
1
...
When I run it on the ESP8266 board I get the following crash result:
l*⸮⸮⸮⸮CI>⸮⸮⸮HB⸮⸮Start
Exception (28):
epc1=0x402024f8 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
ctx: cont
sp: 3ffef7d0 end: 3ffef9a0 offset: 01a0
>>>stack>>>
3ffef970: feefeffe 00000000 3ffee950 40201eb4
3ffef980: feefeffe feefeffe 3ffee96c 40202340
3ffef990: feefeffe feefeffe 3ffee980 40100108
<<<stack<<<
7!a!*6⸮⸮⸮Start
Exception (28):
epc1=0x402024f8 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
ctx: cont
sp: 3ffef7d0 end: 3ffef9a0 offset: 01a0
>>>stack>>>
3ffef970: feefeffe 00000000 3ffee950 40201eb4
3ffef980: feefeffe feefeffe 3ffee96c 40202340
3ffef990: feefeffe feefeffe 3ffee980 40100108
<<<stack<<<
ĜBs⸮`⸮"⸮⸮Start
...
And last but not least on the ESP Development board I receive:
i%M/⸮`⸮i%M7
⸮⸮%Q=qU=\Md⸮aGd<$⸮Start
Guru Meditation Error of type LoadProhibited occurred on core 1. Exception was unhandled.
Register dump:
PC : 0x400dde93 PS : 0x00060030 A0 : 0x800d0570 A1 : 0x3ffc7390
A2 : 0x3ffc1c30 A3 : 0x00000000 A4 : 0x0800001c A5 : 0xffffffff
A6 : 0xffffffff A7 : 0x00060d23 A8 : 0x800832e9 A9 : 0x3ffc7380
A10 : 0x00000003 A11 : 0x00060023 A12 : 0x00060020 A13 : 0x00000003
A14 : 0x00000001 A15 : 0x00000000 SAR : 0x0000001f EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff
Backtrace: 0x400dde93:0x3ffc7390 0x400d0570:0x3ffc73b0 0x400d79b0:0x3ffc73d0
CPU halted.
So my question is: What I am doing wrong. What do i miss. What I haven't understood with Arduino IDE, cpp, pointers, etc.
Sorry I forgot: I use Arduino IDE 1.8.2
strcttest *tt; is your problem. You're not allocating memory for and creating an object of type strcttest - you're merely allocating memory for a pointer to an object of that type. Basically, the code should crash everywhere when your code gets to the line tt->a=1; The fact that it doesn't when run on the Nano is basically dumb luck..
Think of the case where you have a char* variable and then try to copy a string to it - it will crash too, since you dont have any storage space for the string itself - you only have a few bytes allocated that store the address of the string.
The following is a more reasonable implementation of your void loop() function:
void loop() {
// put your main code here, to run repeatedly:
//Create structure
strcttest tt;
tt.a=1;
tt.b=2;
//Output result
Serial.println (t.libTest(&tt));
delay(1000);
}
Another (slower, due to use of new and delete) implementation may look like this:
void loop() {
// put your main code here, to run repeatedly:
//Create structure
strcttest *tt = new strcttest;
tt->a=1;
tt->b=2;
//Output result
Serial.println (t.libTest(tt));
delete tt;
delay(1000);
}
For ESP32 and ESP8266, have a excellent tool to help in crashes situations,
like that You report.
This integrates to Arduino IDE
See it in: https://github.com/me-no-dev/EspExceptionDecoder