Делюсь опытом Библиотека для работы с погодой

Добрый день!

Для своих часов написал простую библиотеку для работы с погодой.
OlegReshetnik/ESP8266_Libraries

Как пользоваться:
Код:
#include <ESP8266WiFi.h>
#include <WeatherLib.h>

WeatherLib wl("Krasnodar"); // "moscow,RU" если в разных странах есть одинаковые названия

void InitWiFi()
{
    const char * WiFi_Name = "********";
    const char * WiFi_Pass = "********";
    WiFi.begin( WiFi_Name, WiFi_Pass );
    while(WiFi.waitForConnectResult() != WL_CONNECTED) WiFi.begin( WiFi_Name, WiFi_Pass );
}

void setup() {
    Serial.begin( 115200 );
    InitWiFi();
}

void loop() {
    Serial.println( wl.getWeatherString() );

    delay(5000);
}
Также можно использовать функцию getWeather()
которая возвращает указатель на структуру:
Код:
struct weatherSt {
    uint8_t        temp;
    uint8_t        humidity;
    uint8_t        wind_speed;
    uint8_t        wind_dir;
    uint16_t    pressure;
    char        description[(DESK_LEN+1)];
};
Поле wind_dir содержит одно из следующих значений:
W_W - западный ветер
W_WS - юг-западный
W_S - южный
W_SO - юго-восточный
W_O - восточный
W_NO - северо-восточный
W_N - северный
W_NW - северо-западный

!!!Простая библиотека для Arduino ESP8266 для погоды
 

tretyakov_sa

Moderator
Команда форума
Если вашу библиотеку начнут использовать все кому не лень, ключ API не будет скомпрометирован?
 

enjoynering

Active member
поддерживаю - бесплатный ключ имеет ограничения. забанят.

тоже писал в свое время, но на javascript.
текущая погода:
JavaScript:
  var url = "http://api.openweathermap.org/data/2.5/weather?q=" + encodeURIComponent(city) + "&units=metric&cnt=1&appid=" + encodeURIComponent(key);
прогноз:
JavaScript:
var url = "http://api.openweathermap.org/data/2.5/forecast?q=" + encodeURIComponent(city) + "&units=metric&cnt=1&appid=" + encodeURIComponent(key);
можно еще тянуть иконки с их сервера:
JavaScript:
Weather.Current.prototype.icon = function () {
  var iconCode = this.data.weather[0].icon;
  return "http://openweathermap.org/img/w/" + iconCode + ".png";
};
 
Последнее редактирование:
Если вашу библиотеку начнут использовать все кому не лень, ключ API не будет скомпрометирован?
Честно говоря, не знал.
Это же openweathermap.org, т.е. open.
Если будет такая история, то придется доработать библиотеку.
 
поддерживаю - бесплатный ключ имеет ограничения. забанят.

тоже писал в свое время, но на javascript.
текущая погода:
JavaScript:
  var url = "http://api.openweathermap.org/data/2.5/weather?q=" + encodeURIComponent(city) + "&units=metric&cnt=1&appid=" + encodeURIComponent(key);
прогноз:
JavaScript:
var url = "http://api.openweathermap.org/data/2.5/forecast?q=" + encodeURIComponent(city) + "&units=metric&cnt=1&appid=" + encodeURIComponent(key);
можно еще тянуть иконки с их сервера:
JavaScript:
Weather.Current.prototype.icon = function () {
  var iconCode = this.data.weather[0].icon;
  return "http://openweathermap.org/img/w/" + iconCode + ".png";
};
За информацию про иконки большое спасибо!

А по поводу ключа:
был бы благодарен, если бы Вы дали какую-то информацию, как победить эту проблему?
 

enjoynering

Active member
Никак. Предусмотреть в библиотеке переменную под ключ. Как сейчас у вас есть переменная город. Каждый регится на сайте, получает ключ и поставляет вместе с городом.
 
Никак. Предусмотреть в библиотеке переменную под ключ. Как сейчас у вас есть переменная город. Каждый регится на сайте, получает ключ и поставляет вместе с городом.
Исправил библиотеку, теперь в конструкторе класса есть поле api key
Код:
WeatherLib wl("City","api_key"); // "City,RU" если в разных странах есть одинаковые названия
// Получить API key здесь: https://openweathermap.org/appid
Спасибо за конструктивные замечания.
 
Еще хотел заметить, что библиотека для разбора json ответа не использует громоздкую библиотек arduino json.
Весь разбор производится штатными функциями strstr();
 

Алексей.

Active member
Олег Решетник,
Погода за окном интересна, но форекастов нехватает, а они тяжелые, пятидневный с 3-ч часовым интервалом - полтора десятка килобайт, если принимать полностью (если получится), на джейсон (на парсер) памяти не останется совсем. Остается только парсить налету.
 

Сергей_Ф

Moderator
Команда форума
@Олег Решетник а не лучше инициализацию класса сделать только ключом, а город подставлять как параметр в запросе? Так можно по нескольким городам погоду получать будет.
 

Алексей.

Active member
Олег Решетник,
Почему то нет времени вычисления данных погоды
dt - Time of data calculation, unix, UTC
И совсем мало кодов ошибок, например при инициализации ввели не тот appid или указан не тот City и если нас забанили.
 
