Après un petit temps de silence, pour des raisons personnelles et notamment l’arrivé d’un petit Thomas, voici un nouveau post. Étant un utlisateur occassionnel d’Autolib j’ai besoin d’avoir en flux continu l’état des stations à coté de chez moi (nb de voiture, nb de place). Autour de chez moi, j’ai plusieurs stations Autolib et je dois consulter régulierement l’application iPhone en fonction de mes besoins. Afin de me simplifier la vie j’ai installé et configuré chez moi la solution HomeAssistant, j’utilisais pour cela l’API de Paris en mode REST/HTTP. Malheureusement, le nombre de requetes est limitée et plus on doit superviser de stations (voiture, place libre) plus on doit faire d’appels REST, HomeAssistant est un très bon produit mais un peu limité en terme de scripting du composant RESTful. Je me suis dit, pourquoi ne pas :

MQTTiser l’API Autolib avec Node-Red

Architecture

Voila en résumé l’architecture de la solution que l’on va mettre en place.

MQTT Archi

  • Description du schéma de principe :
    • Un flux/flow Node-Red va consommer régulierement la DataParis API.
    • Le retour est parsé et découpé pour chacune des stations Autolib.
    • Chaque message est envoyé dans le topic MQTT correspond à sa station.
    • Le client HomeAssistant s’abonne ensuite aux topics des stations souhaitées.

API de Paris

L’API de Paris propose un grand nombre d’Objets sur lequels il est possible de requeter (PLU, liste des prénoms, Titularisations). La plupart du temps ces données sont des données froides, ceux sont des extracts de base de données interne à la Ville de Paris . Seules deux sources de données sont temps réel c’est à dire qu’elles sont mise à jour lors de chaque appel, il s’agit du status des stations Velib et des stations Autolib. Dans notre cas, nous allons utiliser cette dernière :

Cette API indique en temps réel l’état des 1119 stations avec la requete HTTP suivante (on se limitera ici à 2 stations) :

curl https://opendata.paris.fr/api/records/1.0/search/?dataset=autolib-disponibilite-temps-reel&rows=2
{
    "nhits": 1119,
    "parameters": {
        "dataset": ["autolib-disponibilite-temps-reel"],
        "timezone": "UTC",
        "rows": 2,
        "format": "json"
    },
    "records": [{
        "datasetid": "autolib-disponibilite-temps-reel",
        "recordid": "a1c22a2c66ac55e6de9b0badcf5fe4f71c33e652",
        "fields": {
            "status": "ok",
            "city": "Paris",
            "kind": "STATION",
            "station_type": "station",
            "charging_status": "operational",
            "rental_status": "operational",
            "cars_counter_bluecar": 3,
            "cars": 3,
            "public_name": "Paris/Ordener/65",
            "geo_point": [48.8913517, 2.3507171],
            "charge_slots": 0,
            "postal_code": "75018",
            "cars_counter_utilib_1.4": 0,
            "subscription_status": "nonexistent",
            "slots": 1,
            "id": "paris-ordener-65",
            "address": "65 rue Ordener",
            "cars_counter_utilib": 0
        },
        "geometry": {
            "type": "Point",
            "coordinates": [2.3507171, 48.8913517]
        }
    }, {
        "datasetid": "autolib-disponibilite-temps-reel",
        "recordid": "8b1396096c4c2761ec5120ffdd3fd824b18a824d",
        "fields": {
            "status": "ok",
            "city": "Paris",
            "kind": "STATION",
            "station_type": "station",
            "charging_status": "operational",
            "rental_status": "operational",
            "cars_counter_bluecar": 5,
            "cars": 5,
            "public_name": "Paris/Raymond Losserand/229",
            "geo_point": [48.828, 2.306022],
            "charge_slots": 0,
            "postal_code": "75014",
            "cars_counter_utilib_1.4": 0,
            "subscription_status": "nonexistent",
            "slots": 1,
            "id": "paris-raymondlosserand-229",
            "address": "229 Rue Raymond Losserand",
            "cars_counter_utilib": 0
        },
        "geometry": {
            "type": "Point",
            "coordinates": [2.306022, 48.828]
        }
    }]
}

Il n’est pas difficile de comprendre le schéma et le resultat obtenu, l’ensemble des informations nécessaire à note besoin sont là :

  • cars :
    • nombre de voiture dispo sur la station.
  • slots :
    • nombre de place libre sur la station.

Nous avons aussi des informations de type descriptifs (nom de la station, coordonnées GPS, etc…). Elles pourront etre utilisés dans d’autres cas d’usage bien sûr, sur une carte par exemple.

