OpenWeather: Weather Forecast, Get by Time
OpenWeather: Weather Forecast, Get by Time
Gets weather forecast for the specific time (corrected to zero minutes) from OpenWeather with specifying latitude and longitude of the world. Not only temperature, humidity and wind speed, but also visibility and sensible temperature can be obtained.
Configs
  • A: Set API Key *#{EL}
  • B1: Set Unit System (Celsius: “metric”, Fahrenheit: “imperial”)#{EL}
  • B2: Set Lang Code to translate description field (eg “ja” “es”)#{EL}
  • C: Set Datetime (of location), Latitude and Longitude in 3 lines *#{EL}
  • E1: Select NUMERIC that stores Temperature (update)
  • E2: Select NUMERIC that store Temperature of Perception (update)
  • E3: Select NUMERIC that stores Dew Point (update)
  • F1: Select NUMERIC that stores Probability of precipitation % (update)
  • F2: Select NUMERIC that stores Humidity % (update)
  • F3: Select NUMERIC that stores Clouds % (update)
  • G1: Select STRING that stores Weather Group (update)
  • G2: Select STRING that stores Weather Condition (update)
  • G3: Select STRING that stores Weather Icon URL (update)
  • H0: Select NUMERIC that stores Wind Gust (update)
  • H1: Select NUMERIC that stores Wind Speed (update)
  • H2: Select NUMERIC that stores Wind Deg coming 0:N 90:E (update)
  • I1: Select NUM that stores Rain Volume for last hour mm (update)
  • I2: Select NUMERIC that stores Sea Level Pressure (update)
  • I3: Select NUMERIC that stores UV Index (update)
  • I4: Select NUMERIC that stores Visibility m (update)
Script (click to open)
// GraalJS Script (engine type: 2)

