IBM BluemixとNode.jsでお天気通知!―Facebook Messenger Bot(3) / BluemixのAPIで天気情報を取得

WSやAzureを始めたとしたクラウドサービス全般を触っていく連載「クラウドサービス研究スタジオ」。この連載では、IaaS,PaaS,BaaS,SaaSなど幅広い形態のサービスを実際に使ってレポートしていきます!

今回作るもの

こんにちは、エンジニアのちゃんとくです。テクニカルライターとしてdotstudioに参加しています。

今回は、2016年に公開された話題のMessenger Platformを使って、Facebook Messenger Botを作りIBM Bluemixにホスティングしてみます。

BotプログラムはNode.jsで作成し、IBM Bluemixで提供されているWeather Company Dataから天気情報を取得して、IBM Bluemixにホスティングし、運用します。

下記の構成で手順を紹介します。

  • IBM Bluemixの設定
  • Botのベースを作成
  • 天気情報を取得
  • Facebook Messenger Botをデプロイ

今回はIBM BluemixのWeather Company Dataから天気情報を取得する方法を説明していきます。

8,568通り、あなたはどのタイプ?

筆者の環境

  • OS X El Capitan(v10.11.6)
  • Node.js v8.2.1

8,568通り、あなたはどのタイプ?

Weather Company Dataとは

IBM Bluemixで提供されているサービスの一つで、APIで世界中の任意の場所の10日先までの気象データを取得することができます。

レスポンスの言語を指定でき、日本語にも対応しています。グローバルなデータでは言語変換がネックになることが多いので嬉しい仕様ですね。

また1分あたり10コール・1ヶ月に10,000コールまで無料で、手軽に試すことができます。(実稼働する際には料金体系をよく確認してください。)

今回は第1回で作成したアプリケーションにWeather Company Dataサービスを追加するところから天気情報を取得するところまでやってみます。

Bluemixのアプリケーションにサービスを追加する

Bluemixのコンソールを開き、メニューからサービス > データ&分析を選択します。

「データ&分析サービスの作成」を選択します。

「Weather Company Data」を検索し選択します。

「地域・組織・スペース・接続」はそれぞれ接続したいアプリケーションのものを選択しましょう。ここでは1本目に作成したアプリケーションを選びます。

その他のサービス名や資格情報名はデフォルトのままでも変更しても大丈夫です。

作成すると、アプリケーション側にサービスが追加されます。クリックしてサービスページに移動しましょう。

APIを作成する

サービスの「管理」に移動し、APIをクリックして移動します。

APIで取得できる情報の一覧が表示されます。今回は「Daily Forecast」を選択しましょう。

Daily ForecastのAPI一覧です。latitude(緯度)とlongitude(経度)を指定して3日後までの情報が取得できる一番上のAPIを利用してみます。

APIをクリックするとフォームが開きます。

取得したい地点の緯度経度をそれぞれ入力します。(サンプルは秋葉原の緯度経度です)都市の緯度経度を取得できるAPIも用意されていますが、今回はGoogleのGeocodingを使用しました。「language」はja-JPを指定します。

入力して「Try it out!」をクリックします。このとき認証を求められる場合がありますが、「キャンセル」を選択して先に進めます。(Bluemixアカウントだと弾かれます)

入力した情報でAPIが生成されるので、「Request URL」をコピーしておきます。

このURLをブラウザなどで試してみるとわかりますが、このままでは認証ができておらず利用することができません。先ほどのサービスのページの「サービス資格情報」の項目に移動し、「新規資格情報」を選択します。

任意の名前をつけ、「追加」します。

作成できたら「資格情報の表示」を開き、「username」と「password」の値をそれぞれ取得します。

APIを試してみる

前回オウム返しを試したディレクトリに移動し、app.jsを以下のように変更します。(新しくディレクトリを作成する場合はrequestモジュールをインストールしてください)<username><password>は上記で取得したものに置き換えます。

'use strict';

const request = require('request');