MQTT

Le Protocole MQTT est un protocole MoM dans le domaine de l’IoT. Ce protocole est largement utilisé dans le monde de l’Internet des Objets car il est ouvert, leger et consommant peu de ressources reseau. Dans la version 3.x, il n’implemente pas de gestion de Transaction, et se limite au mode Topic ou autrement appelé Publish/Subscribe. Plusieurs niveaux de QoS sont définisable tant sur le message, sur le topic que sur le broker lui-même. Plusieurs features sont intéressantes notamment la notion d’adressage hierarchique des topics, il est possible de s’abonner dans ce cas là à tout un sous-groupe de topic :

  • /nasdaq/#
    • Pour tout les indices du nasdaq
  • /meteo/fr/92/#
    • Pour toute les villes du départements du 92.

Utilisé au dessus de TCP/IP et bindé sur le port 1883, il est standardisé par l’OASIS, l’ISO et IANA.

Broker MQTT

Plusieurs Broker MQTT existent sur le marché, nous allons en voir deux OpenSource développé sur des langages différents. Nous allons comme cela testé leur interoperabilité.

Mosquitto

Développé par la Fondation Eclispe, il est écrit en C. Il possede une bon support de la communauté et est régulièrement mis à jour. Disponible sur l’ensemble des environement Unix like, il est distribué par les systemes de packaging de chaque OS.

Version 1.4.15
Date Fev 2018
License EPL/EDL
Langage C

Warning

Je n’ai pas encore trouvé de système de supervision un peu serieux, je suis preneur par vos retours.

Dans ce post nous allons simplement utilisé le client mosquitto qui est très facile d’utilisation.

mosquitto_sub -i <id client> -h <host> -t <topic> -v

mosquitto_sub -i mosquitto_client -h localhost -t "/autolib/boulognebillancourt/#" -v

Info

Mosquitto est disponible en mode container Docker.

ActiveMQ Artemis

La fondation Apache quand à elle propose le project commumautaire Apache ActiveMQ Artemis. Il s’agit du petit frère du projet Apache ActiveMQ. Comme souvent dans les projet de la Fondation, le projet est developpé en Java. Au contraire de Mosquitto qui est mono protocole, Artemis support un grand nombre de protocole ouvert comme : AMQP v1.0, MQTT, STOMP, OpenWire. Il est compatible JMS 1.0 et 2.0 pour les utilisateurs de l’API JMS. Il est aussi facilement clusterisable afin de garantir une haute disponible.

Version 2.5.0
Date Mars 2018
License Apache 2.0
Langage Java

Info

ActiveMQ Artemis vient en standard avec un outil de monitoring

Node-red

Le project Node-Red est un outil de creation et d’execution EIP dédié à l’IoT et executé sur la plateforme NodeJs. C’est un outil léger tout en disposant d’une IHM complete de création de flow. L’IHM permet de créer des flows de traitement en assemblant et reliant des composants d’entrée et/ou sortie en eux via des liens.

Voici une liste non exhaustive des composants disponible :

  • mqtt in/out.
  • email in/out.
  • file in/out.
  • http/tcp/udp in/out.
  • timer, switch, change, range, join, sort, batch, function, debug, log.
  • csv, html, json, yaml, xml, html.

Lorsque le flow est validé, il suffit simplement de le deployer pour l’executer directement.

| ————: | :————– | | Version | v0.18.4 | | Date | Jan 2018 | | License | Apache 2.0 | | Langage | JavaScript |

Info

Node-Red s’execute très bien sur un RaspberryPi

Flow Autolib

Pour notre use-case, nous allons faire un appel toute les 20s (cf info) sur l’API de Paris, on verifie rapidement que l’on recupere bien un retour HTTP/200. On découpe ensuite la liste des stations message par message. Puis on crée dynamiquement pour chaque message et donc chaque station, le bon adressage de Topic pour l’envoie au broker MQTT. Le composant RBE est simplement là pour faire transiter le message que si il y a effectivement un changement de contenu.

MQTT Autolib flow

Info

L’API de Paris est limitée 5000 req/j. Cela fait dans une journée, pas plus d’une requete toute les 17s. Donc pour etre large, j’ai pris toutes les 20s.

Le code du flow est disponible sur le repository suivant :

https://github.com/gautric/mqtt-4-autolib/blob/master/flows_mbp.g.a.net.json

Résultat

Monitoring ActiveMQ

Nous voyons bien dans l’outil de monitoring les divers topics qui dependent directement des stations Autolib, nous voyons aussi la connexion de deux clients MQTT, l’un étant le Node-Red, l’autre le client Mosquitto.