//////// START "main()" /////////////////////////////////////////////////////////////////
main();
function main(){ 

//// == Config Retrieving / 工程コンフィグの参照 ==
const strApiKey      = configs.get( "StrConfA" ); // required
  if( strApiKey    === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {A API Key} is empty \n" );
  }
const strUnitSystem  = configs.get( "StrConfB1" );
const strLangCode    = configs.get( "StrConfB2" );
const strTarget3     = configs.get( "StrConfC" ); // required
  if( strTarget3   === "" ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {C Date Latitude Longitude} is empty \n" );
  }
  const arrTarget3   = strTarget3.split("\n");
  if( arrTarget3.length < 3 ){
    throw new Error( "\n AutomatedTask ConfigError:" +
                     " Config {C Date Latitude Longitude} Set in 3 lines \n" );
  }
  const strSpecifiedDate = arrTarget3[0].slice(0, 13); // eg "2021-12-31 23"
  let  dateSpecified = toJsDate( strSpecifiedDate + ":00" ); // Specified DateTime (Platform)
  const strLat       = arrTarget3[1];
  const strLon       = arrTarget3[2];
const numPocketTemp      = configs.getObject( "SelectConfE1" );
const numPocketFeelTemp  = configs.getObject( "SelectConfE2" );
const numPocketDewPoint  = configs.getObject( "SelectConfE3" );
const numPocketPop       = configs.getObject( "SelectConfF1" );
const numPocketHumidity  = configs.getObject( "SelectConfF2" );
const numPocketClouds    = configs.getObject( "SelectConfF3" );
const strPocketGroup     = configs.getObject( "SelectConfG1" );
const strPocketCondition = configs.getObject( "SelectConfG2" );
const strPocketIconUrl   = configs.getObject( "SelectConfG3" );
const numPocketWindGust  = configs.getObject( "SelectConfH0" );
const numPocketWindSpeed = configs.getObject( "SelectConfH1" );
const numPocketWindDeg   = configs.getObject( "SelectConfH2" );
const numPocketRain      = configs.getObject( "SelectConfI1" );
const numPocketPressure  = configs.getObject( "SelectConfI2" );
const numPocketUvi       = configs.getObject( "SelectConfI3" );
const numPocketVisibility = configs.getObject( "SelectConfI4" );


//// == Data Retrieving / ワークフローデータの参照 ==
// (Nothing. Retrieved via Expression Language in Config Retrieving)


//// == Calculating / 演算 ==

/// Get all essential weather data for a specific location
/// https://openweathermap.org/api/one-call-api
// request1, prepare
let getUri1  = "https://api.openweathermap.org/data/2.5/onecall";
let request1 = httpClient.begin(); // HttpRequestWrapper
    request1 = request1.queryParam( "appid", strApiKey ); 
    request1 = request1.queryParam( "lat", strLat ); 
    request1 = request1.queryParam( "lon", strLon ); 
    request1 = request1.queryParam( "exclude", "minutely,daily" ); // focus "hourly[]"
    if( strUnitSystem !== "" ){
      request1 = request1.queryParam( "units", strUnitSystem ); 
    }
    if( strLangCode !== "" ){
      request1 = request1.queryParam( "lang", strLangCode ); 
    }
// request1, try
const response1     = request1.get( getUri1 ); // HttpResponseWrapper
engine.log( " AutomatedTask ApiRequest1 Start: " + getUri1 );
const response1Code = response1.getStatusCode() + "";
const response1Body = response1.getResponseAsString() + "";
engine.log( " AutomatedTask ApiResponse1 Status: " + response1Code );
if( response1Code !== "200"){
  throw new Error( "\n AutomatedTask UnexpectedResponseError: " +
                    response1Code + "\n" + response1Body + "\n" );
}
// response1, parse
// engine.log( response1Body ); // debug
/* response sample
{
  "lat": 43.0687,
  "lon": 141.3508,
  "timezone": "Asia/Tokyo",
  "timezone_offset": 32400,
  "hourly": [
    {
      "dt": 1613692800,
      "temp": 1,
      "feels_like": -3.02,
      "pressure": 1005,
      "humidity": 60,
      "dew_point": -5.22,
      "uvi": 0.67,
      "clouds": 75,
      "visibility": 10000,
      "wind_speed": 1.89,
      "wind_deg": 240,
      "wind_gust": 4.15,
      "weather": [
        {
          "id": 803,
          "main": "Clouds",
          "description": "曇りがち",
          "icon": "04d"
        }
      ],
      "pop": 0.51,
      "rain": {
        "1h": 0.24
      }
    },
*/
const response1Obj = JSON.parse( response1Body );
engine.log( " AutomatedTask ApiResponse1 # of Array Hourly: " + response1Obj.hourly.length );
engine.log( " AutomatedTask ApiResponse1 timezone: " + response1Obj.timezone );
engine.log( " AutomatedTask ApiResponse1 offset: " + (response1Obj.timezone_offset /3600) );
engine.log( " AutomatedTask Workflow Platform offset: " + (engine.getTimeZoneOffsetInMinutes() /60) );

/// Find ID of the specified datetime
// Time (recognized by Workflow Platform) -> Time (Weather Location Timezone)
dateSpecified.setSeconds( dateSpecified.getSeconds() +
  engine.getTimeZoneOffsetInMinutes() * 60 -
  response1Obj.timezone_offset
  ); 
let numHourlyId = 0;
engine.log( "  Time to search: " + dateSpecified.getTime() +
                " (" + dateSpecified.toISOString() + ")"
          );
for( let i = 0; i < response1Obj.hourly.length; i++ ){ // must be sorted
  let dateTmp = new Date( response1Obj.hourly[i].dt *1000 );
  if( response1Obj.hourly[i].dt *1000 > dateSpecified.getTime() ){
    engine.log( "    hourly[" + i + "].dt: " + response1Obj.hourly[i].dt +
                " (" + dateTmp.toISOString() + ") is larger"
              );
    break;
  }else{
    engine.log( "    hourly[" + i + "].dt: " + response1Obj.hourly[i].dt +
                " (" + dateTmp.toISOString() + ")"
              );
    numHourlyId = i;
  }
}

/// Extract weather info with Date-ID
let numTemp        = response1Obj.hourly[numHourlyId].temp;
let numFeelTemp    = response1Obj.hourly[numHourlyId].feels_like;
let numDewPoint    = response1Obj.hourly[numHourlyId].dew_point;
let numPop         = response1Obj.hourly[numHourlyId].pop *100; // "0.51" to "51"%
let numHumidity    = response1Obj.hourly[numHourlyId].humidity;
let numClouds      = response1Obj.hourly[numHourlyId].clouds;
let strGroup       = response1Obj.hourly[numHourlyId].weather[0].main;
let strCondition   = response1Obj.hourly[numHourlyId].weather[0].description;
let strIconUrl     = "https://openweathermap.org/img/wn/" +
                     response1Obj.hourly[numHourlyId].weather[0].icon + ".png";
                     // eg "https://openweathermap.org/img/wn/10d.png"
let numWindGust    = response1Obj.hourly[numHourlyId].wind_speed; // Case where gusts do not blow
if( response1Obj.hourly[numHourlyId].hasOwnProperty('wind_gust') ){
    numWindGust    = response1Obj.hourly[numHourlyId].wind_gust;
}
let numWindSpeed   = response1Obj.hourly[numHourlyId].wind_speed;
let numWindDeg     = response1Obj.hourly[numHourlyId].wind_deg;
let numRain        = 0;
if( response1Obj.hourly[numHourlyId].hasOwnProperty('rain') ){
    numRain        = response1Obj.hourly[numHourlyId].rain['1h'];
}
// The period operator format is not available 
// if the first character of the property name begins with a number
// or if the property name contains a hyphen.
let numPressure    = response1Obj.hourly[numHourlyId].pressure;
let numUvi         = response1Obj.hourly[numHourlyId].uvi;
let numVisibility  = response1Obj.hourly[numHourlyId].visibility;


//// == Data Updating / ワークフローデータへの代入 ==
if( numPocketTemp   !== null ){
  engine.setData( numPocketTemp,      new java.math.BigDecimal( numTemp ) );
}
if( numPocketFeelTemp  !== null ){
  engine.setData( numPocketFeelTemp,  new java.math.BigDecimal( numFeelTemp ) );
}
if( numPocketDewPoint  !== null ){
  engine.setData( numPocketDewPoint,  new java.math.BigDecimal( numDewPoint ) );
}
if( numPocketPop       !== null ){
  engine.setData( numPocketPop,       new java.math.BigDecimal( numPop ) );
}
if( numPocketHumidity  !== null ){
  engine.setData( numPocketHumidity,  new java.math.BigDecimal( numHumidity ) );
}
if( numPocketClouds    !== null ){
  engine.setData( numPocketClouds,    new java.math.BigDecimal( numClouds ) );
}
if( strPocketGroup     !== null ){
  engine.setData( strPocketGroup,     strGroup );
}
if( strPocketCondition !== null ){
  engine.setData( strPocketCondition, strCondition );
}
if( strPocketIconUrl !== null ){
  engine.setData( strPocketIconUrl, strIconUrl );
}
if( numPocketWindGust  !== null ){
  engine.setData( numPocketWindGust,  new java.math.BigDecimal( numWindGust ) );
}
if( numPocketWindSpeed !== null ){
  engine.setData( numPocketWindSpeed, new java.math.BigDecimal( numWindSpeed ) );
}
if( numPocketWindDeg   !== null ){
  engine.setData( numPocketWindDeg,   new java.math.BigDecimal( numWindDeg ) );
}
if( numPocketRain      !== null ){
  engine.setData( numPocketRain,      new java.math.BigDecimal( numRain ) );
}
if( numPocketPressure  !== null ){
  engine.setData( numPocketPressure,  new java.math.BigDecimal( numPressure ) );
}
if( numPocketUvi       !== null ){
  engine.setData( numPocketUvi,       new java.math.BigDecimal( numUvi ) );
}
if( numPocketVisibility !== null ){
  engine.setData( numPocketVisibility, new java.math.BigDecimal( numVisibility ) );
}

} //////// END "main()" /////////////////////////////////////////////////////////////////



