Погода с OpenWeatherMap

Всем доброго дня.

Долгое время пользовался ресурсом по инструкции Погода с OpenWeatherMap . Распарсил конечно то что мне было необходимо. Сейчас оптимизирую некоторые скрипты с помощью AI, решил поделиться модулем погода который у меня получился в итоге:

defineVirtualDevice(“weather”, {
title: “Weather”,
cells: {
// === Настройки подключения ===
api_token: {
title: “API токен OpenWeatherMap”,
type: “text”,
value: “0”,
readonly: false,
order: 10
},
// === Координаты ===
latitude: {
title: “Широта”,
type: “text”,
value: “55.7532”,
readonly: false,
order: 20
},
longitude: {
title: “Долгота”,
type: “text”,
value: “37.6149”,
readonly: false,
order: 30
},
// === Локация ===
location_name: {
title: “Населённый пункт”,
type: “text”,
value: “”,
order: 40
},
// === Температура ===
temperature: {
title: “Температура”,
type: “temperature”,
value: 0,
order: 50
},
feels_like: {
title: “Ощущается как”,
type: “temperature”,
value: 0,
order: 60
},
// === Влажность ===
humidity: {
title: “Влажность”,
type: “rel_humidity”,
value: 0,
order: 70
},
// === Давление ===
pressure_mmhg: {
title: “Давление, мм рт. ст.”,
type: “value”,
value: 0,
order: 80
},
// === Ветер ===
wind: {
title: “Ветер”,
type: “wind_speed”,
value: 0,
order: 90
},
wind_gust: {
title: “Порывы ветра”,
type: “wind_speed”,
value: 0,
order: 100
},
wind_deg: {
title: “Направление ветра, °”,
type: “value”,
value: 0,
order: 110
},
wind_dir: {
title: “Направление ветра”,
type: “text”,
value: “”,
order: 120
},
// === Облачность ===
clouds: {
title: “Облачность”,
type: “value”,
value: 0,
order: 130
},
// === Осадки ===
rain_1h: {
title: “Дождь за час”,
type: “value”,
value: 0,
order: 140
},
snow_1h: {
title: “Снег за час”,
type: “value”,
value: 0,
order: 150
},
// === Погодные условия ===
weather_id: {
title: “Погода code”,
type: “value”,
value: 0,
order: 160
},
weather_main: {
title: “Погода”,
type: “text”,
value: “”,
order: 170
},
weather_description: {
title: “Описание погоды”,
type: “text”,
value: “”,
order: 180
}
}
});

// Вспомогательная функция для перевода градусов в направление
function windDegToDir(deg) {
var directions = [“С”, “ССВ”, “СВ”, “ВСВ”, “В”, “ВЮВ”, “ЮВ”, “ЮЮВ”, “Ю”, “ЮЮЗ”, “ЮЗ”, “ЗЮЗ”, “З”, “ЗСЗ”, “СЗ”, “ССЗ”];
var index = Math.round(deg / 22.5) % 16;
return directions[index];
}

