
Partager:
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.
Créer un service de rapports sur la qualité de l'air avec Messages API
Temps de lecture : 13 minutes
Avez-vous déjà pensé à étendre votre application existante pour qu'elle interagisse avec plusieurs canaux de communication ? Et si nous pouvions utiliser cette idée pour attirer l'attention sur des questions telles que la pollution de l'air et le changement climatique ?
Le projet d'indice mondial de la qualité de l'air est un projet à but non lucratif lancé en 2007. Sa mission est de promouvoir la sensibilisation à la pollution de l'air et d'assurer l'accès aux informations sur la qualité de l'air dans le monde entier. Il fournit des API REST pour accéder aux données des stations de surveillance de la météo et de la qualité de l'air dans le monde entier. Vous pouvez utiliser d'autres sources de données pour créer un service axé sur les questions sociales !
Dans cet exemple, nous construirons un service, alimenté par Node.js - un moteur d'exécution JavaScript et la Vonage Messages APIde Vonage, qui enverra des informations sur la qualité de l'air à un endroit donné via WhatsApp et Facebook Messenger.
Le code source de l'exemple que nous allons construire est également disponible sur 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.
Configurer l'environnement de développement
Nous devrons ouvrir un tunnel ngrok à notre application pour l'exposer sur Internet avec une configuration minimale. Après avoir installé ngrokouvrez un terminal et exécutez ngrok http 3070 pour exposer votre port local 3070 à l'Internet. Assurez-vous d'utiliser la variable PORT dans .env. Copiez l'URL HTTPS telle qu'imprimée par ngrok sur la console et notez-la.

Il est maintenant temps d'installer les dépendances nécessaires à l'application. Exécutez npm init -y pour créer un fichier package.json fichier. Nous utiliserons Express.js - un framework d'application web populaire pour Node.js et Axios - une bibliothèque client HTTP pour ce projet, ainsi que Dotenv - un module de gestion des variables d'environnement. Plus tard, nous utiliserons également Dedent et Commander.js pour implémenter d'autres fonctionnalités. Installez ces modules en exécutant :
Comme nous apporterons de temps à autre des modifications à notre code source, nous pouvons économiser quelques frappes de clavier en installant Nodemon, qui surveille en permanence les modifications et redémarre l'application automatiquement. Installez-le en tant que dépendance de développement en exécutant
Pour ce tutoriel, notre point d'entrée sera un fichier nommé lib/index.js. Ajoutez ou mettez à jour les éléments main et les script dans package.json pour exécuter l'application à l'aide de nodemon :
// package.json
{
...
"main": "lib/index.js",
...
"scripts": {
"start": "node .",
"dev": "nodemon .",
},
...
}Copiez le contenu de .env.example dans le répertoire principal dans un nouveau fichier appelé .env. Une fois connecté au tableau de bord de l'API de Vonage, trouvez votre clé et votre secret d'API et mettez à jour les valeurs dans le fichier .env. Il y a également quelques variables supplémentaires qui seront assignées dans les sections suivantes.
Recevoir un message entrant à l'aide de Messages API
Chaque fois que Vonage reçoit un message entrant sur votre numéro de téléphone virtuel ou via l'un des autres canaux, les serveurs de Vonage effectuent une requête HTTP vers un point de terminaison webhook défini avec une charge utile JSON. Pour ce tutoriel, nous établissons que la route /webhook/inbound de notre application écoutera toutes les demandes de ce type.
Pour être sûr de recevoir cette demande, nous devons configurer l'environnement Sandbox que vous trouverez sur le tableau de bord de l'API Vonage sous "Messages and Dispatch". Définissez le Webhook du message entrant (HTTP POST) comme suit <ngrok-https-url>/webhook/inbound et cliquez sur "Save webhooks".

