
Partager:
Maria is a passionate maker currently working as IoT Developer focused on System Integration & Hardware Development. Also, she is an organizer of IoT Medellin - a tech community that brings together IoT enthusiasts to share knowledge in LATAM.
Suivre les données des appareils en temps réel avec Vonage Messages API et Ubidots
Temps de lecture : 13 minutes
Je considère l l'internet des objets (IdO) est un super-héros : il est pratiquement invisible, mais il améliore notre vie au travail, sur le plan social et sur le plan personnel. Les super-héros ont l'immense pouvoir d'être là où vous en avez besoin, que ce soit dans les villes, les hôpitaux, les établissements d'enseignement, les usines de fabrication, les fermes ou tout autre endroit que vous pouvez avoir à l'esprit. Cela ressemble beaucoup à l'internet des objets, vous ne trouvez pas ?
Mettons-nous à la place de Natalia. Natalia travaille dans le secteur agricole en utilisant Pig Visionune caméra intelligente qui intègre l'intelligence artificielle et les réseaux neuronaux. Grâce à cet appareil, elle peut obtenir des données en temps réel sur le processus de pesage dans les fermes sans stresser les porcs. Que se passe-t-il si Natalia a besoin d'accéder aux données mais qu'elle ne dispose pas d'un accès à l'internet à ce moment précis ? C'est là que l'API Messages API de Vonage de Vonage - et si Natalia demandait les données dont elle a besoin par SMS ?
De nos jours, il existe de nombreux services de messagerie et plateformes de visualisation qui rendent la technologie plus accessible à tous ; nous n'avons pas besoin d'être des ingénieurs experts pour créer des solutions innovantes. De plus, ces services permettent de déployer des solutions complètes en quelques heures. En prenant le cas d'utilisation de Natalia comme référence, ainsi que tous les besoins basés sur les données qui peuvent exister à travers les industries, j'ai pensé qu'il serait formidable d'avoir un système capable d'effectuer une surveillance en temps réel des données de l'appareil indépendamment de l'accès à l'internet.
Dans ce tutoriel, je vais partager les étapes détaillées pour construire ce système en utilisant l'API Vonage Messages API comme service de messagerie et Ubidots comme plateforme IoT. Pour commencer, comprenons l'architecture à mettre en œuvre :
illustration of architecture
L'intégration de ces services se fait par l'intermédiaire d'une UbiFunction, un environnement de Serverless Computing qui va nous permettre de recevoir le message envoyé à notre numéro virtuel via une requête HTTP. Nous sommes alors en mesure de l'analyser pour identifier les appareils et les variables demandées afin d'envoyer la dernière valeur reçue pour chaque variable demandée en tant que réponse.
Il ne fait aucun doute que ce système sera utile pour différents cas d'utilisation. Il suffit de faire preuve d'un peu de créativité pour identifier où il peut être utile pour le projet sur lequel vous travaillez. Sans plus attendre, commençons !
Conditions préalables
Tout appareil disposant d'un accès à l'internet
Configuration de la plateforme IoT
Ubidots permet d'assembler et de lancer rapidement des applications IoT sans avoir à écrire de nombreuses lignes de code - c'est simple mais puissant. Pour commencer à l'utiliser, il suffit d'avoir d'un Account et de n'importe quel appareil disposant d'une connexion internet pour transmettre des données à l API Ubidots.
Configuration de l'appareil
Pour ce projet, j'ai utilisé un Pycon SiPy et PySense 1qui nous permet de surveiller les variables environnementales telles que la température, l'humidité, l'intensité lumineuse et la pression. Cependant, si vous disposez d'un autre matériel qui prend en charge le protocole HTTP, MQTTou TCP/UDP comme protocole de communication, il peut également être intégré. Vous pouvez visiter le centre d'aide Ubidots pour obtenir des tutoriels sur la façon d'envoyer et de contrôler des données vers et depuis la plateforme en utilisant n'importe quel appareil IoT.
L'équipe Pycom ajoute des fonctionnalités supplémentaires chaque semaine sur ses produits, donc avant de commencer à développer, assurez-vous que votre carte fonctionne sous la dernière mise à jour du firmware. De plus, si vous utilisez Windows comme système d'exploitation, vous devez installer les pilotes nécessaires.
*NOTE: Si c'est la première fois que vous développez avec des cartes Pycom, je vous recommande vivement de consulter le guide de démarrage pour vous familiariser avec tous les détails.*
Installer le Pymakr, un plug-in disponible pour Atom et Visual Studio Codepour exécuter et synchroniser des projets sur n'importe quelle carte Pycom. Pymakr ajoute également une console REPL au terminal qui se connecte à la carte.
Ensuite, établissez la communication entre Pymakr et votre carte via Serial ou Telnet, selon votre préférence. Consultez les guides d'installation en fonction de votre éditeur de code :
Code
Ce projet nécessite quelques bibliothèques externes qui doivent être téléchargées et centralisées en un seul endroit pour fonctionner correctement. Si vous souhaitez les télécharger en même temps que le code principal, vous pouvez télécharger ici.
Si vous souhaitez partir de zéro, créez un nouveau projet avec le nom de votre choix. J'ai décidé de l'appeler **_pysense-ubidots-mqtt_**.
Dans le projet **_pysense-ubidots-mqtt_** nous allons gérer les bibliothèques nécessaires et ajouter le code principal. Pour ce faire, créez un nouveau dossier appelé **_lib_**ainsi qu'un nouveau fichier appelé **_main.py_**
Depuis le dépôt de dépôt de bibliothèques pycomtéléchargez les bibliothèques suivantes et placez-les dans le dossier **_lib_** qui vient d'être créé :
Après avoir téléchargé ces bibliothèques, vous devriez avoir la structure suivante dans le dossier du projet :
- lib
- LTR329ALS01.py
- MPL3115A2.py
- pycoproc.py
- pysense.py
- SI7006A20.py
- umqtt
- robust.py
- simple.py
- main.pyCes bibliothèques nous permettent de communiquer avec la carte principale (dans mon cas SiPy), avec le PySense, et de gérer les données avec Ubidots via MQTT.
Copiez le code suivant dans le fichier main.py le code suivant. Ce code publie en permanence les valeurs de température, d'humidité, de pression et d'altitude vers Ubidots :
#!/usr/bin/python
# Include Libraries
from umqtt.robust import MQTTClient
import machine
import time
import pycom
import json
import ubinascii
from network import WLAN
from pysense import Pysense
from LIS2HH12 import LIS2HH12
from SI7006A20 import SI7006A20
from LTR329ALS01 import LTR329ALS01
from MPL3115A2 import MPL3115A2,ALTITUDE,PRESSURE
import gc
gc.collect()
# Define network constants
wifi_ssid = "xxxx" # Set Network's SSID
wifi_password = "xxxx" # Set Network password
# Define Ubidots constants
mqtt_server = "industrial.api.ubidots.com" # 169.55.61.243
mqtt_clientID = ubinascii.hexlify(machine.unique_id(),'').decode()
mqtt_username = "BBFF-xxxx" # Set your Ubidots TOKEN
ubidots_dev_label = "weather-station" # ubinascii.hexlify(machine.unique_id(),':').decode() # Set a device labe
# Constants to manage data rate
last_message = 0
message_interval = 5
'''
Establishes connection with the MQTT server defined
'''
def connect_mqtt():
global mqtt_clientID, mqtt_server
client = MQTTClient(mqtt_clientID, mqtt_server, user=mqtt_username, password=mqtt_username)
client.connect()
print("\nConnected to {} MQTT broker".format(mqtt_server))
return client
'''
Reset the device to restore the connection with the MQTT Server
'''
def restart_and_reconnect():
print("\nFailed to connect to MQTT broker. Reconnecting...")
time.sleep(10)
machine.reset()
'''
Establish network connection
@arg ssid [Mandatory] Network SSID
@arg psw [Mandatory] Network Password
'''
def wifi_connect(ssid, psw):
attempts = 0
print("Starting attempt to connect to WiFi.", end="")
wlan.connect(ssid, auth=(WLAN.WPA2, psw), timeout=5000) # Connect to the WiFi AP provided
# Check network status
while not wlan.isconnected():
time.sleep(0.5)
print(".", end="")
attempts += 1
machine.idle() # Safe power while waiting
if attempts >= 10:
print("\nssid: {}, psw: {}".format(wifi_ssid, wifi_password))
print("\nCould not establish connection with the network provided. Please check the network crendentials or status, and try again.");
time.sleep(0.5)
attempts = 0
machine.reset()
# Network interface parameteres logs
network_settings = wlan.ifconfig()
print("\nWLAN connection succeeded!")
print("IP address: {}".format(network_settings[0]))
print("Subnet: {}".format(network_settings[1]))
print("Gateway: {}".format(network_settings[2]))
print("DNS: {}".format(network_settings[3]))
return True
'''
Reads temperature, humidity, pressure, altitude, and light sensors
@return data, JSON object with sensors readings
'''
def read_sensors():
# Barometric sensor constructor (Pressure (Pascals), Altitud (meters), Temperature (celsius ))
mpl_pressure = MPL3115A2(py, mode=PRESSURE)
mpl_altitude = MPL3115A2(py,mode=ALTITUDE)
# Humidity & Temperature sensor constructor (Humidity (relative humidity), Temperature (celsius))
si = SI7006A20(py)
# Ambient light sensor consturctor (Light levels(luxes))
ltr = LTR329ALS01(py)
# Sensors readings
pressure = mpl_pressure.pressure()
altitude = mpl_altitude.altitude()
temperature_mpl = mpl_altitude.temperature()
temperature_si = si.temperature()
relative_humidity = si.humidity()
ambient_humidty = si.humid_ambient(temperature_si)
dewpoint = si.dew_point()
light = ltr.light()
# Readings logs
print("\nMPL3115A2 | Pressure: {} Pa, Altitude: {} m, Temperature: {} ºC".format(pressure, altitude, temperature_mpl))
print("SI7006A20 | Temperature: {} ºC, Relative Humidity: {} %RH, Ambient Humidity: {} %RH, Dew point: {}".format(temperature_si, relative_humidity, ambient_humidty, dewpoint))
print("LTR329ALS01 | Light (channel Blue lux, channel Red lux): {}\n".format(light))
# JSON build
data = b'{ "pressure" : %s,"altitude" : %s, "temp_mpl" : %s, "temp_si" : %s, "rel_hum" : %s, "amb_hum" : %s, "dew_point" : %s, "lux_blue" : %s, "lux_red" : %s }' % (pressure, altitude, temperature_mpl, temperature_si, relative_humidity, ambient_humidty, dewpoint, light[0], light[1])
return data
# Network's inizalitation
wlan = WLAN(mode=WLAN.STA) # Set STA (Station Aka Client, connects to an AP) as WLAN network interface 'STA_IF' (Station aka client, connects to upstream WiFi Access points)
wlan.antenna(WLAN.EXT_ANT) # Set antenna type (INT_ANT: Internal, EXT_ANT: External)
wifi_connect(wifi_ssid, wifi_password)
# Sensors' inizalitation
py = Pysense()
# Establishes connection with the MQTT server
try:
client = connect_mqtt()
except OSError as e:
restart_and_reconnect()
# Main function
while True:
try:
# Network reconnection
if wlan.isconnected() != True:
wifi_connect(wifi_ssid, wifi_password)
# Publish sensor data every 5 seconds
if (time.time() - last_message) > message_interval:
data = read_sensors()
client.publish(b"/v1.6/devices/%s" % (ubidots_dev_label), data)
last_message = time.time()
except OSError as e:
restart_and_reconnect()
Plutôt que de se contenter d'un simple copier-coller, nous pouvons également examiner le fonctionnement du code. Tout d'abord, les bibliothèques nécessaires doivent être importées :
from umqtt.robust import MQTTClient
import machine
import time
import pycom
import json
import ubinascii
from network import WLAN
from pysense import Pysense
from LIS2HH12 import LIS2HH12
from SI7006A20 import SI7006A20
from LTR329ALS01 import LTR329ALS01
from MPL3115A2 import MPL3115A2,ALTITUDE,PRESSURE
import gcEnsuite, dans les variables suivantes, nous attribuons les informations d'identification du réseau pour établir la connexion :
wifi_ssid = "xxxx"
wifi_password = "xxxx"Pour établir une communication avec un Account Ubidots via MQTT, nous devons définir l'adresse du broker, ainsi que celle du client, et le nom d'utilisateur pour l'authentification de la communication :
Courtier MQTT:
industrial.api.ubidots.comou169.55.61.243.MQTT ClientIdentifiant unique pour la communication client-serveur. Il est recommandé d'utiliser l'adresse MAC de l'appareil comme identifiant du client car il s'agit d'une valeur unique par appareil.
Nom d'utilisateur MQTT: Authentifie la communication avec le broker. Dans le cas d'Ubidots, nous devons assigner le Account token comme nom d'utilisateur.
mqtt_server = "industrial.api.ubidots.com" # 169.55.61.243
mqtt_clientID = ubinascii.hexlify(machine.unique_id(),'').decode()
mqtt_username = "BBFF-xxxx" # Set your Ubidots TOKENEnsuite, attribuez l'étiquette étiquette de l'appareil. Ce label est l'identifiant unique qui nous permettra de communiquer avec Ubidots, soit pour publier, soit pour s'abonner à des données vers/depuis un sujet. Il peut s'agir d'une chaîne de caractères unique ou de l'adresse MAC de l'appareil. Dans mon cas, j'ai attribué weather-station comme étiquette de l'appareil :
ubidots_dev_label = "weather-station"Pour terminer avec les déclarations, attribuez le débit de données souhaité comme suit message_interval. La variable est fixée par défaut à cinq secondes. La variable last_message contiendra la dernière fois qu'un message a été envoyé.
last_message = 0
message_interval = 5Il est maintenant temps de connecter la carte au réseau local. Tout d'abord, nous créons un objet WLAN interface réseau. Comme vous pouvez le voir ci-dessous, l'objet est créé sous la variable wlan et est configuré pour utiliser l'antenne externe, puisque l'appareil est déployé un peu loin du routeur. Si vous souhaitez utiliser l'antenne interne, il vous suffit d'utiliser wlan.antenna(WLAN.INT_ANT).
wlan = WLAN(mode=WLAN.STA)
wlan.antenna(WLAN.EXT_ANT)Ensuite, la fonction wifi_connect() établit la communication avec le réseau spécifié :
wifi_connect(wifi_ssid, wifi_password)Mais que fait exactement la fonction wifi_connect fait-elle ? Comme vous pouvez le voir ci-dessous, elle se charge d'établir la connexion réseau et ne renvoie les paramètres réseau que si la connexion a été établie avec succès. En cas de problème, celui-ci sera signalé et l'appareil sera redémarré pour réessayer la connexion.
def wifi_connect(ssid, psw):
attempts = 0
print("Starting attempt to connect to WiFi.", end="")
wlan.connect(ssid, auth=(WLAN.WPA2, psw), timeout=5000)
while not wlan.isconnected():
time.sleep(0.5)
print(".", end="")
attempts += 1
machine.idle()
if attempts >= 10:
print("\nssid: {}, psw: {}".format(wifi_ssid, wifi_password))
print("\nCould not establish connection with the network provided. Please check the network crendentials or status, and try again.");
time.sleep(0.5)
attempts = 0
machine.reset()
network_settings = wlan.ifconfig()
print("\nWLAN connection succeeded!")
print("IP address: {}".format(network_settings[0]))
print("Subnet: {}".format(network_settings[1]))
print("Gateway: {}".format(network_settings[2]))
print("DNS: {}".format(network_settings[3]))
return True
Ensuite, initialiser la carte PySense comme suit py
py = Pysense()Pour éviter les problèmes de communication avec le courtier, la connexion sera établie avant d'entrer dans le champ de saisie. while. Cependant, en cas de problème de communication, la bibliothèque umqtt gérera une reconnexion automatique. Si la connexion ne peut être établie pour une autre raison, par exemple si le courtier est hors service, la carte sera redémarrée pour tenter d'établir à nouveau la connexion.
try:
client = connect_mqtt()
except OSError as e:
restart_and_reconnect()La fonction connect_mqtt() ouvre une nouvelle connexion MQTT avec le broker spécifié :
def connect_mqtt():
global mqtt_clientID, mqtt_server
client = MQTTClient(mqtt_clientID, mqtt_server, user=mqtt_username, password=mqtt_username)
client.connect()
print("\nConnected to {} MQTT broker".format(mqtt_server))
return clientPour finir, comme vous pouvez le voir ci-dessous, le code principal est en fait en charge de trois processus.
Vérifiez d'abord la connexion au réseau :
if wlan.isconnected() != True:
wifi_connect(wifi_ssid, wifi_password)Publier ensuite les données des capteurs sur Ubidots toutes les 5 secondes :
if (time.time() - last_message) > message_interval:
data = read_sensors()
client.publish(b"/v1.6/devices/%s" % (ubidots_dev_label), data)
last_message = time.time()
Ici, la fonction read_sensors() est chargée de prendre les mesures de tous les capteurs et de construire une charge utile JSON à envoyer à Ubidots :
def read_sensors():
mpl_pressure = MPL3115A2(py, mode=PRESSURE)
mpl_altitude = MPL3115A2(py,mode=ALTITUDE)
si = SI7006A20(py)
ltr = LTR329ALS01(py)
pressure = mpl_pressure.pressure()
altitude = mpl_altitude.altitude()
temperature_mpl = mpl_altitude.temperature()
temperature_si = si.temperature()
relative_humidity = si.humidity()
ambient_humidty = si.humid_ambient(temperature_si)
dewpoint = si.dew_point()
light = ltr.light()
print("\nMPL3115A2 | Pressure: {} Pa, Altitude: {} m, Temperature: {} ºC".format(pressure, altitude, temperature_mpl))
print("SI7006A20 | Temperature: {} ºC, Relative Humidity: {} %RH, Ambient Humidity: {} %RH, Dew point: {}".format(temperature_si, relative_humidity, ambient_humidty, dewpoint))
print("LTR329ALS01 | Light (channel Blue lux, channel Red lux): {}\n".format(light))
# JSON build
data = b'{ "pressure" : %s,"altitude" : %s, "temp_mpl" : %s, "temp_si" : %s, "rel_hum" : %s, "amb_hum" : %s, "dew_point" : %s, "lux_blue" : %s, "lux_red" : %s }' % (pressure, altitude, temperature_mpl, temperature_si, relative_humidity, ambient_humidty, dewpoint, light[0], light[1])
return dataEnfin, redémarrez la carte si une erreur se produit avec le courtier :
except OSError as e:
restart_and_reconnect()La fonction restart_and_reconnect() redémarre la carte pour rétablir la connexion avec le courtier.
def restart_and_reconnect():
print("\nFailed to connect to MQTT broker. Reconnecting...")
time.sleep(10)
machine.reset()Une fois que vous avez le code dans Pymakr, vous pouvez le télécharger dans la carte en appuyant sur le bouton Télécharger pour télécharger le code dans la carte. Attendez quelques secondes jusqu'à ce que l'appareil termine sa compilation.
A partir du compte Ubidots, allez dans Appareils > Appareils et voyez comment un weather-station a été automatiquement créé une fois que les données du capteur ont été reçues :
Ubidots New Device
FACULTATIF Ubidots nous permet de personnaliser les dispositifs et les variables avec des noms, des couleurs, des icônes et des descriptions sympathiques. Il faut savoir que les étiquettes des appareils et des variables ne peuvent pas être modifiées car c'est l'étiquette qui gère la communication entre les appareils et la plateforme.
Dans mon cas, j'ai personnalisé la variable noms, icônes, unitéset les couleurs.
Avant la personnalisation :
Ubidots Generic Device
Après personnalisation :
Ubidots Custom Device
Configuration du tableau de bord
L'une des choses que j'aime le plus lorsque je travaille avec Ubidots, ce sont les visualisations accrocheuses qu'ils fournissent. Ils ont également une grande variété de widgets qui vous permettent de personnaliser entièrement l'apparence de votre tableau de bord. Les tableaux de bord sont une partie très importante des solutions IoT, puisque nous pouvons accéder à toutes les données de nos appareils de n'importe où dans le monde, mais... seulement si nous avons une connexion internet.
Pour créer un tableau de bord, accédez à la section Données > Tableau de bord. Cliquez ensuite sur _Nouveau tableau de bord et donnez-lui le nom souhaité.
Pour ajouter de nouveaux widgets, il suffit de cliquer sur l'icône bleue plus, de sélectionner le type de widget et de définir quelques paramètres de visualisation. A ce stade, il est temps d'être créatif et de commencer à explorer les différents widgets offerts par Ubidots.
Voici à quoi ressemble mon tableau de bord !
Ubidots Dashboard
Pour plus d'informations sur les tableaux de bord et les paramètres des widgets, je vous recommande vivement de consulter les guides suivants :
Configuration de Vonage
Grâce à l Vonage Messages APIde Vonage, nous pouvons activer différentes stratégies de messagerie de manière simple. Il nous permet non seulement d'envoyer des SMSmais aussi de communiquer par le biais de différents canaux, notamment les MMS, Whatsapp, Facebook Messengeret Viber. Pour ce projet, j'utiliserai le canal SMS, car je veux démontrer comment demander des données lorsque vous n'avez pas d'accès à Internet.
Voyons les étapes ci-dessous pour configurer notre compte Vonage :
Accédez à votre Account Vonage. Si vous n'en avez pas déjà un, inscrivez-vous et commencez à construire dès aujourd'hui.
Une fois connecté, trouvez la Clé et secret de l'API de votre Account en haut du tableau de bord de l'API de tableau de bord de l'API de Vonage. Ces informations d'identification sont nécessaires pour établir une communication avec des services externes tels que Ubidots. Sachez que ces identifiants doivent toujours être conservés en toute sécurité et ne jamais être partagés.
Créer une nouvelle application. Vous pouvez le faire en utilisant le tableau de bord de l'API de Vonage - allez simplement à nos applications > + Créer une nouvelle application et lui attribuer un nom - ou en envoyant une demande HTTP. Afin de rendre ce guide convivial, j'ai décidé de le faire directement à partir du tableau de bord. Il suffit de quelques clics, d'attribuer un nom, et le tour est joué !
Pour recevoir des messages entrants, vous devez louer un numéro virtuel. Le numéro peut être loué en utilisant le tableau de bord du développeur, Nexmo CLINexmo, ou l API.
Lier le numéro loué à la demande précédemment créée en cliquant sur le lien dans la section numéro de la demande.
Vonage Virtual Number
Intégration de Vonage et Ubidots
Sur le Account Ubidots, allez dans la section Appareil > Fonctions et cliquez sur l'icône plus située en haut à droite du site pour créer une nouvelle fonction. Pour créer la fonction, vous devez assigner les paramètres suivants :
Nom:
Vonage Messages APIMéthode HTTP:
POSTTemps d'exécution:
NodeJs 10
*NOTE: L'UbiFunction peut également être programmée en Python, mais le code fourni dans ce guide est en NodeJS.
Une fois configuré, appuyez sur le bouton Mise en service pour le mettre en service. À ce stade, le champ HTTPS Endpoint URL avec le point de terminaison qui recevra les messages de Vonage.
Dans mon cas, l'URL générée était : https://parse.ubidots.com/prv/{ubidots_username}/vonage-messages-api.
Ensuite, sur le portail des développeurs de Vonage, naviguez jusqu'à l'onglet Paramètres cliquez sur votre nom d'utilisateur, puis attribuez les paramètres suivants sous la rubrique Paramètre SMS par défaut (paramètres SMS par défaut). Pour terminer, enregistrez les modifications.
Accusés de réception: HTTPS URL du point final généré +
/webhooks/delivery-receipts:
https://parse.ubidots.com/prv/{ubidots_username}/vonage-messages-api/webhooks/delivery-receipts
Messages entrants: HTTPS Endpoint URL généré +
/webhooks/inbound-message:
https://parse.ubidots.com/prv/{ubidots_username}/vonage-messages-api/webhooks/inbound-message
Méthode HTTP:
POST
Lorsqu'un message est envoyé au numéro virtuel, il transmet l'information à ce point d'extrémité.
Retournez maintenant à l'UbiFunction créée, et remplacez le code par défaut par le code ci-dessous :
// Import the 'request-promise' library to handle HTTP requests
var request = require("request-promise");
// Ubidots constants
const UBIDOTS_TOKEN = "BBFF-xxxx";
// Vonage constants
const VONAGE_API_SECRET = "xxxxxx";
/*
* Main function - runs every time the UbiFunction is executed
*
* @arg args, dictionary containing Vonage request data
*/
async function main(args) {
// When sending SMS, delivery receipts will be returned
// status: submitted, delivered,
if (args["status"]) {
return args;
}
// Parses incoming values
var api_key = args["api-key"];
var keyword = args["keyword"];
var msisdn = args["msisdn"];
var text = args["text"];
var to = args["to"];
var msg_type = args["type"];
//var message_timestamp = args['message-timestamp'];
//var messageId = args['messageId'];
// Verify the keyword received to request the data
if (keyword == "UBIDOTS") {
text = text.toLowerCase(); // Converts the text received to lowercase letters
// Filter the requested devices
const devices = /Devices:(.*)/i.exec(text);
const deviceList = devices[1].split(",").map((device) => device.trim());
// Filter the requested variables
const variables = /Variables:(.*)/i.exec(text);
const variableList = variables[1]
.split(",")
.map((variable) => variable.trim());
// "msg" stores the response to be sent
var msg = "Data requested:\n";
// Iterates the deviceList previously filtered
for (const device of deviceList) {
msg = msg.concat("\nDevice: ", device);
// Iterates the variableList previously filtered
for (const variable of variableList) {
// Handle GET request to Ubidots
try {
var response = await ubidots_get_request(
UBIDOTS_TOKEN,
device,
variable
);
msg = msg.concat("\nVariable: ", variable, " = ", response);
} catch (error) {
// Send a reply back in case any error is presented
var vonage_response = await vonage_messages(
api_key,
msg_type,
msisdn,
to,
"The requested data cannot be found. Please verify it and try again."
);
// Pass the error message caught as the function's response
return { message: error.message };
}
}
msg = msg.concat("\n");
}
}
// Send a reply back with the requested data
/* Reply example for multiple devices and variables:
Data requested:
Device: balcony
Variable: humidity = 50.87
Variable: temperature = 36.39
Device: kitchen
Variable: humidity = 55.72
Variable: temperature = 29.45
*/
//var vonage_response = await vonage_messages(api_key, msg_type, msisdn, to, msg);
var vonage_response = await vonage_messages(
api_key,
msg_type,
msisdn,
to,
msg
);
// Pass Vonage's API Response as the function's reponse
return vonage_response;
}
/*
* Handle an HTTP POST request to Vonage Messaging API
* API Documentation: https://developer.nexmo.com/api/messages-olympus#overview
*
* @arg api_key [Mandatory], Nexmo account's API Key
* @arg msg_channel [Mandatory], type of message that you want to send.
* @arg recipient [Mandatory], phone number of the message recipient
* @arg sender [Mandatory], phone number of the message sender
* @arg msg [Mandatory], text of the message
*
* @return message_uuid, UUID of the message
*/
async function vonage_messages(api_key, msg_type, recipient, sender, msg) {
// Base64 encoded API key and secret joined by a colon
var auth =
"Basic " +
Buffer.from(api_key + ":" + VONAGE_API_SECRET).toString("base64");
var options = {
method: "POST",
url: "https://api.nexmo.com/v0.1/messages",
headers: {
Authorization: auth,
"Content-Type": "application/json",
Accept: "application/json",
},
json: {
from: {
type: "sms",
number: sender,
},
to: {
type: "sms",
number: recipient,
},
message: {
content: {
type: msg_type,
text: msg,
},
},
},
};
// Pass UUID of the message sent
return await request.post(options);
}
/*
* Handle an GET request to Ubidots API
* API Documentation: https://ubidots.com/docs/sw/
*
* @arg token [Mandatory], Ubidots account's Token
* @arg device_label [Mandatory], single and unique label of device
* @arg variable_label [Mandatory], single and unique label of variable
*
* @return last_value, variable last value
*/
async function ubidots_get_request(token, device_label, variable_label) {
var options = {
method: "GET",
url:
"https://industrial.api.ubidots.com/api/v1.6/devices/" +
device_label +
"/" +
variable_label +
"/lv",
json: true,
headers: {
"Content-Type": "application/json",
"X-Auth-Token": token,
},
};
var last_value = await request.get(options);
return last_value;
}
/*
* Handle an POST request to Ubidots API
* API Documentation: https://ubidots.com/docs/sw/
*
* @arg token [Mandatory], Ubidots account's Token
* @arg device_label [Mandatory], single and unique label of device
* @arg variable_label [Mandatory], single and unique label of variable
*
* @return last_value, variable last value
*/
async function ubidots_post_request(token, label, body) {
var options = {
method: "POST",
url: "https://industrial.api.ubidots.com/api/v1.6/devices/" + label,
body: body,
json: true,
headers: {
"Content-Type": "application/json",
"X-Auth-Token": token,
},
};
var response = await request.post(options);
return response;
}
Il faut alors remplacer la UBIDOTS_TOKEN par la constante TOKEN Ubidotset le VONAGE_API_SECRET par le Vonage API Secret pour permettre la communication entre l'UbiFunction et les deux services.
// Ubidots constants
const UBIDOTS_TOKEN = "BBFF-xxxx";
// Vonage constants
const VONAGE_API_SECRET = "xxxxxx";N'oubliez pas d'appuyer sur le bouton Mettre en ligne pour enregistrer les modifications apportées !
Le code fourni est commenté en détail pour chacun de ses processus et fonctions, de sorte que sa compréhension ne devrait pas être trop difficile. Toutefois, nous allons mettre en évidence son fonctionnement :
Le code principal d'UbiFunction est chargé de recevoir la charge utile envoyée par Vonage lorsqu'un nouveau SMS est envoyé, ou lorsqu'un autre statut de SMS est signalé.
Ensuite, le SMS reçu est analysé pour identifier la clé API, le mot-clé, le SMS reçu et l'expéditeur.
Si le mot-clé reçu est égal à Ubidots, le texte reçu sera filtré pour créer une liste des appareils et des variables à demander.
Les listes créées sont itérées pour demander la dernière valeur de chacune des variables à Ubidots.
Les données demandées sont concaténées dans une chaîne, qui est envoyée comme réponse à l'expéditeur une fois que toutes les données ont été correctement demandées.
Pour que la demande de données se fasse de manière satisfaisante par SMS, nous devons utiliser les modèles suivants :
Pour un seul appareil:
Demande de SMS:
Ubidots request data
Devices: {device_label}
Variables: {variable_label_1}, {variable_label_2}, {variable_label_n}Réponse par SMS:
Data requested:
Device: {device_label}
Variable: {variable_label_1} = 23
Variable: {variable_label_2} = 246
Variable: {variable_label_n} = 85Pour plusieurs appareils:
Demande de SMS:
Ubidots request data
Devices: {device_label_1}, {device_label_2}, {device_label_n}
Variables: {variable_label_1}, {variable_label_2}, {variable_label_n}Réponse par SMS:
Data requested:
Device: {device_label_1}
Variable: {variable_label_1} = 23
Variable: {variable_label_2} = 246
Variable: {variable_label_n} = 85
Device: {device_label_2}
Variable: {variable_label_1} = 23
Variable: {variable_label_2} = 246
Variable: {variable_label_n} = 85
Device: {device_label_n}
Variable: {variable_label_1} = 23
Variable: {variable_label_2} = 246
Variable: {variable_label_n} = 85*NOTE IMPORTANTE: Les demandes de dispositifs multiples ne seront prises en charge que pour les dispositifs contenant les mêmes variables.
Pour vérifier que tout fonctionne comme il se doit, envoyons deux messages au numéro loué, l'un avec le dispositif créé (weather-station), et un autre avec un appareil qui n'existe pas pour différencier les réponses :
Demande #1:
Ubidots request data
Devices: weather-station
Variables: dew_point, lux_blue, amb_hum, temp_mplDemande #2:
Ubidots request data
Devices: ws
Variables: dew_point, lux_blue, amb_hum, temp_mplLes réponses reçues sont les suivantes :
Satisfactory reply
Device not found
Comme prévu, cela fonctionne correctement ! Maintenant, si nous comparons les valeurs reçues avec les valeurs de notre tableau de bord, nous pouvons voir qu'elles sont identiques :
Ubidots Final Dashboard
Synthèse et prochaines étapes
Lorsque nous parlons de l'internet des objets, la première chose qui nous vient à l'esprit est "Internet", mais il existe en réalité d'autres solutions qui nous permettent d'accéder à ces données même si nous n'avons pas accès à l'internet à un moment ou à un autre.
Dans ce guide, nous avons couvert tout ce que vous devez savoir pour communiquer avec l'API Messages de Vonage et Ubidots pour demander des données via un SMS. Cependant, vous pouvez étendre ce développement et le personnaliser à n'importe quelle application IoT que vous pouvez avoir en tête, qu'il s'agisse d'une application de contrôle de l'éclairage domestique, de réseaux communautaires pour les capteurs, d'un chatbot personnalisé, et bien plus encore.
En outre, vous pouvez explorer les autres canaux offerts par l'API Messages de Vonage Messages APIJe suis certain qu'avec cette application, vous pourrez commencer à travailler sur votre prochain super-héros :)