Запрос на сервер OpenWeatherMap

Mihay
Offline
Зарегистрирован: 07.08.2020
Хочу получить погоду с сайта OpenWeatherMap.com. Модуль ESP-01 подключен к Arduino. Подключаюсь к WI-FI, нормально, Посылаю запрос. 
Ответ приходит не с ожидаемыми данными а в виде  +IDP,787:HTTP/1.1, естественно парсить ответ невозможно. 
Это часть кода:
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('\r'); //Добавляем полученные данные в строку line } Serial.println(line); // +IDP,787:HTTP/1.1 вместо ответа для парсинга
DeserializationError error = deserializeJson(root, line); // Парсинг невозможен

Вот полный код: #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 = "dddd71098446021e66e71a6aaf4cc69c"; //Мой API ключ (изменил на ложный)
const char* city = "518970"; //ID моего города
String line;

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('\r'); //Добавляем полученные данные в строку line
}
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;
}
}

 

Mihay
Offline
Зарегистрирован: 07.08.2020
Serial.println(cmd);
 dbgSerial.println(cmd); // Посылка запроса 
delay(3000); 
if(dbgSerial.find("SEND OK"))
 { 
   Serial.println("Request send"); // Ответ пришел 
 }
Serial.println("Begin JSON"); 
while(dbgSerial.available())
{ //Если получили ответ от сервера... 
   line = dbgSerial.readStringUntil('\r'); //Добавляем полученные данные в строку line 
} 
Serial.println(line); // +IDP,787:HTTP/1.1 вместо ответа для парсинга
DeserializationError error = deserializeJson(root, line); // Парсинг невозможен

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

У Вас есть какой-то вопрос? Или это просто плач в жилетку?

Если первое, то Вы забыли его (вопрос) задать.

Если второе, то "принято к сведению".

Weisnar
Weisnar аватар
Offline
Зарегистрирован: 19.07.2018

ЕвгенийП пишет:
У Вас есть какой-то вопрос?

Ну, тут про то, что приходит не тот ответ с сервера, что ожидается. Такого вида: "+IDP,787:HTTP/1.1 вместо ответа для парсинга"

Не знаю, откуда пример скопирован, но может... он немного устарел или не знаю. В новых API надо указывать тип ответа с сервера. Тоесть, в строку запроса GET добавить еще &mode=json&units=metric, а то там только ID города передаётся. Что-то маловато, вроде как. 

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Weisnar пишет:

Что-то маловато, вроде как. 

Принято к сведению.

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

Weisnar пишет:

 

Не знаю, откуда пример скопирован, но может... он немного устарел или не знаю. В новых API надо указывать тип ответа с сервера. Тоесть, в строку запроса GET добавить еще &mode=json&units=metric, а то там только ID города передаётся. Что-то маловато, вроде как. 

 

Не могу найти как создавать строку запроса в новой форме? А то попадаются старые коды где нет типа запроса с сервера!

b707
Offline
Зарегистрирован: 26.05.2017

Mihay пишет:

Не могу найти как создавать строку запроса в новой форме?

нет никаких "новых" и старых форм запроса, это зависит исключительно от сервера

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

нет пророка в своём отечестве...
Это я о том, что данные этого ресурса не актуальны, то-есть совсем не актуальны,
а точнее сказать - полный бред, для  моего QTH...
Может как-то можно с НАРОДНОГО МОНИТОРИНГА получать?

 

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Ну вообще-то openweathermap довольно точный.

Можно и с народмона. Туда ему POST на http://narodmon.ru/lst/0 с координатами нужного квадрата, обратно отдаст массив в json.

ajax=1&types=&ourcam=1&windy=1&metar=1&bounds=57.50903,26.316416,58.91345,29.733164

 

b707
Offline
Зарегистрирован: 26.05.2017

negavoid2 пишет:

Можно и с народмона.

с народмона хорошо, когда рядом какая-то профессиональная метеостанция есть. Например некоторые аэропорты свои данные на народмон выкладывают

 

Izvekoff
Offline
Зарегистрирован: 02.03.2020

negavoid2 пишет:

Ну вообще-то openweathermap довольно точный...

видимо разговор идёт о широко известных объектах...
PS смотрел неоднократно, по давлению врёт на 50мм.рт.ст, по ветру на 8 метров в секунду, по температуре на 5 градусов, откуда такие данные берёт загадка со многими неизвестными )))

sadman41
Offline
Зарегистрирован: 19.10.2016

Врет относительно чего?

b707
Offline
Зарегистрирован: 26.05.2017

Izvekoff пишет:

видимо разговор идёт о широко известных объектах...
PS смотрел неоднократно, по давлению врёт на 50мм.рт.ст, по ветру на 8 метров в секунду, по температуре на 5 градусов, откуда такие данные берёт загадка со многими неизвестными )))

Вот сейчас данные по Москве

OPENWeatherMap        Шереметьево аэропорт