function toJsDate( bpmsDateOrDatetimeStr ){
  // BPMS Date:     "2020-04-01"  (subtype "Y/M" "M/D" "Y", not supported)
  // BPMS Datetime: "2020-04-01 23:59"
  let year       = 0;
  let monthIndex = 0;
  let day        = 0;
  let hours      = 0;
  let minutes    = 0;

  //  The ECMA/JavaScript Date object has a large number of methods.
  // "Date.parse" is danger (strongly discouraged)
  // - new Date("2014-11-10") // Mon Nov 10 2014 09:00:00 GMT+0900 (JST)
  // - new Date(2014, 10, 10) // Mon Nov 10 2014 00:00:00 GMT+0900 (JST)
  let arrDatetime = bpmsDateOrDatetimeStr.split(" ");
  if( arrDatetime.length === 1 ){
    let arrDateParts = arrDatetime[0].split("-");
    year       = parseInt(arrDateParts[0], 10);
    monthIndex = parseInt(arrDateParts[1], 10) - 1;
    day        = parseInt(arrDateParts[2], 10);
  }
  if( arrDatetime.length === 2 ){
    let arrDateParts = arrDatetime[0].split("-");
    let arrTimeParts = arrDatetime[1].split(":");
    year       = parseInt(arrDateParts[0], 10);
    monthIndex = parseInt(arrDateParts[1], 10) - 1;
    day        = parseInt(arrDateParts[2], 10);
    hours      = parseInt(arrTimeParts[0], 10);
    minutes    = parseInt(arrTimeParts[1], 10);
  }
  return new Date( year, monthIndex, day, hours, minutes );
}



