Publié par
Il y a 2 années · 6 minutes · IoT

Atelier – Plateforme 1 – AWS (2/3)

Les recettes IoT de l'atelier Xebia

La semaine dernière, nous avons envoyé les données notre objet connecté vers AWS. Cette semaine, nous allons compléter la liste de nos exigences fonctionnelles en ajoutant les services additionnels, et en gérant le downlink.

Stocker les données.

Pour ceux qui ont l’habitude de AWS, il n’y aura pas vraiment de surprise. Amazon offre en effet un service de base de données non relationnelle orientée document, à savoir DynamoDB. Et comme AWS sait si bien le faire, l’intégration entre IoT et DynamoDB est aisée.

Retournons donc dans l’onglet IoT. Nous allons ajouter une nouvelle règle de gestion.

AWS IoT

Il suffit ensuite de choisir DynamoDB dans la liste déroulante. Fait très appréciable, si votre base n’est pas préexistante, AWS vous permet de la créer à partir de cet écran. Nous verrons que ce n’est pas le cas chez tous les fournisseurs.

Les mécanismes internes de DynamoDB, et notre façon d’accéder aux données nous pousse vers un design simple : créer un clé primaire composite, avec l’identifiant de l’objet comme clé de hachage (toutes les données relatives à un objet se retrouveront sur la même partition), et le timestamp de la mesure comme clé de tri (les données seront ordonnées chronologiquement sur le disque). Petite subtilité, que je n’ai pas réussi à m’expliquer : votre colonne time doit être au format string, faute de quoi DynamoDB refusera vos messages. Il semblerait que bien que le JSON de debug généré dans S3 montre que le champ time est un format number, mais que la communication entre ioT et Dynamo le « convertit » en string.

DynamoDB

AWS IoT

Créez votre action, et en déclenchant votre objet connecté (ou une simulation via Postman), vous devriez voir votre table se remplir :

DynamoDB AWS

Alerter par email

Mettons maintenant en place une simple règle métier : envoyer un mail d’alerte si la température dépasse 27°C. Là encore, tout se fait au niveau des actions disponibles dans le module IoT.

DynamoDB AWS

Il suffit d’adapter la requête de sélection des données pour qu’elle reflète cette règle simple. On ajoute donc une restriction dans la colonne Condition.

Souscrire à Amazon Web Service

En ce qui concerne l’action déclenchée, nous allons utiliser le service de notification d’AWS, SNS. Là encore, chose agréable, il est possible de créer la file SNS (et le rôle associé) directement depuis le module IoT.

Ensuite, direction SNS, pour ajouter un envoi de mail lors de la réception d’un message dans la file.

Et là, magie, dès que votre objet envoie à Sigfox un message contenant une température supérieure à 27°C, Lambda transmet le message à IoT, qui fait suivre le message à SNS, qui transforme ce message en email :

Notification AWS

Pour un email un peu plus élaboré, il faut concocter une architecture un peu plus complexe, qui enverra un évènement dans le service dédié, SES.

Mettre à jour un dashboard

Dernier étage de la fusée, pousser les données collectées sur un Dashboard « temps réel ». Là au moins, c’est simple, AWS ne propose pas ce type de service. Vous avez donc deux choix : héberger votre propre instance (par exemple en utilisant Dashing) ou bien vous reposer sur un service SaaS externe. Nous avons choisi cette dernière solution, avec un service de dashboarding extrêmement simple, Dashku.

Une fois inscrit, nous allons créer un tableau de bord basique, affichant les dernières valeurs reçues par chacun de nos trois capteurs.

Sigfox IoT

Pour cela, il faut pousser à chacun des trois panels un fichier JSON en REST. Vous pouvez obtenir un exemple de code d’appel depuis NodeJs en cliquant sur l’engrenage, puis sur la pastille verte. Le code ressemble à celui ci :

var request = require("request");

