1

Problem

I send sensor measurements from an Arduino to -> AWS APIGateway -> Lambda -> CloudWatch, which works but only for a couple of minutes, then a stack-trace is shown and the program stops.

Request

I search for solutions, which ..

  • avoides the stack trace
  • recovers from the stack trace and starts over
  • speed up sending data (as close to once every second as possible!)
  • still collect data points during sending/receiving data (if I add the uncommented part during receiving the response nothing is happening) -> Parallel execution?

Tried so far

I so far observed that it may be a time issue, as with more "delay" it takes longer to receive the error. I really just want to write the data and therefore uncomment my code part which reads the APIGateway response, this way the error comes sooner. I already looked up the related issue on Github, but nothing solved my problem.

Specs

  • NodeMCU v2 including ESP8266
  • LM393 noise sensor
  • MacBook for development

The bare output:

...
Request: { "id": "S3", "noise": 41 , "ip": "192.168.178.20" }

Exception (29):
epc1=0x4020c612 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000004 depc=0x00000000

ctx: cont 
sp: 3fff0010 end: 3fff0530 offset: 01a0

>>>stack>>>
3fff01b0:  00820000 00000082 3fff57cc 40219652  
3fff01c0:  3ffef4b0 3fff5f44 3fff57cc 4021984c  
3fff01d0:  3fffba7c 00000208 3fffba7c 40100670  
3fff01e0:  00000104 0000b018 00001603 00000042  
3fff01f0:  00000040 00000082 3fff7dd4 40219b65  
3fff0200:  00800000 00000080 00000000 00000041  
3fff0210:  00000040 0000003f 3fff6164 00000041  
3fff0220:  3fffb664 3fff7dd4 3fff6164 3fff6f34  
3fff0230:  3fffbb78 ffffffff 3fff5f44 40204c04  
3fff0240:  00000040 3fff5f44 3fff7dd4 3fff5f44  
3fff0250:  00000040 3fff5f44 3fff7dd4 4021a69f  
3fff0260:  3fff67b4 0000003f a5c6bfaf 00000001  
3fff0270:  3fff5f44 3fff6a04 3fff7dd4 00000001  
3fff0280:  00000010 3fff5f44 0000000f 4021a8f4  
3fff0290:  3fff6164 3fff9b1c 0000000f 00000001  
3fff02a0:  00000001 3fff68bc 3fff3872 402196f8  
3fff02b0:  00000100 3fff96fc 3fff3847 00000000  
3fff02c0:  00000100 3fff96fc 3fff3847 4021ba7d  
3fff02d0:  3fff0300 00000000 000000d0 00000030  
3fff02e0:  b9a842ca 3fff68c8 3fff6170 00000004  
3fff02f0:  3fff3841 3fffa794 3fff3841 40216778  
3fff0300:  eb090303 4fed87e4 8f9aa767 9126663e  
3fff0310:  ea791a25 f4e54d08 e2cb4f3b da7af472  
3fff0320:  3d042744 7d12ab50 1cecee1e 42cab262  
3fff0330:  3fff3841 00000004 3fffa794 40216c0d  
3fff0340:  fa036a52 f16613d1 c13f331a 40213cd0  
3fff0350:  f6658dd1 3fffc6fc 3ffef510 4020f835  
3fff0360:  00000000 00000004 00000004 40203688  
3fff0370:  00000012 00001192 00000064 40204bc4  
3fff0380:  00000050 00000000 00000032 00000004  
3fff0390:  3fff3841 00000004 3fffa794 00000004  
3fff03a0:  3fff3841 00000004 3fffa794 40216580  
3fff03b0:  d7c44818 00000131 00000131 0000002d  
3fff03c0:  00000062 3fff3841 3fffa794 4021695c  
3fff03d0:  00000016 3fff3874 3fffa794 401004d8  
3fff03e0:  3fff0438 0000000e 00000010 3fff3044  
3fff03f0:  4020343c 3fffa794 3fff0430 01000000  
3fff0400:  3fff0438 00029c3d 3fffa794 402166e8  
3fff0410:  3fffa794 3fff13ec 3fff14ec 3fff3044  
3fff0420:  3fff241c 00029c3d 3fff14ec 40203e25  
3fff0430:  3fffa794 3fff13ec 40204b4c 3ffef510  
3fff0440:  00003a98 00003a98 00003a98 4020136f  
3fff0450:  3ffef248 00000000 3fff241c 00000029  
3fff0460:  000001bb 3ffe8a09 3ffef248 40204073  
3fff0470:  000001bb 3ffef248 3ffe8a09 00000029  
3fff0480:  000001bb 3ffef248 3ffe8a09 40204119  
3fff0490:  40107158 ce653134 40107158 ce653134  
3fff04a0:  3ffe8a09 3ffef248 3ffef240 402022d4  
3fff04b0:  40244290 00000004 00000000 4023d5cd  
3fff04c0:  4023d631 60000a00 00000000 3fffdad0  
3fff04d0:  004b004b 004b004b 004b004b 004b004b  
3fff04e0:  00000000 00000026 40238168 3ffef4f4  
3fff04f0:  402013fa 0000001c 00000000 3ffef4fc  
3fff0500:  3fffdad0 3ffef244 3ffef240 4020245c  
3fff0510:  3fffdad0 00000000 3ffef4f4 40204b98  
3fff0520:  feefeffe feefeffe 3ffef510 40100710  
<<<stack<<<
⸮⸮؁⸮