/*
Notes:
- For agriculture, transportation, retail, hotel, restaurant service, etc.
- Weather data in OpenWeatherMap is calculated mechanically based on public info or airport observations.
    - There is a difference from the weather data provided by the weather company.
- The acquired forecast data and historical data can be freely used under the Open Database License.
    - https://openweathermap.org/full-price#licenses
- Datetime up to 48 hours in advance are valid.
    - If a Datetime outside the range is specified, it will be updated with the data 48 hours ahead.
    - Specify with a string starting with "YYYY-MM-DD HH". (Date type + static HH is also acceptable)

Notes-ja:
- 農業・運送業の稼働判断や小売・宿泊・飲食における仕入業務の自動化省力化等に活用されます。
- OpenWeatherMap の気象データは、公的情報や空港観測値などを元に機械的に算出されています。
    - 気象会社による気象データとは、違いがあります。
- 取得した予報データや履歴データは、Open Database License 下で自由に利用できます。
    - https://openweathermap.org/full-price#licenses
- 48時間先までの日時が指定可能です。
    - 範囲外の日時が指定された場合、48時間先のデータで更新されます。
    - "YYYY-MM-DD HH" で始まる文字列で指定します。("日付型データ+固定時刻文字列" でも構いません)
*/


/*
APPENDIX
- Create an API key on the "API keys" page of your personal account beforehand.
    - https://home.openweathermap.org/api_keys
- In this Addon, the weather data is acquired via "One Call API".
    - Available in OpenWeather Free subscription.
- Units of measurement in response
    - (default): temperature in Kelvin and wind speed in meter/sec
    - "metric": temperature in Celsius and wind speed in meter/sec
    - "imperial": temperature in Fahrenheit and wind speed in miles/hour
- Translation samples of weather description field, corresponding language codes
    - eg. "broken clouds: muy nuboso", "overcast clouds: nubes", "light snow: nevada ligera"
    - https://openweathermap.org/api/one-call-api#multi
    - https://openweathermap.org/weather-conditions
- Wind Direction degrees
    - 0 to 11, 349 to 359: N
    - 12 to 33: NNE
    - 34 to 56: NE
    - 57 to 78: ENE
    - 79 to 101: E
    - 102 to 123: ESE
    - 124 to 146: SE
    - 147 to 168: SSE
    - 169 to 191: S
    - 192 to 213: SSW
    - 214 to 236: SW
    - 237 to 258: WSW
    - 259 to 281: W
    - 282 to 303: WNW
    - 304 to 326: NW
    - 327 to 348: NNW
- Latitude Longitude sample
    - Metropolitan Government Building, Tokyo: 35.689472, 139.69175
    - Kiyomizu-dera Temple, Kyoto: 34.994831, 135.785003
    - Waikiki Beach, Hawaii: 21.275278, -157.825
    - Oymyakon, Russia: 63.25, 143.15 (the coldest permanently inhabited settlement on Earth)
    - Use Google Maps, Wikipedia, etc. to obtain the latitude and longitude of any point.
        - https://www.google.co.jp/maps/

APPENDIX-ja
- 個人アカウントの "API keys" ページにて、あらかじめ API Key を生成しておく必要があります。
    - https://home.openweathermap.org/api_keys
- このAddonで、気象データは "One Call API" 経由で取得されます。
    - OpenWeather Free subscription(無料)で利用可能です。
- レスポンス数値の物理単位系
    - (デフォルト): 気温は「ケルビン(絶対温度)」にて、風速は「メートル毎秒」にて表示されます
    - "metric": 気温は「摂氏」、風速は「メートル毎秒」にて表示されます
    - "imperial": 気温は「華氏」、風速は「マイル毎時」にて表示されます
- 天気概況フィールドの翻訳サンプル、および対応言語コード
    - 例 "broken clouds: 曇りがち"、"overcast clouds: 厚い雲"、"light snow: 小雪"
    - https://openweathermap.org/api/one-call-api#multi
    - https://openweathermap.org/weather-conditions
- 風向と角度
    - 0 to 11, 349 to 359: 北の風、北風
    - 12 to 33: 北北東の風
    - 34 to 56: 北東の風
    - 57 to 78: 東北東の風
    - 79 to 101: 東の風
    - 102 to 123: 東南東の風
    - 124 to 146: 南東の風
    - 147 to 168: 南南東の風
    - 169 to 191: 南の風
    - 192 to 213: 南南西の風
    - 214 to 236: 南西の風
    - 237 to 258: 西南西の風
    - 259 to 281: 西の風
    - 282 to 303: 西北西の風
    - 304 to 326: 北西の風
    - 327 to 348: 北北西の風
- 緯度経度サンプル
    - 東京都庁: 35.689472, 139.69175
    - 京都 清水寺: 34.994831, 135.785003
    - ハワイ ワイキキビーチ: 21.275278, -157.825
    - ロシア オイミャコン: 63.25, 143.15 (世界で最も寒い定住地)
    - 任意地点の緯度経度は Google マップや Wikipedia 等で取得してください
        - https://www.google.co.jp/maps/
*/


