Mongodb et Node-red

Mongodb est un moteur de base de données noSQL (not only SQL) orienté documents. Ce genre de base de données est structurée autour de classeurs qu’on nomme “collections”, chaque collection contenant des documents. Les documents sont indexés afin de pouvoir y accéder rapidement. Les bases de données noSQL favorisent la vitesse d’accès aux données, au détriment parfois de la compacité. Nous verrons ici comment installer mongoDB sur Raspberry Pi, puis comment l’utiliser au sein de Node-Red.

Installation de mongoDB sur raspberry pi

(voir le document complet)

MongoDB et node-red

Installation du nœud mongodb2 et insertion d’un document dans une collection par injection :

Création d’un formulaire d’insertion de données à l’aide des nœuds Dashboard.

 

Installation de mongoDB et mongo-express

Pour mongoDB c’est plutôt simple :

sudo apt-get install mongodb

On peut vérifier que cela fonctionne :
Démarrage du service mongodb

$ sudo /etc/init.d/mongodb start

Le serveur mongo db démarre normalement à l’adresse 127.0.0.1 :27017

$ mongo

Ça lance une console

> use myDB
> db.LicencePlate.insert({})

Confirmation de l’existence de la base et de la collection :

> show dbs
> show collections

Mongo-express est une interface utilisateur permettant de manipuler mongoDB de manière visuelle. Il faut que node-red et npm soit installés (voir le document d’installation de node-red avec Johnny5)

sudo npm install -g mongo-express

Par défaut le login et le mot de passe sont admin et pass cela peut être changé en modifiant le fichier de configuration. Sur raspberry le fichier de configuration se trouve dans /usr/lib/node_modules/mongo-express

Il faut recopier en le renommant config.js  puis l’éditer:

sudo cp /usr/lib/node_modules/mongo-express/config.default.js /usr/lib/node_modules/mongo-express/config.js
sudo nano /usr/lib/node_modules/mongo-express/config.default.js

Si la base myDB a été créée (voir l’installation de mongodb et les commandes shell), il faut modifier le fichier config.js :

// Accesing Bluemix variable to get MongoDB info
if (process.env.VCAP_SERVICES) {
var dbLabel = 'mongodb-2.4';
var env = JSON.parse(process.env.VCAP_SERVICES);
if (env[dbLabel]) {
mongo = env[dbLabel][0].credentials;
}
} else {
mongo = {
db: 'myDB',
host: 'localhost',
// password: 'pass',
port: 27017,
ssl: false,
url: 'mongodb://localhost:27017/db',
// username: 'admin',
};
}

Si on veut accéder à l’interface utilisateur depuis un autre ordinateur que le raspberry, dans la section « site »,  il faut renseigner l’adresse IP du raspberry à la place de localhost et modifier le login et le mot de passe:

site: {
// baseUrl: the URL that mongo express will be located at - Remember to add the forward slash at the start and end!
baseUrl: process.env.ME_CONFIG_SITE_BASEURL || '/',
cookieKeyName: 'mongo-express',
cookieSecret: process.env.ME_CONFIG_SITE_COOKIESECRET || 'cookiesecret',
host: process.env.VCAP_APP_HOST || '0.0.0.0', //connexion quelle que soit l’adresse de la carte Raspberry
port: process.env.VCAP_APP_PORT || 8081, //port du serveur web
requestSizeLimit: process.env.ME_CONFIG_REQUEST_SIZE || '50mb',
sessionSecret: process.env.ME_CONFIG_SITE_SESSIONSECRET || 'sessionsecret',
sslCert: process.env.ME_CONFIG_SITE_SSL_CRT_PATH || '',
sslEnabled: process.env.ME_CONFIG_SITE_SSL_ENABLED || false,
sslKey: process.env.ME_CONFIG_SITE_SSL_KEY_PATH || '',
},
//set useBasicAuth to true if you want to authenticate mongo-express loggins
//if admin is false, the basicAuthInfo list below will be ignored
//this will be true unless ME_CONFIG_BASICAUTH_USERNAME is set and is the empty string
useBasicAuth: process.env.ME_CONFIG_BASICAUTH_USERNAME !== '',
//useBasicAuth: false,
basicAuth: {
username: process.env.ME_CONFIG_BASICAUTH_USERNAME || 'admin',
password: process.env.ME_CONFIG_BASICAUTH_PASSWORD || 'pass',
},