Т = 16 гр С                     17
Р = 764 мм                      748
H = 77%                          63
W = 2.8 m/sec                    2,1

разница, конечно, есть, но не особо существенная

b707
Offline
Зарегистрирован: 26.05.2017

И кстати, расхождения по давлению обьясняются просто - OpenWeatherMap по умолчанию отдает давление на уровне моря, если вы живете не на уровне моря, эту цифру надо пересчитывать.

Например в примере выше OWM дает для Москвы 764 мм, в то время как метеостанция в Шарике (Шереметьево) - 748 мм. Но, как я писал выше, у OWM давление, приведенное к уровню моря. С учетом того что Шарик - это примерно 140м над уровнем моря, подставляем это в калькулятор вот тут:

https://www.mide.com/air-pressure-at-altitude-calculator

и получаем данные от OWM - 749 мм рт ст, то есть всего на 1 мм рт ст отличающиеся от данных аэропорта

sadman41
Offline
Зарегистрирован: 19.10.2016

У нас метеостанция находится за городом, в низине. Расхождение с ней моих "городских" датчиков - процентов 20, как минимум. И что тут такого? Понятное дело, что показания термометра в будке Стивенсона посреди поля не сравнятся с термометром с Алиэкспресса, вывешенным с балкона посреди города.

Это как-то влияет на жизнедеятельность? Что даст совпадение показаний 1:1?

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

b707 пишет:

Mihay пишет:

Не могу найти как создавать строку запроса в новой форме?

нет никаких "новых" и старых форм запроса, это зависит исключительно от сервера

Сервер - OpenWeatherMap. 

Настолько я понял поменял форму запроса. 

Дайте мне пример запроса в новом формате! 

Именно это я хочу, а то в этой ветке форума понесло в сторону адекватности датчиков

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Mihay пишет:

Дайте мне пример запроса в новом формате! Именно это я хочу

Ножкой надо ещё топнуть! Что они вообще себе позволяют? Теме уж две недели, а до сих пор никто не дал примеров запросов в новом формате? Нахрена вообще форум?

---------------

Все запросы с херовой тучей примеров описаны на самом сайте - вот здесь. Какого ж тебе ещё надо? Что-то там непонятно, так задай конкретный вопрос.

Weisnar
Weisnar аватар
Offline
Зарегистрирован: 19.07.2018

Та ну вы вообще злюки бобры:) Я там ранее написал, что запрос правильный, только двух параметров не хватает. Давайте тогда "ссылку в студию" по которой делается запрос не возвращающий результатов. Я его вам исправлю. Что ссылка будет работать. OpenWeatherMap идеален уже тем, что альтернатив нет. Сервис жестко юзает интерполяцию (усреднение результатов между двумя известными метеостанциями) но она в целом всё равно останется похожа на правду и лучше, чем несуществующие альтернативы (бесплатные).
Надо лишь передать в запросе, что хотите JSON.
В общем, давайте пример - исправлю. Кто, как не я.

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

Была строка запроса:

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";

Должна стать вот такой:

cmd = "GET /data/2.5/weather?id=" + String(city) + "&mode=json&units=metric&appid=" + String(api);
cmd += " HTTP/1.0\r\nHost: api.openweathermap.org\r\n\r\n";

Правильно я понимаю!?

Weisnar
Weisnar аватар
Offline
Зарегистрирован: 19.07.2018

Та вроде как. Можно еще и язык указать, чтобы в сумме получилось:

http://api.openweathermap.org/data/2.5/weather?id=518970&mode=json&units=metric&lang=ru&appid=dddd71098446021e66e71a6aaf4cc69c

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:
У нас метеостанция находится за городом, в низине. Расхождение с ней моих "городских" датчиков - процентов 20, как минимум. И что тут такого? Понятное дело, что показания термометра в будке Стивенсона посреди поля не сравнятся с термометром с Алиэкспресса, вывешенным с балкона посреди города. Это как-то влияет на жизнедеятельность? Что даст совпадение показаний 1:1?

вот пишет:

21°C Feels like 13°C. Broken clouds. Gentle Breeze 4.9m/s 1013hPa Humidity:3% UV:7
 
а фактически 712мм.рт.ст и полный штиль

 

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

Пытаюсь сосчитать ответ от сервера в функции loop(): 

while(dbgSerial.available()){ //Если получили ответ от сервера...
line = dbgSerial.readStringUntil('\r'); //Добавляем полученные данные в строку line
}
Serial.println(line);

Приходит ответ от сервера:

+IDP,787:HTTP/1.1

Я так понимаю там будет дальше 2-е \n и потом данные. Я их пока не могу получить... Кто подскажет как правильно их выгрести из ответа!

b707
Offline
Зарегистрирован: 26.05.2017

ua6em пишет:

вот пишет:

21°C Feels like 13°C. Broken clouds. Gentle Breeze 4.9m/s 1013hPa Humidity:3% UV:7
 
а фактически 712мм.рт.ст и полный штиль

 