Sur la même page, liez un compte de test à partir duquel vous enverrez des messages. Cliquez sur les liens "Ajouter à l'Environnement de test" sur les canaux WhatsApp et Messenger. Scannez ensuite le code QR sur votre téléphone ou cliquez sur le lien donné. Il s'agit généralement d'envoyer une phrase de passe à un numéro ou une page provisionnée pour la sandbox. Une fois que vous avez lié votre Account de test et défini le point de terminaison du webhook, vous pouvez continuer plus loin. Enregistrez le numéro de téléphone du bac à sable mentionné sur le tableau de bord dans votre carnet d'adresses pour y accéder facilement.
Nous allons construire une application Express.js pour écouter sur le port 3070 Les exigences minimales sont d'accepter les requêtes HTTP POST sur cette route et d'envoyer un code d'état de 200. Dans notre application Express.js, ce payload est accessible via l'objet req.body dans notre application Express.js. Pour jeter un coup d'œil aux données de la requête payload, lancez l'application en exécutant 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}...`));
Essayez d'envoyer un message depuis WhatsApp vers le numéro de sandbox et observez la sortie sur la fenêtre de terminal sur laquelle votre application s'exécute. Envoyez un autre message depuis l'appli Messenger vers la page du bac à sable et observez à nouveau la sortie.

Les sorties présentées dans l'exemple ci-dessus montrent que les différents canaux peuvent être distingués en validant req.body.from.type. En fonction du canal, nous constatons également que le message entrant peut provenir soit d'un numéro de téléphone, soit d'une page ou d'un Account ID. Il est possible d'accéder au message envoyé grâce à l'objet req.body.message dans le corps de la requête.
Réglez la valeur de VONAGE_NUMBER au numéro de téléphone tel qu'il a été reçu en req.body.to.number et VONAGE_PAGE_ID à l'ID de la page comme dans req.body.to.id aux variables respectives dans .env car nous utilisons le bac à sable. En pratique, cela serait remplacé par un numéro de compte professionnel WhatsApp et un identifiant de page Facebook liés à une application Vonage.
Envoyer un message à l'aide de Messages API
En utilisant l'API Messages de Vonage, l'envoi d'un message à un canal implique l'envoi d'une requête HTTP POST avec un objet de message au point de terminaison de l'API. Lorsque vous utilisez le bac à sable, le point de terminaison est : https://messages-sandbox.nexmo.com/v0.1/messages.
La référence de l'API Référence de l'API Messagesmontre que la demande doit contenir un en-tête Authorization avec la valeur Basic base64(apiKey):base64(apiToken) ou Bearer jwtToken et un objet message dans le corps de la requête. Pour l'utiliser, mettez à jour votre fichier /lib/utils.js avec l'exemple ci-dessous :
// 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,
};
La fonction d'aide sendMessage prend le corps du message pour l'envoyer au numéro WhatsApp défini. L'objet message peut être construit dynamiquement pour prendre en charge plusieurs canaux ; vous pouvez l'implémenter dans une autre fonction utilitaire.
Mettez à jour votre fichier /lib/index.js dans la fonction webhook, appelez la fonction sendMessage avec le message que vous souhaitez envoyer, comme indiqué ci-dessous :
// 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();
});
...
Nous avons construit un squelette pour un service de conversation qui utilisera l'API Messages pour envoyer et recevoir des messages en utilisant WhatsApp et Messenger. Essayez d'envoyer un message au numéro Sandbox de Vonage sur WhatsApp !
Récupérer les données des API de l'indice mondial de la qualité de l'air
Le projet d'indice mondial de la qualité de l'air fournit des API JSON pour les données sur la qualité de l'air en temps quasi réel. Pour accéder aux données, inscrivez-vous pour obtenir un jeton API. Nous recevrons un lien de vérification sur l'adresse e-mail que nous fournissons sur cette page qui nous redirigera vers une page affichant le jeton API. Définir la valeur de AQICN_TOKEN dans .env à la clé affichée sur cette page.
Recherchez une station de surveillance de la qualité de l'air pour une ville donnée avec l'API de recherche du WAQI. La requête HTTP GET à https://api.waqi.info/search/ comporte deux paramètres d'interrogation obligatoires - keyword utilisé comme terme de recherche pour trouver le nom d'une station ou d'une ville et token qui fait référence au jeton de l'API du WAQI.
En effectuant la requête à partir de Postman ou d'Insomnia - deux applications GUI populaires pour le débogage des requêtes API HTTP - nous pouvons voir que la réponse pour le mot-clé london contient des métadonnées de station limitées pour chaque résultat de recherche.
// 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"
}
},
...
]
}
Il est temps d'implémenter une fonction utilitaire pour notre application afin d'obtenir le premier résultat de la recherche et de l'utiliser pour récupérer les données attendues.
// 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;
};
...
Pour obtenir les données d'alimentation de la station, faites une autre requête HTTP GET, cette fois à l'API WAQI City/Station Feed. Le point de terminaison de cette API est https://api.waqi.info/feed/<station-url>/ où station-url correspond à la valeur de la clé url dans l'objet station renvoyé par getStation. Le jeton API est également requis en tant que paramètre de la requête.
La demande de la station a été renvoyée pour londonun objet JSON est renvoyé, qui contient les mesures brutes et les métadonnées détaillées de la stationcomme indiqué ci-dessous :
// 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" }
}
}Mettre en œuvre une autre fonction utilitaire pour effectuer cette demande. Cette fonction prend en paramètre l'objet station en tant que paramètre, qui est récupéré à partir de getStationet interroge l'API pour obtenir les données de la station. Mettre à jour lib/utils.js en ajoutant la fonction suivante getStationData suivante :
// 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;
};
...
Nous pouvons maintenant utiliser nos fonctions utilitaires pour interroger l'API WAQI sur la réception d'un message sur un canal pris en charge par l'API Messages de Vonage et renvoyer une réponse significative après avoir traité ces données.
Répondre avec des informations pertinentes
Les données que nous obtenons des API du WAQI doivent être traitées et rendues "lisibles". Nous pouvons utiliser deux modèles différents pour rapporter les données - l'un pour un rapport bref contenant l'indice de qualité de l'air et les implications pour la santé selon l'échelle US EPA 2016 - et l'autre pour un rapport détaillé mentionnant les niveaux de polluants et les informations météorologiques avec leurs unités de mesure respectives.
| 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. |
Source : AQI Basics, AirNow
Nous devons également résoudre les noms des polluants et des différentes mesures météorologiques à partir des abréviations cryptiques. Nous pouvons consulter la référence de l'API du référence de l'API WAQI et mettre en œuvre des fonctions utilitaires pour ce faire. Nous pouvons également définir des fonctions d'aide supplémentaires dans lesquelles nous pouvons utiliser des méthodes d'interpolation de chaînes et éventuellement formater les messages pour WhatsApp. L'implémentation de ces fonctions d'aide peut être trouvée dans le code source sur GitHub.
Dedent est un module utile lorsqu'il s'agit de littérales de gabarits JavaScript ES6 sur plusieurs lignes. Il peut être utilisé de manière intensive dans le code source pour maintenir les espaces blancs afin d'améliorer la lisibilité.
Analyse des messages entrants avec Commander.js
Il est utile d'analyser les messages destinés explicitement au service et de prendre des mesures différentes selon les commandes. Le fichier Commander.js initialement conçue pour les applications en ligne de commande, peut être utilisée pour analyser le message entrant afin d'en extraire les commandes et les arguments.
// 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();
}
});
...La bibliothèque Commander.js prend en charge les arguments obligatoires et facultatifs, les arguments variables et les alias de commande, ce qui facilite grandement la tâche par rapport à la vérification manuelle des commandes et des arguments.
Garantir la livraison avec le Webhook d'état
Nous pouvons créer une nouvelle route pour écouter les événements qui se sont produits après l'envoi d'un message à l'adresse /webhook/status. Assurez-vous d'ajouter ceci au tunnel ngrok et de l'enregistrer en tant que Status Webhook sur le tableau de bord de l'API Vonage et de cliquer sur "Save webhooks".
// lib/index.js
...
app.post("/webhook/status", (req, res) => {
console.log(req.body);
res.status(200).end();
});
...
La prochaine fois que notre service reçoit un message et y répond, nous observons des états distincts du message qui a été envoyé. Le champ req.body.status contiendra l'état dans lequel l'objet du message est passé lorsque la demande de webhook a été envoyée. Lorsque le message est reçu par les serveurs de Vonage, l'objet est dans l'état submitted état. Si la livraison a effectivement réussi, nous devrions recevoir une valeur d'état qui serait probablement delivered suivie de read.
En cas d'erreur, le statut peut être rejected ou undeliverable et nous pourrions, en théorie, traiter ce cas séparément. Il est à noter que Vonage se charge d'une grande partie du travail en réessayant à intervalles réguliers en cas d'échec de la livraison du message.
Terrain de jeu de WhatsApp et Messenger
Assurez-vous que l'application est en cours d'exécution et que le tunnel correct est enregistré dans l'Environnement de test des messages. ngrok est sauvegardé dans le bac à sable des messages. Prenez votre téléphone et envoyez des messages aux comptes de l'Environnement de test. N'est-ce pas agréable de voir que la chose fonctionne vraiment ?
WhatsApp

Messager

Conclusion
Ce projet montre à quel point les Applications de Vonage sont flexibles pour s'intégrer avec à peu près n'importe quelle application. Nous avons abordé la communication multicanal avec WhatsApp et Messenger et utilisé les API WAQI pour cet exemple. Je suis curieux de savoir ce que vous pourrez construire après avoir lu cet article !
Pour en savoir plus
Vous pouvez trouver le code présenté dans ce tutoriel et le code source complet de l'application fonctionnelle sur le dépôt GitHub.
Consultez la documentation pertinente pour l'API Messages sur Développeur API de Vonage et Référence API Vonage. Apprenez-en plus sur la façon dont les communications avec WhatsApp et Messenger sur Vonage API Developer.
Si vous n'avez pas de compte Vonage, inscrivez-vous dès aujourd'hui pour obtenir des crédits gratuits et utiliser les API de Vonage dans votre prochain projet ! Contactez nous sur sur Twitter ou rejoignez le canal Slack de la communauté. Faites-nous savoir ce que vous prévoyez de construire avec les API de Vonage !
Partager:
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.