Ensuite on peut lancer mongo-express :

cd /usr/lib/node_modules/mongo-express/ && node app.js

ou plus simplement

$ mongo-express

Lancer un navigateur http://<adresse_IP_Raspberry>:8081 puis s’authentifier avec le l’identifiant et le mot de passe choisit précédemment :

Page d’accueil de mongo express Collections de la base myDB(cliquer sur « View » sur la page d’accueil pour voir les collections)
Documents de la collection « LicencePlate », on voit qu’une plaque d’immatriculation est inscrite (AV865XG) Cliquer sur « New Document » pour créer une nouvelle plaque d’immatriculation : ajouter “immatriculation”:”XX123YY”, avant “_id”: ObjectID() puis cliquer sur Save.

En cliquant sur le numéro de plaque on peut modifier le document, en cliquant sur le bouton rouge représentant une poubelle, on peut effacer ce document.

openALPR sur raspberry

OpenALPR est un logiciel de reconnaissance de plaque d’immatriculation. Ce logiciel s’appuie sur la bibliothèque openCV et le logiciel de reconnaissance de caractères tesseract.

Raspbian Jessie

On trouve sur les forums tout ce qu’il faut pour télécharger, compiler et installer ce package depuis les sources. L’inconvénient est que la compilation sur raspberry est très longue. Nous proposons ici une version packagée de openALPR, ce qui réduit considérablement le temps d’installation.

sudo apt-get update
sudo apt-get install liblog4cplus-1.0-4 beanstalkd libgtk2.0-0 libtiff5 libdc1394-22 libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev
wget http://www.rgot.org/wp-content/uploads/2016/12/openalpr.tgz
tar -zxvf openalpr.tgz
sudo dpkg -i openalpr_20161219-1-complet_armhf.deb
rm openalpr_20161219-1-complet_armhf.deb
rm openalpr.tgz

Pour déinstaller :

sudo dpkg -r openalpr

Pour Raspbian Stretch c’est plus simple :

il suffit de suivre les instructions disponibles sur le github de openalpr

sudo apt-get update && sudo apt-get install -y openalpr openalpr-daemon openalpr-utils libopenalpr-dev

Réinstallation de NODE-RED, RASPI-IO et JOHNNY-FIVE sur Raspberry Pi

La version intégrée de node-red permet de s’initier mais ne permet pas d’utiliser la bibliothèque raspi-io utilisée par le raspberry pour communiquer avec l’extérieur (problème de droits d’accès aux broches du raspi).
Pour pouvoir communiquer avec l’extérieur (capteurs, afficheurs, leds…) il faut donc réinstaller node.js et node-red.

Télécharger le fichier install_johnny5 , le rendre exécutable puis le lancer:

wget http://www.rgot.org/wp-content/uploads/2016/12/install_johnny5.txt
sudo chmod 755 install_johnny5.txt
./install_johnny5.txt