Moniroting

J’ai configuré les messages MQTT afin d’etre en mode retain à minima, c’est pour cela que l’on retrouve un prefix technique à l’adressage des topics des stations Autolib. Cette fonctionnalité permettra de conserver une dernière valeur si HomeAssistant tombe ou bien le flux Node-Red.

Dashboard HomeAssistant

Mon Dashboard HomeAssistant commence à être bien complet avec plusieurs onglets pour chaque cas d’usage. J’ai un onglet en particuler qui affiche l’ensemble des informations de transport dont Autolib, la RATP ainsi que le traffic des voitures en IDF.

Configuration

Après avoir envoyé les messages dans le broker ActiveMQ Artemis, il faut que le Dashboard HomeAssistant puisse lire correctement les données. Pour cela, il suffira de rajouter dans sa liste dans le fichier sensor.yaml, les sensors de type MQTT. Il suffit de comprendre le schéma du message recu et de récuperer le bon élément du message.


* platform: mqtt
  name: "Autolib Boulogne-Billancourt/Henri Martin/2 Cars"
  state_topic: "/autolib/boulognebillancourt/henrimartin/2"
  value_template: '\{\{value_json.fields.cars\}\}'
  unit_of_measurement: ''

* platform: mqtt
  name: "Autolib Boulogne-Billancourt/Henri Martin/2 Slots"
  state_topic: "/autolib/boulognebillancourt/henrimartin/2"
  value_template: '\{\{value_json.fields.slots\}\}'
  unit_of_measurement: ''

.....

* platform: mqtt
  name: "Autolib Last Update"
  state_topic: "/autolib/\_lastCall"
  unit_of_measurement: ''

ScreenShot

Et pour finir, voici le résultant dans le Dashboard HomeAssistant. J’ai rajouté un petit hook dans le flow nominal afin d’avoir l’heure de la dernière mise à jour des données. Il s’agit de verifier si tout ce passe bien.

HA

Mosquitto Client

L’utilisation du client mosquitto est interopérable facilement avec le broker ActiveMQ Artemis.

mosquitto_sub -i mosquitto_client -h localhost -t "/autolib/boulognebillancourt/#" -v

/autolib/boulognebillancourt/henrimartin/2 {"datasetid":"autolib-disponibilite-temps-reel","recordid":"a165c1342525a1c27a24eb1cdf781eddf6aaa149","fields":{"status":"ok","city":"Boulogne-Billancourt","kind":"STATION","station_type":"station","charging_status":"nonexistent","rental_status":"operational","cars_counter_bluecar":1,"cars":1,"public_name":"Boulogne-Billancourt/Henri Martin/2","geo_point":[48.8365078,2.2524132],"charge_slots":0,"postal_code":"92100","cars_counter_utilib_1.4":0,"subscription_status":"nonexistent","slots":1,"id":"boulognebillancourt-henrimartin-2","address":"2 rue Henri Martin","cars_counter_utilib":0},"geometry":{"type":"Point","coordinates":[2.2524132,48.8365078]}}

/autolib/boulognebillancourt/reine/12 {"datasetid":"autolib-disponibilite-temps-reel","recordid":"885e5ba23a48e4c519ed9eded9422628dec6ef14","fields":{"status":"ok","city":"Boulogne-Billancourt","kind":"STATION","station_type":"station","charging_status":"nonexistent","rental_status":"operational","cars_counter_bluecar":4,"cars":4,"public_name":"Boulogne-Billancourt/Reine/12","geo_point":[48.8388074,2.2505008],"charge_slots":0,"postal_code":"92100","cars_counter_utilib_1.4":0,"subscription_status":"nonexistent","slots":1,"id":"boulognebillancourt-reine-12","address":"12 bis Route de la Reine","cars_counter_utilib":0},"geometry":{"type":"Point","coordinates":[2.2505008,48.8388074]}}

Conclusion

En conclusion, pourquoi faire simple quand on peut faire compliquer. En fait, j’utilise un broker MQTT pour un autre cas d’usage dans ma domotique, donc je rentabilise bien l’utilisation de mon broker. Pour être totalement transparent, le broker Mosquitto est largement suffisant pour ma domotique, Artemis bien que beaucoup plus complet et un peu overkill pour mon usage. Je voulais simplement remercier la limite de l’API de Paris qui m’a permis de faire un petit projet d’intégration bien sympa je trouve et toujours dans la philosophie standard ouvert, interoperabilité et projets commumnutaires OpenSource.

En esperant, vous avoir intéressé par ce post, n’hésitez pas à me faire vos retours,