OpenWeather: 気象履歴, 時刻を指定して取得
OpenWeather: 気象履歴, 時刻を指定して取得 (OpenWeather: Weather History, Get by Time)
任意時刻(毎時ゼロ分に補正)の気象履歴を OpenWeather から取得します。世界中の緯度と経度を指定できます。気温、湿度、風速だけでなく、降雪量や最大瞬間風速なども取得可能です。
Configs
  • A: API Key をセットしてください *#{EL}
  • B1: 表示単位系をセットしてください (摂氏:”metric” or 華氏:”imperial”)#{EL}
  • B2: 天気概況フィールドを翻訳したい場合、言語コードをセットしてください (例 “ja” “es”)#{EL}
  • C: 日時(ワークフロー基盤の時刻)、緯度、経度を3行に分けてセットしてください *#{EL}
  • E1: 気温が格納される数値型データ項目を選択してください (更新)
  • E2: 体感気温が格納される数値型データ項目を選択してください (更新)
  • E3: 露点温度が格納される数値型データ項目を選択してください (更新)
  • F2: 湿度(%)が格納される数値型データ項目を選択してください (更新)
  • F3: 雲量(%)が格納される数値型データ項目を選択してください (更新)
  • G1: 天気区分が格納される文字列型データ項目を選択してください (更新)
  • G2: 天気概況が格納される文字列型データ項目を選択してください (更新)
  • G3: 天気アイコンURLが格納される文字列型データ項目を選択してください (更新)
  • H0: 最大瞬間風速が格納される数値型データ項目を選択してください (更新)
  • H1: 風速が格納される数値型データ項目を選択してください (更新)
  • H2: 風向角度(0:真北 90:真東)〔風が吹いてくる方向〕が格納される数値型データ項目を選択してください (更新)
  • I1: 1時間降雪量(mm)が格納される数値型データ項目を選択してください (更新)
  • I1: 1時間降水量(mm)が格納される数値型データ項目を選択してください (更新)
  • I2: 海面更正気圧(hPa)が格納される数値型データ項目を選択してください (更新)
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 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 numPocketSnow      = configs.getObject( "SelectConfI0" );
const numPocketRain      = configs.getObject( "SelectConfI1" );
const numPocketPressure  = configs.getObject( "SelectConfI2" );


//// == 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#history
// request1, prepare
let getUri1  = "https://api.openweathermap.org/data/2.5/onecall/timemachine";
let request1 = httpClient.begin(); // HttpRequestWrapper
    request1 = request1.queryParam( "appid", strApiKey ); 
    request1 = request1.queryParam( "lat", strLat ); 
    request1 = request1.queryParam( "lon", strLon ); 
    request1 = request1.queryParam( "dt", ( dateSpecified.getTime() /1000 + "" ) );
    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: 37.25,
  lon: 139.15,
  timezone: "Asia/Tokyo",
  timezone_offset: 32400,
  current: { 略 },
  hourly: [
    {
      dt: 1614038400,
      temp: 2.78,
      feels_like: 0.43,
      pressure: 1016,
      humidity: 80,
      dew_point: -0.28,
      clouds: 100,
      wind_speed: 0.45,
      wind_deg: 320,
      wind_gust: 1.34,
      weather: [
        {
          id: 601,
          main: "Snow",
          description: "雪",
          icon: "13d"
        }
      ],
      snow: {
        1h: 0.64
      }
    },
*/
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)
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 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 numSnow        = 0;
if( response1Obj.hourly[numHourlyId].hasOwnProperty('snow') ){
    numSnow        = response1Obj.hourly[numHourlyId].snow['1h'];
}
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;


//// == 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( 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( numPocketSnow      !== null ){
  engine.setData( numPocketSnow,      new java.math.BigDecimal( numSnow ) );
}
if( numPocketRain      !== null ){
  engine.setData( numPocketRain,      new java.math.BigDecimal( numRain ) );
}
if( numPocketPressure  !== null ){
  engine.setData( numPocketPressure,  new java.math.BigDecimal( numPressure ) );
}

} //////// 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 snow removal (snowfall), forecasting of vegetable prices (temperature and cloud in production), 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 5 days ago
    - If a date and time outside the range is specified, an error will occur.
    - 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
- 5日前(世界標準時換算)までの日時が指定可能です。
    - 範囲外の日時が指定された場合、エラーとなります。
    - "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 (Historical weather data)".
    - 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 (Historical weather data)" 経由で取得されます。
    - 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-25 (C) Questetra, Inc. (MIT License)
https://support.questetra.com/ja/addons/openweather-weather-history-get-by-time/
Addonファイルのインポートは Professional でのみご利用いただけます

Notes

  • 気象履歴データは、除排雪の計画業務(降雪量)や野菜価格の変動予測(生産地の気温と雲量)等で活用されます。
  • OpenWeatherMap の気象データは、公的情報や空港観測値などを元に機械的に算出されています。
    • 気象会社による気象データとは、違いがあります。
  • 取得した予報データや履歴データは、Open Database License 下で自由に利用できます。
  • 5日前(世界標準時換算)までの日時が指定可能です。
    • 範囲外の日時が指定された場合、エラーとなります。
    • “YYYY-MM-DD HH” で始まる文字列で指定します。(”日付型データ+固定時刻文字列” でも構いません)

Capture

任意時刻(毎時ゼロ分に補正)の気象履歴を OpenWeather から取得します。世界中の緯度と経度を指定できます。気温、湿度、風速だけでなく、降雪量や最大瞬間風速なども取得可能です。

Appendix

  • 個人アカウントの “API keys” ページにて、あらかじめ API Key を生成しておく必要があります。
  • このAddonにおける気象データは “One Call API (Historical weather data)” 経由で取得されます。
    • OpenWeather Free subscription(無料)で利用可能です。
  • レスポンス数値の物理単位系
    • (デフォルト): 気温は「ケルビン(絶対温度)」にて、風速は「メートル毎秒」にて表示されます
    • “metric”: 気温は「摂氏」、風速は「メートル毎秒」にて表示されます
    • “imperial”: 気温は「華氏」、風速は「マイル毎時」にて表示されます
  • 天気概況フィールドの翻訳サンプル、および対応言語コード
  • 風向と角度
    • 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 等で取得してください

See also

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

%d人のブロガーが「いいね」をつけました。