autre méthode : exécuter les lignes suivantes dans une console. (démarche issue de la note d’installation de node-red : http://nodered.org/docs/hardware/raspberrypi )

sudo apt-get update
sudo apt-get remove nodered
sudo apt-get remove nodejs nodejs-legacy
curl -sL https://deb.nodesource.com/setup_4.x | sudo bash -
sudo apt-get install -y build-essential python-rpi.gpio nodejs
sudo npm cache clean
sudo npm install -g --unsafe-perm node-red
sudo apt-get update && sudo apt-get install python-rpi.gpio
sudo wget https://raw.githubusercontent.com/node-red/raspbian-deb-package/master/resources/nodered.service -O /lib/systemd/system/nodered.service
sudo wget https://raw.githubusercontent.com/node-red/raspbian-deb-package/master/resources/node-red-start -O /usr/bin/node-red-start
sudo wget https://raw.githubusercontent.com/node-red/raspbian-deb-package/master/resources/node-red-stop -O /usr/bin/node-red-stop
sudo chmod +x /usr/bin/node-red-st*
sudo systemctl daemon-reload
sudo npm i -g npm@2.x

Pour les raspi 2 et 3 il faut aussi exécuter les lignes suivantes pour installer raspi-io (gestion des entrées/sorties) et johnny5 (bibliothèque permettant la programmation d’automates)

sudo npm install -g johnny-five --unsafe-perm --force
sudo npm install -g raspi-io --unsafe-perm --force
sudo npm install -g node-red-contrib-gpio --unsafe-perm --force
sudo npm install serialport --unsafe-perm --build-from-source
sudo npm i -g oled-js oled-font-5x7

Éditer le fichier /lib/systemd/system/nodered.serviceet remplacer USER=pi par USER=root
ainsi la commande node-red-start lancera node-red en mode root (dans le dossier /root/.node-red )

Activer SSH au premier boot d’une carte Raspberry Pi

Depuis la dernière version de Raspbian Jessie (nov 2016) ssh est déactivé par défaut. Il faut donc se connecter via l’interface graphique et activer ssh dans la configuration de raspberry ( bouton framboise -> Préférences -> configuration du Raspberry Pi puis dans l’onglet “Interfaces” cocher SSH)
Si on possède une carte Raspberry qui n’est pas connectée à un ensemble clavier/souris/écran, il semble impossible de se connecter…
La solution consiste à ajouter un fichier (vide) nommé ssh dans la partition boot (c’est la partition visible lorsque la carte SD est introduite dans un PC Windows).
Au premier boot Raspberry détecte le fichier ssh, active le protocole ssh et efface le fichier ssh sur la partition boot.

connexion wifi d’une carte Raspberry Pi 3

La Carte Raspberry 3 possède nativement d’une interface réseau sans fils (WIFI) . Nous allons voir diverses méthodes pour se connecter au wifi

Utilisation de l’interface graphique :

C’est certainement la méthode la plus simple : connecter la carte raspberry à un clavier, une souris et un écran (via la prise HDMI) . Dans la  barre supérieur on voit l’icône réseau , il suffit alors de sélectionner le réseau wifi, de saisir le mot de passe… et voilà.

Pour les raspberry sans interface graphique.

Une autre méthode consiste à écrire un petit fichier de configuration qui est pris en compte au boot de la carte.
Il faut connaitre le nom du point d’accès et le mot de passe. Pour l’exemple imaginons que le point d’accès se nomme mammouth et que le mot de passe soit motDePasse
Sur un PC, il faut créer un fichier texte nommé wpa_supplicant.conf
Puis le compléter de la manière suivante :

country=FR
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
                ssid="nomDuPointDacces"
                psk="motDePasse"
               }

Une fois ce fichier créé, il faut le sauvegarder sur la carte SD du raspberry :

  • Couper l’alimentation du raspberry
  • Extraire la carte SD
  • A l’aide d’un adaptateur SD/ USB, introduire la carte SD dans le PC
  • Sauvegarder le fichier wpa_supplicant.conf précédemment créé sur la carte SD
  • Réintroduire la carte SD dans le raspberry pi et le redémarrer.

Le fichier wpa_supplicant.conf est automatiquement placé au bon endroit dans l’arborescence et la connexion wifi se fait.

Retrouver l’adresse IP d’une carte Raspberry.