Download

2021-02-17 (C) Questetra, Inc. (MIT License)
https://support.questetra.com/addons/openweather-weather-forecast-get-by-time/
The Addon-import feature is available with Professional edition.

Notes

  • For agriculture, transportation, retail, hotel, restaurant service, etc.
  • Weather data in OpenWeatherMap is calculated mechanically based on public info or airport observations.
    • There is a difference from the weather data provided by the weather company.
  • The acquired forecast data and historical data can be freely used under the Open Database License.
  • Datetime up to 48 hours in advance are valid.
    • If a Datetime outside the range is specified, it will be updated with the data 48 hours ahead.
    • Specify with a string starting with “YYYY-MM-DD HH”. (Date type + static HH is also acceptable)

Capture

Gets weather forecast for the specific time (corrected to zero minutes) from OpenWeather with specifying latitude and longitude of the world. Not only temperature, humidity and wind speed, but also visibility and sensible temperature can be obtained.

Appendix

  • Create an API key on the “API keys” page of your personal account beforehand.
  • In this Addon, the weather data is acquired via “One Call API”.
    • Available in OpenWeather Free subscription.
  • Units of measurement in response
    • (default): temperature in Kelvin and wind speed in meter/sec
    • “metric”: temperature in Celsius and wind speed in meter/sec
    • “imperial”: temperature in Fahrenheit and wind speed in miles/hour
  • Translation samples of weather description field, corresponding language codes
  • Wind Direction degrees
    • 0 to 11, 349 to 359: N
    • 12 to 33: NNE
    • 34 to 56: NE
    • 57 to 78: ENE
    • 79 to 101: E
    • 102 to 123: ESE
    • 124 to 146: SE
    • 147 to 168: SSE
    • 169 to 191: S
    • 192 to 213: SSW
    • 214 to 236: SW
    • 237 to 258: WSW
    • 259 to 281: W
    • 282 to 303: WNW
    • 304 to 326: NW
    • 327 to 348: NNW
  • Latitude Longitude sample
    • Metropolitan Government Building, Tokyo: 35.689472, 139.69175
    • Kiyomizu-dera Temple, Kyoto: 34.994831, 135.785003
    • Waikiki Beach, Hawaii: 21.275278, -157.825
    • Oymyakon, Russia: 63.25, 143.15 (the coldest permanently inhabited settlement on Earth)
    • Use Google Maps, Wikipedia, etc. to obtain the latitude and longitude of any point.

See also

2 thoughts on “OpenWeather #Weather_Forecast: Get by Time”

  1. Pingback: OpenWeather: Weather Forecast, Get by Date – Questetra Support

  2. Pingback: OpenWeather: Weather History, Get by Time – Questetra Support

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: