
シェア:
Sudipto is an undergraduate student at the University of Delhi with a background in Computer Science and Mathematics. He is always excited and curious to know how things work and how they are built. He has experience in building applications with JavaScript, TypeScript, Python and Java with research interests in distributed computing and recommender systems.
Messages APIで大気質レポートサービスを構築する
所要時間:4 分
既存のアプリケーションを拡張して、複数のコミュニケーション・チャンネルと相互作用させることを考えたことがあるだろうか?このアイデアを使って、大気汚染や気候変動などの問題に注意を向けることができたらどうでしょう?
世界大気質指標プロジェクトは2007年に始まった非営利プロジェクトである。彼らの使命は、大気汚染に対する認識を促進し、世界中の大気質情報へのアクセスを確保することである。彼らは、世界中の気象・大気質モニタリングステーションからのデータにアクセスするためのREST APIを提供している。他のデータソースを使用して、社会問題に焦点を当てたサービスを構築することもできる!
この例では、Node.js(JavaScriptランタイム)と Vonage Messages APIを使い、WhatsAppとFacebook Messengerで指定した場所の現在の空気の質に関する情報を送信するサービスを構築します。
これからビルドするサンプルのソースコードは GitHub.
Vonage API Account
To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.
開発環境のセットアップ
最小限の設定でインターネット上に公開するために ngrokトンネルを開く必要があります。インストール後 ngrokをインストールしたら、ターミナルを開いて ngrok http 3070を実行して、ローカルのポート3070をインターネットに公開します。必ず PORT変数 .env.で出力されたHTTPS URLをコンソールにコピーし、メモしてください。 ngrokをコンソールにコピーし、メモしておく。

アプリケーションに必要な依存関係をインストールしましょう。を実行します。 npm init -yを実行して package.jsonファイルを作成します。このプロジェクトでは、Node.js用の一般的なウェブ・アプリケーション・フレームワークであるExpress.jsと、HTTPクライアント・ライブラリであるAxios、環境変数を管理するモジュールであるDotenvを使用する。後ほど、DedentとCommander.jsも活用して、さらにいくつかの機能を実装する予定だ。これらのモジュールをインストールするには
ソースコードに時々変更を加えるので、変更を継続的に監視し、アプリケーションを自動的に再起動するNodemonをインストールすることで、キー入力をいくつか節約することができます。開発依存として
このチュートリアルでは、エントリーポイントを lib/index.js.を追加または更新します。 mainと scriptキーを追加または更新します。 package.jsonを追加または更新し、nodemonを使用してアプリケーションを実行します:
// package.json
{
...
"main": "lib/index.js",
...
"scripts": {
"start": "node .",
"dev": "nodemon .",
},
...
}メイン・ディレクトリの .env.exampleの内容をメイン・ディレクトリの .env.Vonage API Dashboardにログインしたら、APIキーとAPIシークレットを見つけて、その値を .env.この後のセクションで割り当てられる追加の変数もいくつかあります。
Messages APIを使用して受信メッセージを受け取る
Vonageがあなたのバーチャル電話番号または他のチャネルのいずれかを介して着信メッセージを受信するたびに、VonageサーバはJSONペイロードを持つ定義されたWebhookエンドポイントにHTTPリクエストを行います。このチュートリアルでは /webhook/inboundルートを確立します。
このリクエストを確実に受信するために、Vonage API Dashboardの "Messages and Dispatch "にあるSandbox Environmentを設定する必要があります。Inbound Message Webhook (HTTP POST)を次のように設定します。 <ngrok-https-url>/webhook/inboundとして設定し、"Save webhooks "をクリックする。

同じページでメッセージを送信するテストアカウントをリンクします。WhatsAppとMessengerチャンネルの "サンドボックスに追加 "リンクをクリック。その後、携帯電話のQRコードをスキャンするか、指定されたリンクをクリック。通常、サンドボックス用に設定された番号またはページにパスフレーズを送信します。テストアカウントをリンクし、ウェブフックのエンドポイントを設定したら、次に進むことができます。ダッシュボードに記載されているサンドボックスの電話番号をアドレス帳に保存しておくと、簡単にアクセスできます。
をリッスンするExpress.jsアプリケーションを構築する。 3070最低限必要なのは、そのルートで HTTP POST リクエストを受け付け、ステータスコードが 200.Express.js アプリケーションでは、このペイロードは req.bodyオブジェクトを通してアクセスできます。ペイロードリクエストデータを見るには、アプリケーションを実行します。 npm run dev.
// lib/index.js
require("dotenv").config();
const express = require("express");
const app = express();
const PORT = process.env.PORT || 3070;
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.post("/webhook/inbound", (req, res) => {
console.log(req.body);
res.status(200).end();
});
app.listen(PORT, () => console.log(`Listening on Port ${PORT}...`));
WhatsAppからサンドボックス番号にメッセージを送信し、端末ウィンドウの出力を確認してください。メッセンジャーアプリからサンドボックスページにメッセージを送信し、出力を確認して下さい。