высота какая у вас над уровнем моря.? Дай угадаю, примерно 400 метров?
Я выше писал как пересчитывать давление с опенвезер на фактическое

b707
Offline
Зарегистрирован: 26.05.2017

Mihay пишет:

Я так понимаю там будет дальше 2-е \n и потом данные. Я их пока не могу получить... Кто подскажет как правильно их выгрести из ответа!


мне кажется вы этот вопрос пятый раз задаете. В чем проблема у вас? Если вы знаете, как считать первую строку, в чем сложность точно также считать вторую и все последующие?

b707
Offline
Зарегистрирован: 26.05.2017

Михай, Посмотрел код. Вы отправляете запрос на сервер, а потом ставите задержку 5 секунд. Размер ответа сервера, судя по первой строке - 787 байт. И все это на ардуине через Софтсериал, у которого буфер для данных толи 64, толи 128 байт. То есть к моменту окончания вашего делея весь ответ сервера уже безвозвратно потерян. Это даже при условии, что у ардуины хватит памяти для парсинга ответа в 800 байт
Вывод - работать это не может в принципе

Izvekoff
Offline
Зарегистрирован: 02.03.2020

И как это использовать? Я о давлении. Если лечу по правилам визуальных полётов, запрашиваю давление на площадке, выставляю на приборе, тогда альтиметр показывает истинную высоту, а это без 100 грамм (математики) как применять?

b707
Offline
Зарегистрирован: 26.05.2017

Там в параметрах есть как давление на уровне моря, так и на уровне земли, но по умолчанию отдается именно на уровне моря, видимо так считать проще

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

b707 пишет:
Там в параметрах есть как давление на уровне моря, так и на уровне земли, но по умолчанию отдается именно на уровне моря, видимо так считать проще

Ну не знаю, я привык на 714 ориентироваться, без всяких расчётов, а мне предлагают математикой позаниматься )))

 

b707
Offline
Зарегистрирован: 26.05.2017

ua6em пишет:

Ну не знаю, я привык на 714 ориентироваться, без всяких расчётов, а мне предлагают математикой позаниматься )))

 

ну так что, угадал высоту? :)

Вместо сложной математики просто вычитай из данных OWM примерно 46-48 мм рт ст - ошибка будет 2-3 мм

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

b707 пишет:

ua6em пишет:

Ну не знаю, я привык на 714 ориентироваться, без всяких расчётов, а мне предлагают математикой позаниматься )))

 

ну так что, угадал высоту? :)

Вместо сложной математики просто вычитай из данных OWM примерно 46-48 мм рт ст - ошибка будет 2-3 мм

почти, у меня от 512 до 530 (где постоянно присутствую), а 2 -3 миллиметра разброс это сильно много, совсем разная погода за бортом, я тут вот думаю, как бы шумовую с датчика снимать и по ней ориентироваться

b707
Offline
Зарегистрирован: 26.05.2017

кстати, еще подумал - в том что OWM дает давление на уровне моря - есть глубокий смысл. Для плоских мест, типа питера - там понятно, какое давление показывать, оно одно на весь город и окрестности. А во Владике, например, там же разница высот между районами до 300 метров вроде - там какие данные давать? :) Это OWM пришлось бы расчитывать по координатам на гугле-Мапс высоту гор в данной точке... Проше оставить это юзеру - ведь он точно знает свою высоту, вот пусть и вводит поправку сам.

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

b707 пишет:
Для плоских мест, типа питера - там понятно, какое давление показывать, оно одно на весь город и окрестности.

40 метров над уровнем моря на просвете :)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

b707 пишет:

кстати, еще подумал - в том что OWM дает давление на уровне моря - есть глубокий смысл. Для плоских мест, типа питера - там понятно, какое давление показывать, оно одно на весь город и окрестности. А во Владике, например, там же разница высот между районами до 300 метров вроде - там какие данные давать? :) Это OWM пришлось бы расчитывать по координатам на гугле-Мапс высоту гор в данной точке... Проше оставить это юзеру - ведь он точно знает свою высоту, вот пусть и вводит поправку сам.

у меня метеостанция в ста метрах, в центре города, (была, надо сходить посмотреть, не ликвидировали ли)  )))

b707
Offline
Зарегистрирован: 26.05.2017

ua6em пишет:

у меня метеостанция в ста метрах, в центре города, (была, надо сходить посмотреть, не ликвидировали ли)  )))

думаю, OWM не берет данные у сотен и тысяч местных метеостанций, вместо этого у них своя рассчетная метеомодель на регион... приводимая к реальности по нескольким наиболее крупным точкам

ziyara
Offline
Зарегистрирован: 05.11.2019

По ID города

Вы можете сделать вызов API по идентификатору города. Список идентификаторов городов city.list.json.gz можно скачать здесь .

Рекомендуем вызывать API по идентификатору города, чтобы получить однозначный результат для вашего города.

Вызов API

api.openweathermap.org/data/2.5/weather?id={city id}&appid={API key}