The decoded stack trace:

Decoding 36 results
0x40219652: more_comps at crypto/bigint.c line 672
0x4021984c: alloc at crypto/bigint.c line 672
0x40100670: _umm_realloc at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/cores/esp8266/umm_malloc/umm_malloc.c line 1641
:  (inlined by) realloc at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/cores/esp8266/umm_malloc/umm_malloc.c line 1715
0x40219b65: regular_multiply at crypto/bigint.c line 672
0x40204c04: optimistic_yield at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/cores/esp8266/core_esp8266_main.cpp line 57
0x4021a69f: bi_barrett at crypto/bigint.c line 1289
0x4021a8f4: bi_mod_power at crypto/bigint.c line 1414
0x402196f8: trim at crypto/bigint.c line 672
0x4021ba7d: RSA_public at crypto/rsa.c line 254
:  (inlined by) RSA_encrypt at crypto/rsa.c line 288
0x40216778: send_client_key_xchg at ssl/tls1_clnt.c line 409
0x40216c0d: do_clnt_handshake at ssl/tls1_clnt.c line 123
0x40213cd0: mem_free at /local/users/gauchard/arduino/arduino_esp8266/origin/tools/sdk/lwip2/builder/lwip2-src/src/core/mem.c line 152
0x4020f835: pbuf_free_LWIP2 at /local/users/gauchard/arduino/arduino_esp8266/origin/tools/sdk/lwip2/builder/lwip2-src/src/core/pbuf.c line 1306
0x40203688: ClientContext::_consume(unsigned int) at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp line 310 (discriminator 1)
:  (inlined by) ClientContext::read(char*, unsigned int) at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/libraries/ESP8266WiFi/src/include/ClientContext.h line 253 (discriminator 1)
0x40204bc4: __yield at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/cores/esp8266/core_esp8266_main.cpp line 57
0x40216580: do_handshake at ssl/tls1.c line 2007
:  (inlined by) basic_read at ssl/tls1.c line 1483
0x4021695c: do_client_connect at ssl/tls1_clnt.c line 168
0x401004d8: malloc at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/cores/esp8266/umm_malloc/umm_malloc.c line 1668
0x4020343c: SSLContext::_delete_shared_SSL(SSL_*) at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp line 310 (discriminator 1)
0x402166e8: ssl_read at ssl/tls1.c line 2007
0x40203e25: SSLContext::connect(ClientContext*, char const*, unsigned int) at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp line 310 (discriminator 1)
0x40204b4c: esp_yield at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/cores/esp8266/core_esp8266_main.cpp line 57
0x4020136f: delay at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/cores/esp8266/core_esp8266_wiring.c line 51
0x40204073: WiFiClientSecure::_connectSSL(char const*) at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp line 310 (discriminator 1)
0x40204119: WiFiClientSecure::connect(char const*, unsigned short) at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp line 310 (discriminator 1)
0x40107158: sntp_get_current_timestamp at ?? line ?
0x40107158: sntp_get_current_timestamp at ?? line ?
0x402022d4: loop_send_post(int) at /var/folders/ld/dws59xv93p15208nvrw7tt9w0000gn/T/arduino_modified_sketch_158237/HTTPSRequest.ino line 86
0x40244290: pm_wakeup_init at ?? line ?
0x4023d5cd: test_tout at ?? line ?
0x4023d631: test_tout at ?? line ?
0x40238168: system_adc_read at ?? line ?
0x402013fa: __analogRead at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/cores/esp8266/core_esp8266_wiring_analog.c line 33
0x4020245c: loop at /var/folders/ld/dws59xv93p15208nvrw7tt9w0000gn/T/arduino_modified_sketch_158237/HTTPSRequest.ino line 52
0x40204b98: loop_wrapper at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/cores/esp8266/core_esp8266_main.cpp line 57
0x40100710: cont_norm at /Users/lony/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/cores/esp8266/cont.S line 109

The sketch/code I use:

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