上記の例で示された出力は、以下の検証によって異なるチャンネルが区別可能であることを示している。 req.body.from.type.チャネルによって、インバウンドメッセージは電話番号かページ/アカウントIDのどちらかであることにも注意。送信されたメッセージは、リクエストボディの req.body.messageオブジェクトを通してアクセスできます。
の値を VONAGE_NUMBERに受信した電話番号を設定する。 req.body.to.numberそして VONAGE_PAGE_IDのページIDを req.body.to.idのそれぞれの変数に設定する。 .envのそれぞれの変数に設定する。実際には、これはVonageアプリケーションにリンクされたWhatsAppビジネスアカウント番号とFacebookページIDに置き換えられます。
Messages APIを使用したメッセージの送信
Vonage Messages API を使用してチャネルにメッセージを送信するには、API エンドポイントにメッセージオブジェクトを含む HTTP POST リクエストを送信します。サンドボックスを使用する場合、エンドポイントは https://messages-sandbox.nexmo.com/v0.1/messages.
メッセージ Messages APIリファレンスを見ると、リクエストには Authorizationヘッダが含まれていなければなりません。 Basic base64(apiKey):base64(apiToken)または Bearer jwtTokenとメッセージ・オブジェクトがリクエスト・ボディに含まれていなければならない。これを使うには /lib/utils.jsファイルを更新してください:
// lib/utils.js
require("dotenv").config();
const Axios = require("axios");
const sendMessage = async (message, body) => {
await Axios.post(
"https://messages-sandbox.nexmo.com/v0.1/messages",
{
from: {
type: body.from.type,
number: process.env.VONAGE_NUMBER
},
to: {
type: body.from.type,
number: body.from.number
},
message: {
content: {
type: "text",
text: message
}
}
},
{
auth: {
username: process.env.VONAGE_API_KEY,
password: process.env.VONAGE_API_SECRET
}
}
);
};
module.exports = {
sendMessage,
};
ヘルパー関数 sendMessageは、定義された WhatsApp 番号に送信するメッセージの本文を受け取ります。メッセージオブジェクトは複数のチャンネルをサポートするように動的に構築できます。
ファイルを更新します。 /lib/index.jsファイルを更新し、ウェブフック関数の中で、以下のように送信したいメッセージで sendMessage関数を呼び出します:
// lib/index.js
...
const { sendMessage } = require("./utils");
app.post("/webhook/inbound", (req, res) => {
sendMessage("Thanks for sending a message!", req.body);
res.status(200).end();
});
...
MessagesAPIを使ってWhatsAppやMessengerとメッセージを送受信する会話サービスのスケルトンを構築しました。WhatsAppのVonage Sandbox番号にメッセージを送信してみてください!
世界大気質指標APIからデータを取得する
World Air Quality Index Projectは、ほぼリアルタイムの大気質データをJSON APIで提供している。データにアクセスするには APIトークンにサインアップする.このページで提供したメールアドレスに認証リンクが届き、APIトークンを表示するページにリダイレクトされます。の値を AQICN_TOKENの値を .envの値を、そのページに表示されるトークンに設定します。
WAQI Search APIを使用して、特定の都市の大気質モニタリングステーションを検索します。へのHTTP GETリクエストには、2つの必須クエリパラメータがあります。 https://api.waqi.info/search/への HTTP GET リクエストには、2 つの必須クエリパラメータがあります。 keywordステーション名または都市名を検索するための検索用語として使用されます。 tokenWAQI API トークンを参照します。
HTTPのAPIリクエストをデバッグするための一般的なGUIアプリケーションであるPostmanやInsomniaからリクエストを行うと、キーワード londonに対するレスポンスには 限定されたステーションのメタデータが含まれていることがわかる。
// GET https://api.waqi.info/search/?token={{AQICN_TOKEN}}&keyword=london
{
"status": "ok",
"data": [
{
"uid": 5724,
"aqi": "36",
"time": {
"tz": "+01:00",
"stime": "2020-11-04 05:00:00",
"vtime": 1604462400
},
"station": {
"name": "London",
"geo": [
51.5073509,
-0.1277583
],
"url": "london"
}
},
...
]
}
検索結果の一番上の結果を取得し、それを使って期待されるデータを取得するために、アプリケーションのユーティリティ関数を実装する時が来た。
// lib/utils.js
...
const getStation = async (keyword) => {
const stationData = await Axios.get(
"https://api.waqi.info/search/",
{
params: {
token: process.env.AQICN_TOKEN,
keyword
}
});
if (stationData.data.data.length === 0) {
return { error: "No Stations Found. Try Again." };
}
return stationData.data.data[0].station;
};
...
ステーションからフィードデータを取得するには、もう一度 HTTP GET リクエストを行い、今度は WAQI City/Station Feed API にリクエストします。このAPIのエンドポイントは https://api.waqi.info/feed/<station-url>/ここで station-urlの urlキーの値に対応する場所です。 stationオブジェクトのキーの値に対応します。 getStation.API トークンもクエリ・パラメータとして必要です。
ステーションへのリクエストは londonJSONオブジェクトが返される。 生測定値と詳細なステーションのメタデータを含むJSONオブジェクトが返される:
// GET https://api.waqi.info/feed/london/?token={{AQICN_TOKEN}}
{
"status": "ok",
"data": {
"aqi": 36,
"idx": 5724,
"attributions": [
{
"url": "http://uk-air.defra.gov.uk/",
"name": "UK-AIR, air quality information resource - Defra, UK",
"logo": "UK-Department-for-environment-food-and-rural-affairs.png"
},
{
"url": "https://londonair.org.uk/",
"name": "London Air Quality Network - Environmental Research Group, King's College London",
"logo": "UK-London-Kings-College.png"
},
{
"url": "https://waqi.info/",
"name": "World Air Quality Index Project"
}
],
"city": {
"geo": [51.5073509, -0.1277583],
"name": "London",
"url": "https://aqicn.org/city/london"
},
"dominentpol": "pm25",
"iaqi": {
"co": { "v": 7.4 },
"h": { "v": 92 },
"no2": { "v": 23.3 },
"o3": { "v": 2.9 },
"p": { "v": 1029.4 },
"pm10": { "v": 16 },
"pm25": { "v": 36 },
"so2": { "v": 3.4 },
"t": { "v": 3.8 },
"w": { "v": 3.7 }
},
"time": {
"s": "2020-11-04 05:00:00",
"tz": "+00:00",
"v": 1604466000,
"iso": "2020-11-04T05:00:00Z"
},
"forecast": {},
"debug": { "sync": "2020-11-04T14:41:04+09:00" }
}
}このリクエストを行うための別のユーティリティ関数を実装する。この関数は stationオブジェクトをパラメータとして受け取り、それを getStationから取得し、API にステーションからのデータを問い合わせます。更新 lib/utils.jsを更新する。 getStationData関数を追加します:
// lib/utils.js
...
const getStationData = async (station) => {
const aqiData = await Axios.get(
`https://api.waqi.info/feed/${station.url}/`,
{
params: {
token: process.env.AQICN_TOKEN
}
}
);
if (aqiData.data.data.status === "error") {
return { error: "Could not get data. Try Again." };
}
return aqiData.data.data;
};
...
これでユーティリティ関数を使用して、Vonage Messages APIがサポートするチャネルでメッセージを受信した際にWAQI APIに問い合わせを行い、このデータを処理した後に意味のある応答を送り返すことができるようになりました。
関連情報を返信する
WAQI APIから取得したデータを処理し、「読み取り可能」にする必要があります。データを報告するために2つの異なるテンプレートを使用することができます - 1つは、大気質インデックスとUS EPA 2016スケールによる健康への影響を含む簡単なレポート用、もう1つは、それぞれの測定単位とともに汚染物質レベルと気象情報に言及する詳細なレポート用です。
| AQI | Air Pollution Level | Health Implications | Cautionary Statement (for PM 2.5) |
|---|---|---|---|
| 0-50 | Good | Air quality is considered satisfactory, and air pollution poses little or no risk. | None. |
| 51-100 | Moderate | Air quality is acceptable; however, for some pollutants there may be a moderate health concern for a very small number of people who are unusually sensitive to air pollution. | Active children and adults, and people with respiratory disease, such as asthma, should limit prolonged outdoor exertion. |
| 101-150 | Unhealthy for Sensitive Groups | Members of sensitive groups may experience health effects. The general public is not likely to be affected. | Active children and adults, and people with respiratory disease, such as asthma, should limit prolonged outdoor exertion. |
| 151-200 | Unhealthy | Everyone may begin to experience health effects; members of sensitive groups may experience more serious health effects. | Active children and adults, and people with respiratory disease, such as asthma, should avoid prolonged outdoor exertion; everyone else, especially children, should limit prolonged outdoor exertion. |
| 201-300 | Very Unhealthy | Health warnings of emergency conditions. The entire population is more likely to be affected. | Active children and adults, and people with respiratory disease, such as asthma, should avoid all outdoor exertion; everyone else, especially children, should limit outdoor exertion. |
| 300+ | Hazardous | Health alert: everyone may experience more serious health effects. | Everyone should avoid all outdoor exertion. |
また、汚染物質やさまざまな気象指標の名称を、不可解な略語から解決しなければならない。私たちは WAQI APIリファレンスを参照し、そのためのユーティリティ関数を実装することができる。また、文字列補間メソッドや、オプションで以下のようなヘルパー関数を定義することもできます。 WhatsApp用メッセージのフォーマット.これらのヘルパー関数の実装は、GitHub のソースコードにあります。
Dedentは、複数行の ES6 JavaScript テンプレート・リテラルを扱うときに便利なモジュールです。より読みやすくするために空白を維持するために、ソースコードで多用されているのを見かけるかもしれません。
Commander.jsでインバウンドメッセージを解析する
サービス専用のメッセージを解析し、コマンドごとに異なるアクションを取るのに便利である。この Commander.jsライブラリはコマンドラインアプリケーション用に作られたもので、コマンドと引数の受信メッセージを解析するのに使うことができる。
// lib/index.js
...
const { Command } = require("commander");
const trigger = new Command("vonage-aqi");
// override default cli behaviour
trigger.exitOverride();
trigger.addHelpCommand(false);
trigger
.command("aqi <searchterm...>")
.alias("a")
.action(async (searchterm) => {
searchterm = searchterm.join(" ");
// fetch and send the brief report
});
trigger
.command("info <searchterm...>")
.alias("i")
.action(async (searchterm) => {
searchterm = searchterm.join(" ");
// fetch and send the detailed report
});
trigger
.command("act")
.action(async () => {
// send links to resources and information
});
trigger
.command("help")
.alias("h")
.action(async () => {
// send help and usage information
});
...
app.post("/webhook/inbound", async (req, res) => {
try {
// pass the incoming message text to Commander.js
trigger.parse(
req.body.message.content.text
.trim().toLowerCase().split(" "),
{
from: "user"
}
);
} catch (err) {
// send message based on the type of error
} finally {
res.status(200).end();
}
});
...Commander.jsライブラリーは、必須引数、オプション引数、可変引数、コマンドエイリアスをサポートしており、手作業でコマンドと引数をチェックするよりもはるかに簡単に作業を行うことができる。
ステータスウェブフックによる確実な配信
でメッセージを送った後に起こったイベントをリッスンするために、新しいルートをセットアップすることができる。 /webhook/status.これを ngrokトンネルに追加し、Vonage API Dashboard の Status Webhook として保存し、"Save webhooks" をクリックします。
// lib/index.js
...
app.post("/webhook/status", (req, res) => {
console.log(req.body);
res.status(200).end();
});
...
次にサービスがメッセージを受信し、それに返信するとき、送信されたメッセージの異なる状態を観察する。この req.body.statusフィールドには、ウェブフック・リクエストが送信されたときにメッセージ・オブジェクトが遷移したステータスが格納されます。メッセージが Vonage サーバによって受信されると、オブジェクトは submitted状態になります。配信が成功した場合、ステータスの値を受け取るはずです。 deliveredの後に read.
エラーがあった場合、ステータスは次のようになる。 rejectedまたは undeliverableであり、理論的にはこのケースを別に扱うことができる。Vonageは、メッセージの配送に失敗した場合、一定の間隔で再試行することで、多くの重労働をこなしていることに注意してください。
WhatsAppとMessengerの遊び場
アプリケーションが実行中であることと、正しい ngrokトンネルがメッセージサンドボックスに保存されていることを確認してください。携帯電話を手に取り、サンドボックスのアカウントにメッセージを送る。実際に動くと気持ちいいでしょう?
WhatsApp

メッセンジャー

まとめ
このプロジェクトは、Vonage APIがあらゆるアプリケーションといかに柔軟に統合できるかを示しています。WhatsAppとMessengerを使ったマルチチャンネルコミュニケーションを取り上げ、この例ではWAQI APIを使用しました。これを読んで、あなたが何を作るか興味があります!
さらに読む
このチュートリアルで示したコードと、動作しているアプリケーションの完全なソースコードは GitHub リポジトリ.
のMessages APIの関連ドキュメントをチェックしてください。 Vonage API Developerおよび Vonage API リファレンス.との通信方法については WhatsAppと メッセンジャーの動作については Vonage API Developer をご覧ください。
Vonageアカウントをお持ちでない場合、 今すぐサインアップ次のプロジェクトでVonage APIをご利用ください!私たちに連絡する ツイッターまたは コミュニティSlackチャンネル.Vonage APIを使って何を作る予定かお知らせください!
シェア:
Sudipto is an undergraduate student at the University of Delhi with a background in Computer Science and Mathematics. He is always excited and curious to know how things work and how they are built. He has experience in building applications with JavaScript, TypeScript, Python and Java with research interests in distributed computing and recommender systems.