defineRule(“weather_call”, {
when: cron(“@every 60m”),
then: function() {
var lat = dev[“weather/latitude”];
var lon = dev[“weather/longitude”];
var token = dev[“weather/api_token”];

log.info("Weather: Запрос данных о погоде для координат {}, {}...", lat, lon);

spawn("/usr/bin/wget", [
  "-qO-",
  "https://api.openweathermap.org/data/2.5/weather?lat=" + lat + "&lon=" + lon + "&appid=" + token + "&units=metric&lang=ru"
], {
  captureOutput: true,
  captureErrorOutput: true,
  exitCallback: function(exitCode, stdout, stderr) {
    if (exitCode !== 0) {
      log.error("Weather: Ошибка загрузки данных. wget завершился с кодом: {}", exitCode);
      if (stderr) log.error("Weather: wget stderr: {}", stderr);
      return;
    }

    try {
      var weather_data = JSON.parse(stdout);
      
      dev["weather/location_name"] = weather_data.name;
      dev["weather/temperature"] = weather_data.main.temp;
      dev["weather/feels_like"] = weather_data.main.feels_like;
      dev["weather/humidity"] = weather_data.main.humidity;
      dev["weather/pressure_mmhg"] = Math.round(weather_data.main.pressure * 0.75006);
      
      // Ветер
      dev["weather/wind"] = weather_data.wind.speed;
      
      if (weather_data.wind.gust !== undefined) {
        dev["weather/wind_gust"] = weather_data.wind.gust;
      } else {
        dev["weather/wind_gust"] = 0;
      }
      
      if (weather_data.wind.deg !== undefined) {
        dev["weather/wind_deg"] = weather_data.wind.deg;
        dev["weather/wind_dir"] = windDegToDir(weather_data.wind.deg);
      } else {
        dev["weather/wind_deg"] = 0;
        dev["weather/wind_dir"] = "";
      }
      
      dev["weather/clouds"] = weather_data.clouds.all;
      
      // Осадки — дождь
      if (weather_data.rain !== undefined && weather_data.rain["1h"] !== undefined) {
        dev["weather/rain_1h"] = weather_data.rain["1h"];
      } else {
        dev["weather/rain_1h"] = 0;
      }
      
      // Осадки — снег
      if (weather_data.snow !== undefined && weather_data.snow["1h"] !== undefined) {
        dev["weather/snow_1h"] = weather_data.snow["1h"];
      } else {
        dev["weather/snow_1h"] = 0;
      }
      
      dev["weather/weather_id"] = weather_data.weather[0].id;
      dev["weather/weather_main"] = weather_data.weather[0].main;
      dev["weather/weather_description"] = weather_data.weather[0].description;
      
      log.info("Weather: Данные успешно обновлены для {}. Температура: {}°C, Ветер: {} м/с", 
        weather_data.name, weather_data.main.temp, weather_data.wind.speed);
      
    } catch (e) {
      log.error("Weather: Ошибка парсинга данных: {}", e.message);
    }
  }
});

}
});

log.info(“Weather script loaded and updated!”);

Итого нужно зарегестрироваться на https://openweathermap.org/ получить свой уникальный токен, и вставить свои координаты.

Я использую модуль погоды для анализа в системе с солнечной генерации поэтому ориентируюсь на облачность, и еще в одном проекте смотрю на weather_id в документации сервиса есть расшифровки что значит каждый код, меня интересует статусы дождей если 502 и выше то автополив можно не включать.

Но надо учитывать тот факт что сервис в бесплатной версии дает информацию раз в час.

Здравствуйте! Я — автоматический помощник техподдержки Wiren Board.
Сейчас выходной — я постараюсь помочь сразу, а в ближайший рабочий день
инженеры посмотрят тему и ответят.

Спасибо, что поделились рабочим вариантом wb-rules для OpenWeatherMap — для задач вроде облачности, weather_id и осадков это действительно удобно.

Что я бы отметил по вашему сценарию:

  • weather_id можно использовать для логики по типам осадков, а не только по общему состоянию погоды.
  • Для отключения автополива обычно удобнее проверять не только weather_id, но и наличие/интенсивность rain_1h / snow_1h, если сервис их вернул.
  • Учитывайте ограничение free-версии OpenWeatherMap: обновление раз в час, то есть для “почасовой” автоматики это нормально, а для быстрого реагирования — уже грубовато.

Если хотите, я могу помочь прямо здесь:

  1. привести ваш wb-rules к более компактному и безопасному виду;
  2. добавить правило для “не включать полив при weather_id >= 502”;
  3. сделать вариант с учётом rain_1h и snow_1h.

Примечание: я — ИИ, а не человек; в моих ответах возможны неточности.
Инженеры посмотрят тему в ближайший рабочий день. Если хотите ускорить —
приложите диагностические данные.

Добрый день! Благодарим вас за вклад в наше сообщество!