Как прочитать вторую строку ответа от сервера OpenWeatherMap

Mihay
Offline
Зарегистрирован: 07.08.2020

Помогите правильно написать код для парсинга погоды с сайта OpenWeatherMap.

Суть проекта проста: К Arduino Uno подключен модуль ESP-01. Подключаемся по WI-FI, делаем запрос на сайт. Приходит ответ. Но разобрать я могу только 1-ую строку. Это +IPD,792:HTTP/1.1. Я так понимаю что длина сообщения, которое содержит данные о погоде и находится во второй строке - 792. А вот как получить правильно вторую строку  в цикле while(dbgSerial.available()), я не понимаю. Все облазил в интернете - ничего похожего не нашел. Может надо вообще по другому получать данные. Вот код, который у меня - Он довольно простой: 

001#include <ArduinoJson.h>
002#include <SoftwareSerial.h>
003 
004#define SSID "DFCT" // введите ваш SSID
005#define PASS "Dp#qTR82" // введите ваш пароль
006#define LOCATIONID "2925533" // id местоположения
007//#define DST_IP "188.226.224.148" //api.openweathermap.org
008#define DST_IP "api.openweathermap.org"
009 
010const char* api = "d90c71098446021e66e71a6aaf4dd69c";   //Мой API ключ (Он ложный - Изменил для конспирации)
011const char* city = "518970";               //ID моего города
012String line;
013String line2;
014bool pr = false;
015 
016SoftwareSerial dbgSerial(3, 4); // RX, TX для отладки
017StaticJsonDocument<500> root;
018 
019void setup()
020{
021  Serial.begin(115200);
022  Serial.setTimeout(5000);
023  dbgSerial.begin(115200); // для отладки
024  Serial.println("Init");
025  dbgSerial.println("AT+RST"); // сброс и проверка, если модуль готов
026  delay(6000);
027  // try to connect to wifi
028  boolean connected=false;
029  for(int i=0;i<5;i++){
030    if(connectWiFi()){
031      connected = true;
032      Serial.println("Connected to WiFi...");
033      break;
034    }
035    delay(1000);
036  }
037  if (!connected){
038    Serial.println("Coudn't connect to WiFi.");
039    while(1);
040  }
041  delay(5000);
042  dbgSerial.println("AT+CIPMUX=0"); // установка в режим одиночного соединения
043}
044void loop()
045{
046  String cmd = "AT+CIPSTART=\"TCP\",\"";
047  cmd += DST_IP;
048  cmd += "\",80";
049  dbgSerial.println(cmd);
050  Serial.println(cmd);
051  if(dbgSerial.find("Error")) return;
052  cmd = "GET /data/2.5/weather?id=" + String(city) + "&appid=" + String(api);
053  cmd += " HTTP/1.0\r\nHost: api.openweathermap.org\r\n\r\n";
054 
055  dbgSerial.print("AT+CIPSEND=");
056  dbgSerial.println(cmd.length());
057  if(dbgSerial.find(">")){
058    Serial.print(">");
059  }
060  else
061  {
062    dbgSerial.println("AT+CIPCLOSE");
063    Serial.println("connection timeout");
064    delay(1000);
065    return;
066  }
067  Serial.println(cmd);
068  dbgSerial.println(cmd);
069  delay(3000);
070  if(dbgSerial.find("SEND OK"))
071  {
072    Serial.println("Request send");
073    //delay(5000);
074  
075  Serial.println("Begin JSON");
076 
077  while(dbgSerial.available()){              //Если получили ответ от сервера...
078    line = dbgSerial.readStringUntil('\n');  // +IPD,792:HTTP/1.1
079  }
080  Serial.println(line);
081    
082 DeserializationError error = deserializeJson(root, line);
083 
084  // Test if parsing succeeds.
085  if (error) {
086    Serial.print(F("deserializeJson() failed: "));
087    Serial.println(error.c_str());
088    delay(5000);
089    //return;
090  }
091  double temp = root["temp"];
092  double pressure = root["pressure"];
093  double humidity = root["humidity"];
094  temp -= 273.15; // Перевод градусов кельвины-цельсии
095  Serial.println(temp);
096  Serial.println(pressure);
097  Serial.println(humidity);
098  Serial.println("====");
099  
100  delay(600000);
101}
102  
103boolean connectWiFi()
104{
105  dbgSerial.println("AT+CWMODE=1");
106  String cmd="AT+CWJAP=\"";
107  cmd+=SSID;
108  cmd+="\",\"";
109  cmd+=PASS;
110  cmd+="\"";
111  Serial.println(cmd);
112  dbgSerial.println(cmd);
113  delay(2000);
114  if(dbgSerial.find("OK")){
115    Serial.println("OK, Connected to WiFi.");
116    return true;
117  }else{
118    Serial.println("Can not connect to the WiFi.");
119    return false;
120  }
121}
 
Mihay
Offline
Зарегистрирован: 07.08.2020

Конечно я оплачу в разумных пределах

hamann
Offline
Зарегистрирован: 17.08.2015

"Разумный предел" это сколько? 

rst
Offline
Зарегистрирован: 25.06.2018

Mihay пишет:
Это +IPD,792:HTTP/1.1. Я так понимаю что длина сообщения, которое содержит данные о погоде и находится во второй строке - 792. А вот как получить правильно вторую строку

После "792:" начинается HTTP-заголовок, который заканчивается 2-мя пустыми строками. Спросить "что такое HTTP?" и про его формат можно у гугла. После заголовка идёт JSON. Для JSON-а никакие строки не важны - это просто поток символов. Спросить "что такое JSON?" и про его формат можно там же, где и про HTTP.

После "792:" читаем поток символов, парсим его на лету в HTTP-заголовок (пока он не исчерпается (по 2-м пустым строкам)); потом также парсим JSON пока не исчерпается весь объём в 792 байта.