@Олег Решетник а не лучше инициализацию класса сделать только ключом, а город подставлять как параметр в запросе? Так можно по нескольким городам погоду получать будет.
В этом случае можно сделать несколько экземпляров класса.
Код:
WeatherLib w1("City1","api_key");
WeatherLib w2("City2","api_key");
 
Олег Решетник,
Почему то нет времени вычисления данных погоды
dt - Time of data calculation, unix, UTC
И совсем мало кодов ошибок, например при инициализации ввели не тот appid или указан не тот City и если нас забанили.
Независимо от интервала запросов к библиотеке, данные фактически обновляются каждые 20 минут.
Что касается кодов ошибок, то в случае неправильного города или api key, просто будут возвращаться
нулевые данные.

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

Сергей_Ф

Moderator
Команда форума
В этом случае можно сделать несколько экземпляров
это понятно. Но с параметром будет изящнее. Впрочем, я не настаиваю. Ваша библиотека.
Код:
WeatherLib wl("api_key");
...
wl.getWeatherString("Moscow");
wl.getWeatherString("NewYork");
 
Последнее редактирование:

Алексей.

Active member
Независимо от интервала запросов к библиотеке, данные фактически обновляются каждые 20 минут.
Хоть одна минута, хоть один час, не важно, в ответе присутствует dt: Time of data calculation, unix, UTC
Запросив данные в 22:15, получаю в dt время 21:00, а климат резко континентальный, большие колебания температур (суточные) - нормальное явление, отображать что было на улице более часа назад не совсем правильно, хоть как то сообщить, что данные уже не свежие.

Что касается кодов ошибок, то в случае неправильного города или api key, просто будут возвращаться
нулевые данные.
Отправляю запрос с неверным appid, получаю
{"cod":401, "message": "Invalid API key. Please see ht tp://openweathermap.org/faq#error401 for more info."}
Отправляю запрос с неверным City, получаю
{"cod":"404","message":"city not found"}
Если меня заблокировали, получаю
{"cod":429,"message": "Your account is temporary blocked due to exceeding of requests limitation of your subscription type. Please choose the proper subscription ht tp://openweathermap.org/price"}
Подскажите как по "нулевым данным" определить причину ошибки?

Я делал библиотеку для своего проекта часов, мне там прогноз не нужен, вот его и нет.
Когда утром собераешся на работу, прогноз на день бывает очень полезен, согласитесь.
 
Последнее редактирование:
это понятно. Но с параметром будет изящнее. Впрочем, я не настаиваю. Ваша библиотека.
Код:
WeatherLib wl("api_key");
...
wl.getWeatherString("Moscow");
wl.getWeatherString("NewYork");
Согласен с Вами, такой вариант изящнее.
Для моего проекта часов получать погоду для нескольких городов не нужно,
но я могу доработать свою библиотеку, если в этом будет реальная потребность.
 
Отправляю запрос с неверным appid, получаю
{"cod":401, "message": "Invalid API key. Please see ht tp://openweathermap.org/faq#error401 for more info."}
Отправляю запрос с неверным City, получаю
{"cod":"404","message":"city not found"}
Если меня заблокировали, получаю
{"cod":429,"message": "Your account is temporary blocked due to exceeding of requests limitation of your subscription type. Please choose the proper subscription ht tp://openweathermap.org/price"}
Подскажите как по "нулевым данным" определить причину ошибки?

Когда утром собераешся на работу, прогноз на день бывает очень полезен, согласитесь.
Для отладки в библиотеке есть функция:
bool WeatherLib::_getJson( WiFiClient * pClnt, char * buff, char * city, char * apiKey )
которая возвращает "сырой" json ответ.
Ее использовал для отладки.

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

Алексей.

Active member
Для отладки в библиотеке есть функция:
bool WeatherLib::_getJson( WiFiClient * pClnt, char * buff, char * city, char * apiKey )
которая возвращает "сырой" json ответ.
Ее использовал для отладки.
1. эта функция немножко приватная и недоступна для вызова.
2. эта функция возвращает bool а не джейсон
3. эта функция заполняет buff только частью ответа, первые 300 байт (WEATHER_READ_BUFF)

Когда очередной раз (спустя 20 минут) вызвали getWeather() и получили struct weatherSt* заполненный абсолютно идентичными данными нельзя быть уверенным что данные реально обновлены, потому что они обновляются в случае успешного соединения с хостом и успешного разбора ответа.

PS:
Для отладки, в данном случае контроль трафика, есть более простые средства, такие как tcpdump на роутере ;-)
 
1. эта функция немножко приватная и недоступна для вызова.
2. эта функция возвращает bool а не джейсон
3. эта функция заполняет buff только частью ответа, первые 300 байт (WEATHER_READ_BUFF)

Когда очередной раз (спустя 20 минут) вызвали getWeather() и получили struct weatherSt* заполненный абсолютно идентичными данными нельзя быть уверенным что данные реально обновлены, потому что они обновляются в случае успешного соединения с хостом и успешного разбора ответа.

PS:
Для отладки, в данном случае контроль трафика, есть более простые средства, такие как tcpdump на роутере ;-)
Вы убедили меня, уважаемый гуру.
Выкладывайте свою библиотеку, а я "ломаю подкидную доску и ухожу из большого спорта".
 

Сергей_Ф

Moderator
Команда форума
@Олег Решетник странная у вас реакция на конструктивную критику. Вам подсказывают как сделать вашу библиотеку полезной для широкого круга, а не только для вас. Учиться никогда не поздно, тем более бесплатно :)
 
Сверху Снизу