// bluemixの設定
const USERNAME = '<username>';
const PASSWORD = '<password>';
const LATITUDE = '35.698353';
const LONGITUDE = '139.773114';
const WEATHER_URL = `https://${USERNAME}:${PASSWORD}@twcservice.au-syd.mybluemix.net/api/weather/v1/geocode/${LATITUDE}/${LONGITUDE}/forecast/daily/3day.json?language=ja-JP`;

/**
 * 気象データをまるごと取得
 * @return {JSON}
 */
const getData = () => {
  request({
    method: 'GET',
    url: WEATHER_URL
  }, (e, res, body) => {
    if (!e && res.statusCode == 200) {
      console.log(JSON.parse(body));
    } else {
      console.log('Error: ', body);
    }
  });
}

getData();

ひとまず実行してみます。

このデータから、Botで返したい内容を切り出しましょう。

気象データから必要な部分を切り出す

今日から3日後までのデータがforcastsの中に配列で入っているので、「今日・明日・明後日・明々後日」という文字列に対して対応する天気を返すメッセージを作ります。それ以外の文字列が来た場合はとりあえず「いつの天気を知りたいですか?」というメッセージを返すようにします。

気象データの中にはたくさん情報がありますが、narrativeという天気と気温が一文になった値を使ってみます。

'use strict';

const request = require('request');

// Bluemixの設定
const USERNAME = '<username>';
const PASSWORD = '<password>';
const LONGITUDE = '35.698353';
const LATITUDE = '139.773114';
const BASE_PATH = `https://${USERNAME}:${PASSWORD}@twcservice.au-syd.mybluemix.net/api/weather/v1/geocode/${LONGITUDE}/${LATITUDE}/forecast/daily/3day.json?language=ja-JP`;

/**
 * APIから気象データを取得
 */
const getWeatherForecast = () => {
  return new Promise((resolve, reject) => {
    request({
      url: BASE_PATH,
      method: 'GET'
    }, (e, res, body) => {
      if (!e && res.statusCode == 200) {
        resolve(body);
      } else {
        reject(`Error: ${body}`);
      }
    });
  });
}

/**
 * いつの予報を返すか判定
 * @param {string} text
 * @return {number}
 */
const getForecastDay = (text) => {
  const day = {'今日': 0, '明日': 1,  '明後日': 2, '明々後日': 3};
  return day[text];
}

/**
 * @param {res} data
 * @param {number} day
 * @return {string}
 */
const dataToMessage = (res, day) => {
  return res.forecasts[day].narrative;
}

const main = async text => {
  let forecastDay = await getForecastDay(text);
  let message;
  if (forecastDay === undefined) {
    message = 'いつの天気を知りたいですか?';
  } else {
    let res = await getWeatherForecast();
    message = await dataToMessage(JSON.parse(res), forecastDay);
  }
  console.log(message);
}

main(process.argv[2]).catch(e => {
  console.log(e);
});

確認してみる

実行部分で引数に渡しているprocess.argv[2]の部分はコマンドライン引数を受け取ります。コマンドラインから実行してみましょう。

これでほしい天気情報が返ってくるようになりました!

まとめ

今回はIBM Bluemixのサービスを使って、天気情報を取得する部分をつくってみました。ホスティングするクラウド上に簡単に追加できるので連携がとても簡単です。

Bluemixの会話分析や機械学習APIなども同じように利用できるので、Bot作成と相性がよさそうです。とりあえず無料でサクッと試せるところが嬉しいですね。

次回は2本目に作ったFacebook Messanger Botと組み合わせ、いよいよBotをデプロイしてみたいと思います。

それではまた!

取材・執筆:dotstudio, inc. ちゃんとく

大学までは文系で法学を学んでいたが「モノを作れる人」に憧れて知識ゼロからWebエンジニアの道へ。転職し現在はIoT中心のエンジニア・テクニカルライターとして活動。Node.jsユーザグループ内の女性コミュニティ「Node Girls」を主催。Twitter: @tokutoku393 / dotstudio, inc.

※本記事は「CodeIQ MAGAZINE」掲載の記事を転載しております。

PC_goodpoint_banner2

Pagetop