var data = {
  "bigNumber": 500,
  "_id": "56f028b053146d7909011xxx",
  "apiKey": "7c3585c7-3ac8-45fb-840a-3e33d7e6fxxx"
};

request.post({url: "https://dashku.com/api/transmission", body: data, json: true});

L’apiKey est identique pour chacun des panels ; en revanche, l’_id varie.

Pour que notre dashboard retrouve ses petits, il est nécessaire d’éditer chacun des widgets, pour les rendre plus parlant. Paramétrez donc les onglets HTML, CSS, et Javascript pour remplacer data par le nim de vos champs dans le JSON émis par le module IoT (temperature, humidity et luminance).

Dasku IoT sigfox

Il reste donc à faire le pont entre le module IoT d’AWS et un appel REST. Nous l’avons fait dans un sens lorsque nous avons créé le bridge Sigfox, nous pouvons le faire dans l’autre sens en utilisant Lambda comme fonction de sortie au module IoT.

Reprenons donc notre Rule ‘Simple Debug’. Nous pouvons, en plus de S3, lui ajouter une sortie vers une Lambda, via le menu Edit actions.

IoT AWS resources

Comme vous en avez maintenant l’habitude, il est possible de créer une nouvelle Lambda directement depuis ce menu.

Nous pouvons créer la Lambda directement depuis l’éditeur en ligne, celle ci est suffisamment simple pour qu’elle ne requiert pas un packaging évolué. Nous avons simplement réécrit la fonction extend pour éviter d’avoir à importer le package utils.

// Rewrite to avoir npm require
function extend(obj1,obj2){
    var obj3 = {};
    for (var attrname in obj1) { 
        obj3[attrname] = obj1[attrname]; 
    }
    for (var attrname in obj2) { 
        obj3[attrname] = obj2[attrname]; 
    }
    return obj3;
}

// AWS Lambda handler
exports.handler = function(event, context) {
    var httpCallsEmited = 0;
    var httpCallsEnded = 0;

    console.log('Input :', event);
    
    var data = {
        "temperature": event.temperature,
        "humidity": event.humidity,
        "luminance": event.luminance,
        "time": event.time, 
        "device": event.device,
        "apiKey": "7c3585c7-3ac8-45fb-840a-3e33d7e6fxxx"
    };
    

    function endHttpCall(err) {
        if (err) {
            context.fail("ERROR in http call");
        } else {

            httpCallsEnded++;
            if(httpCallsEmited==httpCallsEnded){
                context.succeed("SUCCESS");  
            }
        }
    }

    httpCallsEmited = 3;

    sendRequest(extend(data, {_id: "56f028b053146d7909011xxx"}), endHttpCall);
    sendRequest(extend(data, {_id: "56f028b453146d7909011xxx"}), endHttpCall);
    sendRequest(extend(data, {_id: "56f028b853146d7909011xxx"}), endHttpCall);
};

function sendRequest(data, callback){
    var http = require('https');
    
    var options = {
        rejectUnauthorized: false,
        host: 'dashku.com',
        port: 443,
        path: '/api/transmission',
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        }
    };
    
    var req = http.request(options, function(res) {
        res.setEncoding('utf8');
        res.on('data', function (chunk) {
            console.log("body: " + chunk);
            callback();
        });
        res.on('error', function (err) {
            console.log("body: " + chunk);
            callback(err);
        });
    });

    req.write(JSON.stringify(data));
    console.log(JSON.stringify(data))
    req.end();
}

Si tout s’est bien passé, chaque émission de votre objet Sigfox devrait maintenant mettre à jour votre tableau de bord Dashku :

IoT sigfox Dashku

Cliffhanger

Nous en avons fini du traitement des données environnementales émises par notre objet connecté. Reste maintenant un gros morceau : le traitement des données en downlink, depuis notre cloud vers notre objet. Mais à chaque jour suffit sa peine ; nous verrons cela une prochaine fois.

Pablo Lopez

Pablo est directeur technique chez Xebia et formateur Hadoop certifié par Cloudera au sein de Xebia Training .

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *