1

I'm trying to parse the JSON string from the National Weather Service Alerts and am encountering a problem where the code can't parse the value and the device auto-resets. I've used this code before on a different API to get the current weather conditions, and that works fine - I'm not sure what I'm doing wrong and would greatly appreciate any advice or help. Thanks!

Here is the error:

21:13:07.521 -> wdt reset
21:13:07.521 -> load 0x4010f000, len 3424, room 16 
21:13:07.521 -> tail 0
21:13:07.521 -> chksum 0x2e
21:13:07.521 -> load 0x3fff20b8, len 40, room 8 
21:13:07.521 -> tail 0
21:13:07.521 -> chksum 0x2b
21:13:07.521 -> csum 0x2b
21:13:07.521 -> v00045d00
21:13:07.521 -> ~ld
21:13:07.555 -> ����n�r��n|�l�l`b��|r�l�n��n�l`��r�l�l��

And here's my code:

#include <ESP8266WiFi.h>
#include <ArduinoJson.h>

const char* ssid     = "mySSID";                      // SSID of local network
const char* password = "myPassword";                 // Password on network                            

WiFiClient client;
char weatherServerName[] = "api.weather.gov";
String result;

//For testing change this zone to any zone from the NWS that's currently experiencing a weather alert
//Find an active alert area by going to https://api.weather.gov/alerts/active and looking for the code in the "affectedZones"
String zone = "LEZ144";                            


bool hasAlert = false;

void setup() { 
  Serial.begin(115200);  
  Serial.println("=====================================================================================================");   
  Serial.println("Connecting");

  WiFi.begin(ssid, password);
  
            while (WiFi.status() != WL_CONNECTED) 
            {
            delay(500);            
            Serial.print(".");            
            }
    
  Serial.println("Connected");
  delay(1000);
}

void loop() {
  Serial.println(":D");
  getWeatherAlerts();
  delay(100000);
}

void getWeatherAlerts()
{
  String server = weatherServerName;

  if (client.connect(server, 443))     
       {                                        
          client.println("GET /alerts/active?zone=" + zone);
          client.println("User-Agent: ArduinoWiFi/1.1");
          client.println("Connection: close");
          client.println();
          } 
  else {
         Serial.println("connection failed");        //error message if no client connect
         Serial.println();
       }

                                       //waits for data
  while (client.connected() || client.available())    
       {                                             //connected or data available
         char c = client.read();                     //gets byte from ethernet buffer
         result = result+c;
       }

  client.stop();                                      //stop client
  result.replace('[', ' ');
  result.replace(']', ' ');
  Serial.println(result);
  char jsonArray [result.length()+1];
  result.toCharArray(jsonArray,sizeof(jsonArray));
  jsonArray[result.length() + 1] = '\0';
  StaticJsonDocument<8196> root;
  DeserializationError error = deserializeJson(root, jsonArray);

  if (error)
    {      
      Serial.println("parseObject() failed");
    }


  String features = root["features"];
  
  Serial.println(features);

  if(features.length() == 0)
  {
    Serial.println(features);
    hasAlert = false;
  }  
  else
  {
    String severity = root["features"]["severity"];  
    Serial.println(severity);
    if(severity == "Moderate" || severity == "Severe")
    {
      hasAlert = true;      
    }
    else
    {
      hasAlert = false;
    }
  }

  Serial.println(hasAlert);
}
1
  • print what is received before you start trying to alter it
    – jsotola
    Commented Nov 15, 2023 at 6:51

2 Answers 2

6

By default, the size of the stack is limited to 4KB on ESP8266, so you cannot store an 8KB document there.

To fix this issue, replace the StaticJsonDocument with a DynamicJsonDocument to move the buffer to the heap.

See also: Why does my device crash or reboot?

2

There is a good clue in the first line of your reported error:

21:13:07.521 -> wdt reset

The ESP-8266 Watchdog Timer (WDT) will reset the device if it has not been correctly 'fed' for a period of time (the watchdog timeout).

As @Juraj noted, the ESP-8266 Arduino libraries 'helpfully' add WDT feeds at various points, suggesting the timeout is because your code is either crashing (overflowing into invalid program code) or is timing out (valid code, but stuck in a loop).

The backtrace information printed on the reset can be used to find where the WDT happened specifically in your code, so you can find the issue (which could be the one @Benoit Blanchon noted). I have found this exception decoder to be very useful to translate the code to the functions in your code.

Also worth noting that the 'garbled characters' after the WDT reset backtrace information is the bootloader startup message, which is fixed at 74880 baud, you can change baud rate of your serial terminal to see those (and 'garble' the other messages).

(Info about watchdog timers and feeding below isn't directly relevant in this case, as @Juraj noted, but is left in for context)

This is an example document from TI introducing watchdog timers. For the ESP8266, you might find this techtutorialsx document more useful. In summary, you need to either turn off the watchdog, or issue periodic

ESP.wdtFeed();

commands. Turning off the watchdog is an appealingly easy option, but it disables a really useful tool to help you to make your project/product handle unexpected conditions/bugs more gracefully, so I'd encourage you to learn how to use it and then feed it as above.

(As @Benoit Blanchon noted, there are other issues on the implementation, which should be addressed, and perhaps deserve a separate post in code review. However I wanted to explain the reason for the reset you asked about, which isn't specifically JSON-related, and will continue to occur unless you take action as above)

5
  • here the wdt is not fed after the crash
    – Juraj
    Commented Nov 15, 2023 at 17:42
  • @Juraj the wdt is not fed at all, which is causing the reported wdt reset.
    – rolinger
    Commented Nov 16, 2023 at 11:31
  • 1
    on esp8266 the wdt feeding is automatic if the loop() ends,in delays, in many function calls
    – Juraj
    Commented Nov 16, 2023 at 12:10
  • Thanks @Juraj, updated accordingly.
    – rolinger
    Commented Nov 16, 2023 at 14:00
  • 1
    so "the size of the stack is limited to 4KB on ESP8266, so you cannot store an 8KB document there." is for me a good explanation for the crash. the "wdt reset' is just a distraction. Benoit Blanchon is author of the ArduinoJson library
    – Juraj
    Commented Nov 16, 2023 at 15:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.