Как прочитать вторую строку ответа от сервера OpenWeatherMap
- Войдите на сайт для отправки комментариев
Чт, 13/08/2020 - 21:24
Помогите правильно написать код для парсинга погоды с сайта OpenWeatherMap.
Суть проекта проста: К Arduino Uno подключен модуль ESP-01. Подключаемся по WI-FI, делаем запрос на сайт. Приходит ответ. Но разобрать я могу только 1-ую строку. Это +IPD,792:HTTP/1.1. Я так понимаю что длина сообщения, которое содержит данные о погоде и находится во второй строке - 792. А вот как получить правильно вторую строку в цикле while(dbgSerial.available()), я не понимаю. Все облазил в интернете - ничего похожего не нашел. Может надо вообще по другому получать данные. Вот код, который у меня - Он довольно простой:
#include <ArduinoJson.h>
#include <SoftwareSerial.h>
#define SSID "DFCT" // введите ваш SSID
#define PASS "Dp#qTR82" // введите ваш пароль
#define LOCATIONID "2925533" // id местоположения
//#define DST_IP "188.226.224.148" //api.openweathermap.org
#define DST_IP "api.openweathermap.org"
const char* api = "d90c71098446021e66e71a6aaf4dd69c"; //Мой API ключ (Он ложный - Изменил для конспирации)
const char* city = "518970"; //ID моего города
String line;
String line2;
bool pr = false;
SoftwareSerial dbgSerial(3, 4); // RX, TX для отладки
StaticJsonDocument<500> root;
void setup()
{
Serial.begin(115200);
Serial.setTimeout(5000);
dbgSerial.begin(115200); // для отладки
Serial.println("Init");
dbgSerial.println("AT+RST"); // сброс и проверка, если модуль готов
delay(6000);
// try to connect to wifi
boolean connected=false;
for(int i=0;i<5;i++){
if(connectWiFi()){
connected = true;
Serial.println("Connected to WiFi...");
break;
}
delay(1000);
}
if (!connected){
Serial.println("Coudn't connect to WiFi.");
while(1);
}
delay(5000);
dbgSerial.println("AT+CIPMUX=0"); // установка в режим одиночного соединения
}
void loop()
{
String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += DST_IP;
cmd += "\",80";
dbgSerial.println(cmd);
Serial.println(cmd);
if(dbgSerial.find("Error")) return;
cmd = "GET /data/2.5/weather?id=" + String(city) + "&appid=" + String(api);
cmd += " HTTP/1.0\r\nHost: api.openweathermap.org\r\n\r\n";
dbgSerial.print("AT+CIPSEND=");
dbgSerial.println(cmd.length());
if(dbgSerial.find(">")){
Serial.print(">");
}
else
{
dbgSerial.println("AT+CIPCLOSE");
Serial.println("connection timeout");
delay(1000);
return;
}
Serial.println(cmd);
dbgSerial.println(cmd);
delay(3000);
if(dbgSerial.find("SEND OK"))
{
Serial.println("Request send");
//delay(5000);
}
Serial.println("Begin JSON");
while(dbgSerial.available()){ //Если получили ответ от сервера...
line = dbgSerial.readStringUntil('\n'); // +IPD,792:HTTP/1.1
}
Serial.println(line);
DeserializationError error = deserializeJson(root, line);
// Test if parsing succeeds.
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
delay(5000);
//return;
}
double temp = root["temp"];
double pressure = root["pressure"];
double humidity = root["humidity"];
temp -= 273.15; // Перевод градусов кельвины-цельсии
Serial.println(temp);
Serial.println(pressure);
Serial.println(humidity);
Serial.println("====");
delay(600000);
}
boolean connectWiFi()
{
dbgSerial.println("AT+CWMODE=1");
String cmd="AT+CWJAP=\"";
cmd+=SSID;
cmd+="\",\"";
cmd+=PASS;
cmd+="\"";
Serial.println(cmd);
dbgSerial.println(cmd);
delay(2000);
if(dbgSerial.find("OK")){
Serial.println("OK, Connected to WiFi.");
return true;
}else{
Serial.println("Can not connect to the WiFi.");
return false;
}
}
Конечно я оплачу в разумных пределах
"Разумный предел" это сколько?
После "792:" начинается HTTP-заголовок, который заканчивается 2-мя пустыми строками. Спросить "что такое HTTP?" и про его формат можно у гугла. После заголовка идёт JSON. Для JSON-а никакие строки не важны - это просто поток символов. Спросить "что такое JSON?" и про его формат можно там же, где и про HTTP.
После "792:" читаем поток символов, парсим его на лету в HTTP-заголовок (пока он не исчерпается (по 2-м пустым строкам)); потом также парсим JSON пока не исчерпается весь объём в 792 байта.