Une fois connecté au wifi, pour pouvoir se connecter à la carte raspberry, il faut connaitre son adresse IP. Nous allons utiliser un logiciel qui scanne le réseau afin de retrouver son adresse IP : Advanced port Scanner (http://www.advanced-port-scanner.com/fr/ ).
Ce Logiciel « ping » les diverses adresses IP du réseau et indique les informations qu’il trouve lorsqu’il rencontre une machine.
Il faut juste connaitre la plage réseau qu’on veut balayer :
Exemple : Réseau Classe C 192.168.5 les adresses possibles vont de 1 à 254. Ce qui veut dire que nous allons balayer de 192.168.5.1 à 192.168.5.254

Une fois le scan effectué on repère la (les) carte(s) Raspberry par leur adresse MAC qui commence toujours par B8:27:EB . On peut alors connaitre l’adresse IP de la carte et s’y connecter via WinSCP et PuTTY.

MQTT – utilisation avec Arduino

Pour arduino il existe une bibliothèque qui permet de créer un client permettant de publier et de souscrire à un topic.
Le code suivant permet de souscrire auprès d’un broker public gratuit : broker.hivemq.com

/*
Basic MQTT example

This sketch demonstrates the basic capabilities of the library.
It connects to an MQTT server then:
- publishes "Arduino Connected" to the topic "eiffel/texte"
- subscribes to the topic "eiffel/texte", printing out any messages
it receives. NB - it assumes the received payloads are strings not binary
It will reconnect to the server if the connection is lost using a blocking
reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to
achieve the same result without blocking the main loop. */

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>

byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
char server[]= "broker.hivemq.com";

void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
Serial.println();
}
EthernetClient ethClient;
PubSubClient client(ethClient);

