Запрос на сервер OpenWeatherMap
- Войдите на сайт для отправки комментариев
Хочу получить погоду с сайта 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;
}
}
У Вас есть какой-то вопрос? Или это просто плач в жилетку?
Если первое, то Вы забыли его (вопрос) задать.
Если второе, то "принято к сведению".
Ну, тут про то, что приходит не тот ответ с сервера, что ожидается. Такого вида: "+IDP,787:HTTP/1.1 вместо ответа для парсинга"
Не знаю, откуда пример скопирован, но может... он немного устарел или не знаю. В новых API надо указывать тип ответа с сервера. Тоесть, в строку запроса GET добавить еще &mode=json&units=metric, а то там только ID города передаётся. Что-то маловато, вроде как.
Что-то маловато, вроде как.
Не знаю, откуда пример скопирован, но может... он немного устарел или не знаю. В новых API надо указывать тип ответа с сервера. Тоесть, в строку запроса GET добавить еще &mode=json&units=metric, а то там только ID города передаётся. Что-то маловато, вроде как.
Не могу найти как создавать строку запроса в новой форме? А то попадаются старые коды где нет типа запроса с сервера!
Не могу найти как создавать строку запроса в новой форме?
нет никаких "новых" и старых форм запроса, это зависит исключительно от сервера
нет пророка в своём отечестве...
Это я о том, что данные этого ресурса не актуальны, то-есть совсем не актуальны,
а точнее сказать - полный бред, для моего QTH...
Может как-то можно с НАРОДНОГО МОНИТОРИНГА получать?
Ну вообще-то openweathermap довольно точный.
Можно и с народмона. Туда ему POST на http://narodmon.ru/lst/0 с координатами нужного квадрата, обратно отдаст массив в json.
Можно и с народмона.
с народмона хорошо, когда рядом какая-то профессиональная метеостанция есть. Например некоторые аэропорты свои данные на народмон выкладывают
Ну вообще-то openweathermap довольно точный...
видимо разговор идёт о широко известных объектах...
PS смотрел неоднократно, по давлению врёт на 50мм.рт.ст, по ветру на 8 метров в секунду, по температуре на 5 градусов, откуда такие данные берёт загадка со многими неизвестными )))
Врет относительно чего?
видимо разговор идёт о широко известных объектах...
PS смотрел неоднократно, по давлению врёт на 50мм.рт.ст, по ветру на 8 метров в секунду, по температуре на 5 градусов, откуда такие данные берёт загадка со многими неизвестными )))
Вот сейчас данные по Москве
разница, конечно, есть, но не особо существенная
И кстати, расхождения по давлению обьясняются просто - OpenWeatherMap по умолчанию отдает давление на уровне моря, если вы живете не на уровне моря, эту цифру надо пересчитывать.
Например в примере выше OWM дает для Москвы 764 мм, в то время как метеостанция в Шарике (Шереметьево) - 748 мм. Но, как я писал выше, у OWM давление, приведенное к уровню моря. С учетом того что Шарик - это примерно 140м над уровнем моря, подставляем это в калькулятор вот тут:
https://www.mide.com/air-pressure-at-altitude-calculator
и получаем данные от OWM - 749 мм рт ст, то есть всего на 1 мм рт ст отличающиеся от данных аэропорта
У нас метеостанция находится за городом, в низине. Расхождение с ней моих "городских" датчиков - процентов 20, как минимум. И что тут такого? Понятное дело, что показания термометра в будке Стивенсона посреди поля не сравнятся с термометром с Алиэкспресса, вывешенным с балкона посреди города.
Это как-то влияет на жизнедеятельность? Что даст совпадение показаний 1:1?
Не могу найти как создавать строку запроса в новой форме?
нет никаких "новых" и старых форм запроса, это зависит исключительно от сервера
Сервер - OpenWeatherMap.
Настолько я понял поменял форму запроса.
Дайте мне пример запроса в новом формате!
Именно это я хочу, а то в этой ветке форума понесло в сторону адекватности датчиков
Дайте мне пример запроса в новом формате! Именно это я хочу
Ножкой надо ещё топнуть! Что они вообще себе позволяют? Теме уж две недели, а до сих пор никто не дал примеров запросов в новом формате? Нахрена вообще форум?
---------------
Все запросы с херовой тучей примеров описаны на самом сайте - вот здесь. Какого ж тебе ещё надо? Что-то там непонятно, так задай конкретный вопрос.
Та ну вы вообще злюки бобры:) Я там ранее написал, что запрос правильный, только двух параметров не хватает. Давайте тогда "ссылку в студию" по которой делается запрос не возвращающий результатов. Я его вам исправлю. Что ссылка будет работать. OpenWeatherMap идеален уже тем, что альтернатив нет. Сервис жестко юзает интерполяцию (усреднение результатов между двумя известными метеостанциями) но она в целом всё равно останется похожа на правду и лучше, чем несуществующие альтернативы (бесплатные).
Надо лишь передать в запросе, что хотите JSON.
В общем, давайте пример - исправлю. Кто, как не я.
Была строка запроса:
Должна стать вот такой:
Правильно я понимаю!?
Та вроде как. Можно еще и язык указать, чтобы в сумме получилось:
http://api.openweathermap.org/data/2.5/weather?id=518970&mode=json&units=metric&lang=ru&appid=dddd71098446021e66e71a6aaf4cc69c
вот пишет:
Пытаюсь сосчитать ответ от сервера в функции loop():
Приходит ответ от сервера:
+IDP,787:HTTP/1.1
Я так понимаю там будет дальше 2-е \n и потом данные. Я их пока не могу получить... Кто подскажет как правильно их выгрести из ответа!
вот пишет:
высота какая у вас над уровнем моря.? Дай угадаю, примерно 400 метров?
Я выше писал как пересчитывать давление с опенвезер на фактическое
Я так понимаю там будет дальше 2-е \n и потом данные. Я их пока не могу получить... Кто подскажет как правильно их выгрести из ответа!
мне кажется вы этот вопрос пятый раз задаете. В чем проблема у вас? Если вы знаете, как считать первую строку, в чем сложность точно также считать вторую и все последующие?
Михай, Посмотрел код. Вы отправляете запрос на сервер, а потом ставите задержку 5 секунд. Размер ответа сервера, судя по первой строке - 787 байт. И все это на ардуине через Софтсериал, у которого буфер для данных толи 64, толи 128 байт. То есть к моменту окончания вашего делея весь ответ сервера уже безвозвратно потерян. Это даже при условии, что у ардуины хватит памяти для парсинга ответа в 800 байт
Вывод - работать это не может в принципе
И как это использовать? Я о давлении. Если лечу по правилам визуальных полётов, запрашиваю давление на площадке, выставляю на приборе, тогда альтиметр показывает истинную высоту, а это без 100 грамм (математики) как применять?
Там в параметрах есть как давление на уровне моря, так и на уровне земли, но по умолчанию отдается именно на уровне моря, видимо так считать проще
Ну не знаю, я привык на 714 ориентироваться, без всяких расчётов, а мне предлагают математикой позаниматься )))
Ну не знаю, я привык на 714 ориентироваться, без всяких расчётов, а мне предлагают математикой позаниматься )))
ну так что, угадал высоту? :)
Вместо сложной математики просто вычитай из данных OWM примерно 46-48 мм рт ст - ошибка будет 2-3 мм
Ну не знаю, я привык на 714 ориентироваться, без всяких расчётов, а мне предлагают математикой позаниматься )))
ну так что, угадал высоту? :)
Вместо сложной математики просто вычитай из данных OWM примерно 46-48 мм рт ст - ошибка будет 2-3 мм
почти, у меня от 512 до 530 (где постоянно присутствую), а 2 -3 миллиметра разброс это сильно много, совсем разная погода за бортом, я тут вот думаю, как бы шумовую с датчика снимать и по ней ориентироваться
кстати, еще подумал - в том что OWM дает давление на уровне моря - есть глубокий смысл. Для плоских мест, типа питера - там понятно, какое давление показывать, оно одно на весь город и окрестности. А во Владике, например, там же разница высот между районами до 300 метров вроде - там какие данные давать? :) Это OWM пришлось бы расчитывать по координатам на гугле-Мапс высоту гор в данной точке... Проше оставить это юзеру - ведь он точно знает свою высоту, вот пусть и вводит поправку сам.
40 метров над уровнем моря на просвете :)
кстати, еще подумал - в том что OWM дает давление на уровне моря - есть глубокий смысл. Для плоских мест, типа питера - там понятно, какое давление показывать, оно одно на весь город и окрестности. А во Владике, например, там же разница высот между районами до 300 метров вроде - там какие данные давать? :) Это OWM пришлось бы расчитывать по координатам на гугле-Мапс высоту гор в данной точке... Проше оставить это юзеру - ведь он точно знает свою высоту, вот пусть и вводит поправку сам.
у меня метеостанция в ста метрах, в центре города, (была, надо сходить посмотреть, не ликвидировали ли) )))
у меня метеостанция в ста метрах, в центре города, (была, надо сходить посмотреть, не ликвидировали ли) )))
думаю, OWM не берет данные у сотен и тысяч местных метеостанций, вместо этого у них своя рассчетная метеомодель на регион... приводимая к реальности по нескольким наиболее крупным точкам
По ID города
Вы можете сделать вызов API по идентификатору города. Список идентификаторов городов city.list.json.gz можно скачать здесь .
Рекомендуем вызывать API по идентификатору города, чтобы получить однозначный результат для вашего города.
Вызов API
api.openweathermap.org/data/2.5/weather?id={city id}&appid={API key}