static const String         SYSTEM_NAME = "S3";

static const char*          WIFI_SSID = "SSID...";
static const char*          WIFI_PASSWORD = "PW...";
static String               local_ip;

static const char*          TARGET_HOST = "host.com";
static const int            TARGET_PORT = 443;
static const String         TARGET_URL = "/v1/noise-data-receiver";
static const char*          TARGET_SSL_SHA1_FINGERPRINT = "8D ....2"; // To retrieve use web browser

static const int            BAUD_RATE = 9600;
static const int            PIN_SENSOR = A0;
static const int            PIN_LED = LED_BUILTIN;

static WiFiClientSecure     client;

static const int            THRESHOLD_NOISE = 100;
static int                  level = 0;

static const unsigned long  REFRESH_INTERVAL = 1000; // ms
static unsigned long        lastRefreshTime = 0;

void setup() {

  pinMode(PIN_LED, OUTPUT);
  Serial.begin(BAUD_RATE);  
  setup_wifi();
}

void loop() {

  // Fetch noise level
  digitalWrite(PIN_LED, LOW);
  level = analogRead(PIN_SENSOR);
  digitalWrite(PIN_LED, HIGH);   

  // Send HTTP POST request (every s)
  if(millis() - lastRefreshTime >= REFRESH_INTERVAL) {  
    // Send request
    loop_send_post(level);

    lastRefreshTime += REFRESH_INTERVAL;
  }
}

/*
 * LIBS 
 */

void setup_wifi() {

  Serial.println();
  Serial.println();
  Serial.print("Connecting system [" + SYSTEM_NAME + "] to WIFI ");
  Serial.print(WIFI_SSID);

  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.print("Connected - ");

  local_ip = WiFi.localIP().toString();
  Serial.print("IP address: ");
  Serial.print(local_ip);
  Serial.println();
}

void loop_send_post(int level) {

  // Connect 
  if (!client.connect(TARGET_HOST, TARGET_PORT)) {
    Serial.println("connection failed");
    return;
  }

  // Speed up sending
  client.setNoDelay(true);

  // Verify TLS
  if (!client.verify(TARGET_SSL_SHA1_FINGERPRINT, TARGET_HOST)) {
    Serial.println("certificate doesn't match");
    return;
  }

  // Send
  String body_json = "{ \"id\": \"" + SYSTEM_NAME + "\", \"noise\": " + String(level) + " , \"ip\": \"" + local_ip + "\" }";
  client.print("POST " + TARGET_URL + " HTTP/1.1\r\n" +
               "Host: " + TARGET_HOST + "\r\n" +
               "Connection: close\r\n" + 
               "User-Agent: ESP8266\r\n" +
               "x-api-key: GEeGwazU1Ia2h6rZH6e0y4jwlxhjVurT9OWbOed4\r\n" +
               "Cache-Control: no-cache\r\n" +
               "Content-Type: application/json\r\n" +
               "Content-Length: " + body_json.length() + "\r\n" +
               "\r\n" +
               body_json);
  Serial.println();
  Serial.println();
  Serial.println("Request: " + body_json);

//  // Wait for response
//  unsigned long timeout = millis();  
//  while (client.available() == 0) {
//    
//    if (millis() - timeout > 5000) {
//      Serial.println(">>> Client Timeout !");
//      client.stop();
//      return;
//    }
//  }
//
//  Serial.println("Response: ");
//  while(client.available()){
//    String line = client.readStringUntil('\r');
//    Serial.print(line);
//  }
}
  • 1
    Can you please move the declarion of your WiFiClientSecure client in your loop_send_post function to force the destruction of that object at the end of the function? Sounds like your client leaks memory because the session is never closed properly.. Maybe try calling client.stop() after sending your request, too? – Maximilian Gerhardt Mar 16 '18 at 9:50
  • It is already running more stable thank you. Still there are delays in the execution. Do you know if there is a tool to analyse memory leaks more detailed? – lony Mar 16 '18 at 19:14
  • 1
    1 second to do a TLS handshake with huge RSA certs is kinda hard on your ESP8266, so I would not expect new sessions to be established that fast. If you want less delay you should .connect() in your setup once and use Connection: keep-alive to POST as many times as possble before re-establishing the connection (and handshake). Regarding memleaks: You can print the amount of available heap memory anytime by using the ESP.getFreeHeap() function. – Maximilian Gerhardt Mar 16 '18 at 23:17
  • If you can fully solve this problem you should post an answer yourself afterwards to close the question – Maximilian Gerhardt Mar 17 '18 at 10:00
  • Will do but so far I only succeeded running the job consistently by moving the client into the function. Everything else needs another week. – lony Mar 17 '18 at 17:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.