void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
// rename "arduinoClient" with an unique Id
// like "arduinoClient1524ztSDeRT"
if (client.connect("arduinoClient")) {
Serial.println("connected");
// Once connected, publish an announcement...

client.publish("eiffel/texte","Arduino connected");
// ... and resubscribe
client.subscribe("eiffel/texte");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup()
{
Serial.begin(115200);

client.setServer(server, 1883);
client.setCallback(callback);

Ethernet.begin(mac); // get IP via DHCP
// Allow the hardware to sort itself out
delay(1500);
}

void loop()
{
if (!client.connected()) {
reconnect();
}
client.loop();
}

Pour tester le programme, il faut que la carte réseau de l’Arduino soit connectée à un réseau ayant accès à internet (adresse IP et passerelle renseignée) le programme utilise un paramétrage automatique DHCP.
Hivemq met à disposition une interface de test : http://www.hivemq.com/demos/websocket-client/
Le paramétrage est simple :
Cliquer sur le bouton Connect (laisser les paramètres par défaut)

Une fois connecté, déplier le bandeau Subscriptions et cliquer sur Add New Topic Subscription

Saisir alors le Topic du programme Arduino : eiffel/texte

Provoquer un reset de la carte Arduino, lancer le moniteur Série et observer la page hiveMQ, le message “Arduino connected” apparait, ce qui signifie que Arduino a publié ce message sur le topic eiffel/texte et que cela fonctionne !

Taper un message dans la fenêtre Publish du site HiveMQ et cliquer sur Publish, On voit normalement arriver le message dans la console du moniteur Arduino.

Si la carte Arduino tente de se reconnecter en permanence, c’est que l’Identifiant de connexion est déjà utilisé par un autre appareil. il faut modifier la ligne 37

if (client.connect("arduinoClient")) {

et remplacer “arduinoClient” par un identifiant unique
if (client.connect("mon_identifiant_perso_1872AZT123p")) {

MQTT – utilisation de node-red

Pour le test nous allons utiliser une version de node-red en ligne : https://fred.sensetecnic.com/

Si ce n’est déjà fait, il faut créer un compte (gratuit) afin d’arriver sur l’interface de node-red en ligne.

Une fois le compte créé et validé (vérification par émail), on peut accéder à l’interface de création de flux node-red.

A gauche (repère 1) on trouve le tableau de bord de notre instance FRED, on peut redémarrer l’instance, rajouter des nœuds…

Le repère 2 montre la liste des nœuds disponibles dans notre instance, il y a des nœuds d’entrée (input), de sortie (output), des nœuds de fonction (function)…

Le repère 3 est l’espace de composition des flux (flow dans le jargon node-red) , on y fait glisser des nœuds, que l’on paramètre en double-cliquant dessus. On relie des nœuds entre-eux à l’aide de connexions.

Le repère 4 possède 2 onglets : info et debug. Info donne les informations d’un nœud quand on le sélectionne, c’est une aide en ligne très pratique. L’onglet debug permet d’afficher les information de débogage du flux en utilisant le nœud debug

flux  MQTT très simple:

Faire glisser un nœud inject (dans input) et un nœud mqtt (dans output), relier les deux nœuds.

Paramétrer le nœud mqtt : double cliquer dessus. Cliquer alors sur le stylo à droite de la liste déroulante « Add new mqtt broker… »

Saisir alors broker.hivemq.com dans la boite de texte , puis cliquer sur Add

De retour à la configuration de la connexion MQTT compléter le topic avec eiffel/texte

laisser la liste déroulante QoS sur 2, puis cliquer sur Done

Publier le flux en cliquant sur

Dans une autre fenêtre de navigateur, ouvrir une page sur http://www.hivemq.com/demos/websocket-client/ et se connecter. Comme précédemment, créer une souscription à eiffel/texte.
dans la fenètre node-red, cliquer sur le bouton du nœud timestamp : une valeur numérique apparait dans la fenêtre Messages du site HiveMQ.

Node-red envoie correctement une donnée au Broker HiveMQ.

Dans le sens inverse il est aussi possible d’utiliser un flux en tant que souscripteur et d’afficher les messages reçus.

Flux plus complexe

Ce flux est composé à l’aide de :

  • Inject (input)
  • Text input (ui)
  • Button (ui)
  • Function (function)
  • Mqtt (input)
  • Mqtt (output)
  • Text (ui)

le code du flux complet est le suivant :

[ { "id": "953bb49c.e4ad38", "type": "legacy_ui_text_input", "z": "5230c72.fadcf38", "tab": "84499b6b.8ac208", "mode": "text", "delay": 300, "name": "saisie", "topic": "texte", "group": "Publication", "order": 1, "x": 389, "y": 168, "wires": [ [ "ced9018e.3a8a78" ] ] }, { "id": "9fd6a3b6.540028", "type": "mqtt out", "z": "5230c72.fadcf38", "name": "", "topic": "eiffel/texte", "qos": "", "retain": "", "broker": "ac60999.b095968", "x": 792, "y": 193, "wires": [] }, { "id": "ced9018e.3a8a78", "type": "function", "z": "5230c72.fadcf38", "name": "", "func": "switch (msg.topic)\n{\n case \"texte\" :\n global.set(\"texte\",msg.payload);\n break;\n case \"btn01\" :\n msg.payload=global.get(\"texte\");\n return msg;\n}\n", "outputs": 1, "noerr": 0, "x": 592, "y": 190, "wires": [ [ "9fd6a3b6.540028" ] ] }, { "id": "7204c371.c12724", "type": "legacy_ui_button", "z": "5230c72.fadcf38", "tab": "84499b6b.8ac208", "name": "Envoi", "payload": "btn01", "topic": "btn01", "group": "Publication", "order": 1, "x": 389, "y": 224, "wires": [ [ "ced9018e.3a8a78" ] ] }, { "id": "da2dd664.a80928", "type": "mqtt in", "z": "5230c72.fadcf38", "name": "", "topic": "eiffel/texte", "qos": "2", "broker": "ac60999.b095968", "x": 385, "y": 297, "wires": [ [ "5f6550ac.8a541" ] ] }, { "id": "5f6550ac.8a541", "type": "legacy_ui_text", "z": "5230c72.fadcf38", "tab": "84499b6b.8ac208", "name": "reçu :", "group": "Souscription", "order": 1, "format": "{{msg.payload}}", "x": 786, "y": 302, "wires": [] }, { "id": "84499b6b.8ac208", "type": "legacy_ui_tab", "z": "5230c72.fadcf38", "name": "Home", "icon": "dashboard", "order": "1" }, { "id": "ac60999.b095968", "type": "mqtt-broker", "z": "5230c72.fadcf38", "broker": "broker.hivemq.com", "port": "1883", "clientid": "", "usetls": false, "compatmode": true, "keepalive": "60", "cleansession": true, "willTopic": "", "willQos": "0", "willPayload": "", "birthTopic": "", "birthQos": "0", "birthPayload": "" } ]

Copier/ coller ce texte dans la fenêtre popup qui s’ouvre si on suit Menu import ClipBoard

Le flux complet apparait à l’écran et peut être placé où l’on veut.

La fonction (nœud function) possède le code suivant :

switch (msg.topic)
    {
      case "texte":
          global.set("texte", msg.payload);
          break;
      case "btn01":
          msg.payload = global.get("texte");
          return msg;
     }

 

Msg.topic permet d’identifier le nœud qui a provoqué l’appel de la fonction, si c’est la boite de texte, on mémorise le texte dans une variable du contexte global. Si l’appel a été provoqué par le clic sur le bouton, on récupère la variable texte du contexte global et on l’affecte à msg.payload, et on retourne msg, de ce fait le texte ressort de la fonction.

Qualité de service QoS [1]:

Le niveau de qualité de service le plus simple est le service non confirmé (Unacknowledged Service). Ce niveau utilise une séquence de paquets PUBLISH : l’éditeur envoie un message une seule fois au broker et ce dernier transmet ce message une seule fois aux abonnés. Aucun mécanisme ne garantit la réception du message et le broker ne l’enregistre pas non plus. Ce niveau de qualité de service est également appelé « QoS niveau 0 » ou QoS0, ou encore « At most once » (au plus une fois).

Le deuxième niveau de service est le service confirmé (Acknowledged Service). Ce niveau utilise une séquence de paquets PUBLISH/PUBACK (Publish Acknowledge) entre l’éditeur et son broker, ainsi qu’entre le broker et les abonnés.

Un paquet de confirmation vérifie que le contenu a été reçu et un mécanisme de renvoi du contenu d’origine est déclenché si l’accusé de réception n’est pas reçu en temps voulu. Cela signifie que l’abonné peut recevoir plusieurs copies du même message. Ce niveau de qualité de service est également appelé « QoS niveau 1 » ou QoS1, ou encore « At least once » (au moins une fois).

Le troisième niveau de QoS est le service garanti (Assured Service). Ce niveau délivre le message avec deux paires de paquets. La première est appelée PUBLISH/PUBREC et la seconde, PUBREL/PUBCOMP. Les deux paires s’assurent que quel que soit le nombre de tentatives, le message ne sera délivré qu’une seule fois. Ce niveau de qualité de service est également appelé « QoS niveau 2 » ou QoS2, ou encore « Exactly once » (exactement une fois).

  1. http://www.lemagit.fr/conseil/Internet-des-Objets-bien-comprendre-MQTT

MQTT : Utiliser un service de messagerie dédié à l’internet des objets

MQTT ou MQ Telemetry Transport (MQ signifiant Message Queue) est un protocole de messagerie extrêmement simple et léger conçu pour les appareils à faible ressources (genre Arduino) et des réseaux à bande passante limitée. Ce protocole est idéal pour les applications M2M (Machine To Machine) et l’internet des objets ainsi que pour les applications mobiles où bande passante et économie d’énergie sont primordiales

MQTT permet à divers appareils de publier des informations (par exemple une sonde de température peut publier le résultat de ses mesures) vers un serveur nommé « BROKER » (courtier en français). Le broker pousse alors les données vers les clients qui sont abonnés au service. Pour différencier les différents services, les objets publient leurs résultats dans des « topics ». Le topics s’écrivent en utilisant un format permettant plusieurs niveaux, chaque niveau est séparé par un slash « / »
Par exemple :

smarthome/chambre/temperature
smarthome/chambre/light

http://www.frugalprototype.com/wp-content/uploads/2015/12/mqttschema.png

Paramétrage de base d’une carte Raspberry PI

Cet Article explore le menu de configuration de la carte Raspberry Pi afin de paramétrer le système en français et d’exploiter au mieux les ressources du nano-ordinateur.

A partir d’une image de raspbian de base, il faut configurer le raspberry . Pour ce faire, dans l’interface graphique, selectionner Menu-> Préférences -> Raspberry Pi Config. Puis pour chaque onglet effectuer les tâches suivantes :

Dans Timezone choisir Europe puis Paris,

Dans Set Keyboard choisir  France et French

Dans Set Wifi Country Choisir France

Il faut ensuite redémarrer la machine.