Нужна помощь с анализом погодных предупреждений NWS JSON, вызывающих сброс на ESP8266.
Я пытаюсь проанализировать строку JSON из оповещений Национальной метеорологической службы и столкнулся с проблемой: код не может проанализировать значение, и устройство автоматически сбрасывается. Раньше я использовал этот код в другом API, чтобы получить текущие погодные условия, и это работает нормально. Я не уверен, что делаю неправильно, и буду очень признателен за любой совет или помощь. Спасибо!
Вот ошибка:
21:13:07.521 -> сброс wdt 21:13:07.521 -> загрузка 0x4010f000, len 3424, комната 16 21:13:07.521 -> хвост 0 21:13:07.521 -> контрольная сумма 0x2e 21:13:07.521 -> загрузка 0x3fff20b8, len 40, комната 8 21:13:07.521 -> хвост 0 21:13:07.521 -> контрольная сумма 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��_
И вот мой код:
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
const char* ssid = "mySSID"; // SSID локальной сети
const char* password = "myPassword"; // Пароль в сети
WiFiClient client;
char weatherServerName[] = "api.weather.gov";
String result;
//Для тестирования измените эту зону на любую зону NWS, в которой в настоящее время наблюдается предупреждение о погоде
//Найдите активную зону оповещения, перейдя на https://api.weather.gov/alerts/active и найдя код в поле "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"); //сообщение об ошибке, если клиент не подключается
Serial.println();
}
//ждём данных
while (client.connected() || client.available())
{ //подключено или данные доступны
char c = client.read(); // получает байт из буфера Ethernet
result = result+c;
}
client.stop(); //остановим клиент
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);
}
@user3481929, 👍1
Обсуждение2 ответа
Лучший ответ:
По умолчанию размер стека ограничен 4 КБ на ESP8266, поэтому вы не можете хранить там документ размером 8 КБ.
Чтобы устранить эту проблему, замените StaticJsonDocument
на DynamicJsonDocument
, чтобы переместить буфер в кучу.
См. также: Почему мое устройство выходит из строя или перезагружается?
В первой строке сообщения об ошибке содержится хорошая подсказка:
21:13:07.521 -> wdt reset
Сторожевой таймер ESP-8266 (WDT) перезагрузит устройство, если оно не было правильно «запитано» в течение определенного периода времени (тайм-аут сторожевого таймера).
Как заметил @Juraj, библиотеки ESP-8266 Arduino «полезно» добавляют каналы WDT в различные моменты, предполагая, что тайм-аут связан с тем, что ваш код либо дает сбой (переполнение в недопустимый программный код), либо истекает время ожидания (действительный код, но застрял в петле).
Информацию обратной трассировки, напечатанную при сбросе, можно использовать для определения места возникновения WDT конкретно в вашем коде, чтобы вы могли найти проблему (которая может быть той, которую заметил @Benoit Blanchon). Я обнаружил, что этот декодер исключений очень полезен для преобразования кода в функции вашего кода.
Также стоит отметить, что «искаженные символы» после информации обратной трассировки сброса WDT — это сообщение о запуске загрузчика, скорость которого фиксирована на 74880 бод. Вы можете изменить скорость передачи данных последовательного терминала, чтобы увидеть их (и «искажать» другие сообщения).
(Информация о сторожевых таймерах и кормлении ниже не имеет прямого отношения к данному случаю, как заметил @Juraj, но оставлена для контекста)
Это пример документа от TI, в котором представлены сторожевые таймеры. Для ESP8266 вы можете найти этот документ techtutorialsx более полезным. Таким образом, вам нужно либо отключить сторожевой таймер, либо периодически выдавать
ESP.wdtFeed();
команды. Отключение сторожевого таймера — это на первый взгляд простой вариант, но он отключает действительно полезный инструмент, который поможет вам более изящно обрабатывать непредвиденные условия/ошибки в вашем проекте/продукте, поэтому я бы посоветовал вам научиться его использовать, а затем накормите его, как указано выше.
(Как заметил @Benoit Blanchon, есть и другие проблемы реализации, которые следует решить и, возможно, заслуживают отдельного поста при проверке кода. Однако я хотел объяснить причину сброса, о котором вы спрашивали, а это не так. Это связано исключительно с JSON и будет продолжать происходить, если вы не предпримете действия, описанные выше)
здесь wdt не подается после сбоя, @Juraj
@Juraj, wdt вообще не подается, что приводит к сбросу wdt., @rolinger
на esp8266 подача wdt происходит автоматически, если цикл() заканчивается, с задержками, во многих вызовах функций, @Juraj
Спасибо @Juraj, обновлено соответственно., @rolinger
поэтому «размер стека на ESP8266 ограничен 4 КБ, поэтому вы не можете хранить там документ размером 8 КБ». для меня это хорошее объяснение аварии. «сброс wdt» — это просто отвлечение. Бенуа Бланшон — автор библиотеки ArduinoJson., @Juraj
- NodeMCU (Arduino IDE) «DynamicJsonBuffer» не был объявлен в этой области
- Чтение файла из SPIFFS в nodemcu с использованием ArduinoJson
- Последовательная связь от Arduino до ESP8266 NodeMCU работает, но от NodeMCU до Arduino не работает
- Проанализировать большой ответ json с помощью ESP8266
- Публиковать данные json в mqtt
- Какой максимальный размер статического документа Json в Arduino JSON?
- Чтение файла json из SPIFFS и отображение содержащейся в нем информации на встроенной веб-странице
- ESP8266 Arduino Json object array десериализация в структуру
распечатайте полученное, прежде чем пытаться его изменить, @jsotola