Créer une LoRaWAN Basic Station avec un Rpi & un iC880a

11 avr. 2021

🚧 Avertissement
Après quelque mois de test, je vous déconseille de migrer votre passerelle
comme je l'ai fait. En effet, c'est assez instable (régulièrement elle se
déconnecte, c'est balto quand même ...).
En revanche contrairement à ce que j'avais compris, "l'ancien" protocole
fonctionne toujours bien, il vous suffit juste de changer l'url du routeur
soit dans mon cas passer de router.eu.thethings.network à
eu1.cloud.thethings.network et vous voilà en V3 :)

Je laisse donc cette article pour info, mais vous déconseille de l'appliquer !


Aujourd'hui j'ai réalisé la mise à jour de la passerelle LoRaWAN du fablab LABsud (Montpellier). Deux axes d'amélioration :

  • Hardware : la station avait été assemblée aux prémices de The Things Network (TTN) à l'aide d'un super tuto et n'avait pas bougé depuis (donc fils volant etc ...). J'ai donc envoyé en fabrication des pcb de ch2i pour mettre ça au propre.
  • Software : vous avez peut-être noté que TTN était en train d'opérer la migration V3 de toute l'architecture. Ceci a plusieurs impacts : déjà à la fin de l'année plus de V2 ... Ensuite la migration étant vraiment pleine de changements, la bascule v2 -> v3 ne peut se faire automatiquement. Trop de protocoles changent, donc si vous ne faîtes rien, vos stations et objets vont décrocher ... Je vais donc basculer cette passerelle en V3 mais tant qu'à faire je vais implanté le protocole "Basic Station" qui est une évolution du dialogue passerelle <-> serveur télécom LoRa.

Remarques sur le passage en V3

Alors juste avant d'attaquer dans le dur, quelques remarques personnelles sur la V3 (très préliminaires je le précise, j'ai pas encore assez joué avec pour rendre un avis très éclairé) :

  • On y gagne en fonctionnalité ce qu'on y perd en simplicité : là où j'appréciais particulièrement The Things Network (au-delà du conept en lui-même) c'était que l'interface était très simple et allait à l'essentiel. Là en résumé on passe en version pro et on finit avec des réglages de tous les côtés ... J'ai pas ramé clairement, mais je vois mal un débutant s'en sortir alors qu'avant il avait peu de chance de se perdre. Même pour moi qui aie une utilisation plus poussée de LoRa, l'ancienne version m'allait très bien.
  • Visiblement le DevEUI n'est plus générable : la V2 vous permettez d'avoir un "vrai" DevEUI en emprunant l'OUI de TTN, mais là c'est pas disponible. Donc en théorie il vous faut un OUI pour générer vos DevEUI et répondre aux exigences du protocole. Dans les faits, il y a une chance infinitésimale qu'un conflit se produise, mais légalement c'est obligatoire, sachez le ...

Ceci étant dit, place à la migration de la passerelle 😸


Hardware

Le concentrateur est celui-ci :

iC880A-SPI LoRa® Concentrator

Pas grand chose de spécial dessus, c'est un schéma très classique à base de SX1301, la puce reine du domaine. Elle cause en bus SPI avec le Raspberry.

Le shield que j'ai utilisé :

ch2i/iC880A-Raspberry-PI
Raspberry PI iC880A and LinkLab Lora Gateway Shield - ch2i/iC880A-Raspberry-PI

Au passage si vous voulez continuer en V2 sur le reste de l'année, ils proposent des scripts et notice pour exploiter le shield (mais si vous voulez passer en V3 directement n'en faîtes rien) :

ch2i/LoraGW-Setup
SX1301 Lora Concentrator Raspberry PI based gateway setup - ch2i/LoraGW-Setup

Bref là on soude, on emboîte ... Et voilà le résultat :

iC880a + shield + Rpi (en-dessous bien caché)
Rpi + shield sans iC880a

A noter que le shield possède plein d'autres prises/sockets pour brancher plein de choses (RFM95, capteur humidité température ... c'est détaillé dans le Github, je vais pas le répéter ici). Moi je voulais surtout que ça soit plus propre 😄


Software

Les sources du programme basic station est ici :

lorabasics/basicstation
LoRa Basics™ Station - The LoRaWAN Gateway Software - lorabasics/basicstation

Alors je suis principalement appuyé sur ce tuto :

LoRaWAN: Upgrading to Basic Station and The Things Network V3 Stack

Cependant j'ai vite remarqué que ça ne marchait pas tel que décrit ... Deux problèmes :

  • L'adresse du LNS n'est pas bonne, ainsi que le certificat SSL.
  • Le script d'initialisation qui gère le reset du SX1301 ne marche pas.

Voici donc ma contre proposition 😁😁

Création de la Gateway chez TTN &  création clé API

Pour cette partie on va pas réinventé la roue, le tuto précédemment cité fait très bien le boulot ( chapitre Registering the Gateway on The Things Network). Ne faîtes juste pas la toute dernière étape avec le fichier tc.key, contentez vous de stocker cette clé quelque part.

Préparation du Rpi

Bon déjà je pars du principe que vous avez installé une raspbian-lite toute fraîche sur votre Raspberry (tuto -> "Installer Raspbian à partir d’une carte SD vierge") que vous l'avez connecté à votre réseau et que vous vous êtes connecté en SSH dessus.

On commence par une bonne mise à jour :

sudo apt update && sudo apt upgrade -y && sudo apt dist-upgrade -y

On va ensuite activer le SPI qui est le bus de communication entre le Rpi et la carte concentrateur. Pour celà :

sudo raspi-config

Puis interface options -> activer le SPI. On redémarre :

sudo reboot

Installation de basic station

On installe git, on se place dans le dossier home, on clone le repository du projet, et on le compile :

sudo apt install git
cd ~
git clone https://github.com/lorabasics/basicstation.git
cd basicstation
make platform=rpi variant=std

Configuration

Aller bientôt la fin, il ne reste plus qu'à créer la configuration. Pour celà l'exécutable aura besoin de plusieurs fichiers.

Je vous propose pour que ça soit propre de ranger ces fichiers de configuration dans un dossier à part :

mkdir ~/TTN
cd ~/TTN

On va créer un fichier tc.uri qui va contenir l'adresse du serveur où le programme va devoir se connecter (le fameux LNS) :

nano tc.uri

Puis saisissez de dedans :

wss://eu1.cloud.thethings.network:8887

On va ensuite récupérer le certificat SSL et le stocker dans un fichier nommé tc.trust :

curl https://www.thethingsnetwork.org/docs/gateways/certificates/ca.pem -o tc.trust

Il ne reste plus qu'à préparer deux fichiers : celui de configuration et le script d'initialisation.

nano station.conf

Et saisissez :

{
   "radio_conf": {                  /* Actual channel plan is controlled by the server */
       "lorawan_public": true,      /* is default */
       "clksrc": 1,                 /* radio_1 provides clock to concentrator */
       "device": "/dev/spidev0.0",  /* default SPI device is platform specific */
       "pps": false,
       "radio_0": {
           /* freq/enable provided by LNS - only hardware-specific settings are listed here */
           "type": "SX1257",
           "rssi_offset": -166.0,
           "tx_enable": true
       },
       "radio_1": {
           "type": "SX1257",
           "rssi_offset": -166.0,
           "tx_enable": false
       }

       /* chan_multiSF_X, chan_Lora_std, chan_FSK provided by LNS */
   },
   "station_conf": {
     "radio_init": "/home/pi/TTN/rinit.sh",
     "log_file":    "/home/pi/basicstation.log",
     "log_file":    "stderr",
     "log_level":   "ERROR",
     "log_size":    10e6,
     "log_rotate":  3
   }
}

Bien évidemment vous pouvez modifier certains paramètres si vous avez compris à quoi ils servent.

Enfin le script d'initialisation :

SX1302_RESET_PIN=17
LED_PIN=18

WAIT_GPIO() {
    sleep 0.01
}


if [ -d /sys/class/gpio/gpio$SX1302_RESET_PIN ]
then
        echo "$SX1302_RESET_PIN" > /sys/class/gpio/unexport; WAIT_GPIO
fi

if [ -d /sys/class/gpio/gpio$LED_PIN ]
then
        echo "$SX1302_RESET_PIN" > /sys/class/gpio/unexport; WAIT_GPIO
fi

echo "$SX1302_RESET_PIN" > /sys/class/gpio/export; WAIT_GPIO
echo "out" > /sys/class/gpio/gpio$SX1302_RESET_PIN/direction; WAIT_GPIO
echo "1" > /sys/class/gpio/gpio$SX1302_RESET_PIN/value; WAIT_GPIO
echo "0" > /sys/class/gpio/gpio$SX1302_RESET_PIN/value; WAIT_GPIO


echo "$LED_PIN" > /sys/class/gpio/export; WAIT_GPIO
echo "out" > /sys/class/gpio/gpio$LED_PIN/direction; WAIT_GPIO
echo "1" > /sys/class/gpio/gpio$LED_PIN/value; WAIT_GPIO

exit 0

Ce script a pour but de faire un reset du shield : c'est indispensable, c'est une partie qui m'a pas mal perturbé ... En bonus une led du shield est allumée (attention elle ne s'éteindra pas si le shield est arrêté, j'ai pas approfondi ce point encore ...).

Ouf en théorie vous êtes au bout du tunnel !! 🎆🎇🎉🎉

Lancement

Il ne vous reste plus qu'à le lancer en utilisant votre fichier de configuration :

sudo -u pi /home/pi/basicstation/build-rpi-std/bin/station -h /home/pi/TTN -d

Le -d permet de lancer le processus en mode démon et -h défini le dossier où il doit récupérer la configuration.

En cas de problème, quelques outils :

  • Le niveau de log dans le fichier de configuration peut être réglé sur "DEBUG" pour avoir plus d'info.
  • Vous pouvez lancer le processus dans passer par un démon (vous avez donc la sortie console en direct, plus pratique parfois) :
  • Dans le SDK fourni par Semtech (qui fabrique la puce au centre de la passerelle s'il fallait le rappeler) il y a des scripts de test, ils m'ont été utile pour vérifier le dialogue entre le Rpi et le shield. Les commandes en vrac :
 git clone https://github.com/Lora-net/lora_gateway.git
 cd lora_gateway/
 make
 cd libloragw/tst/
 cd ../
 ./test_loragw_spi
 ./test_loragw_reg

Résultat

Ca fonctionne ! 😎😎


Bonus : script de monitoring & LED

Petit bonus sans en être un 😅

Comme sur ce beau shield on a 4 LEDS, je voulais m'en servir pour visuellement avoir une idée du statut de la gateway (en fonction, connecté etc ...). J'ai donc écrit un petit script qui va vérifier si le process est bien lancé. Le voici :

#!/bin/bash

processName="/home/pi/basicstation/"
scriptName="monitor.sh"


#23=Orange 18=Green 4=White 24=Yellow

ledOK=18
ledKO=23
ledMonitorRunning=4

WAIT_GPIO() {
    sleep 0.1
}


testProc() {

grepText="${1}"
nProc=`ps -ef|grep ${grepText}|grep -v grep|grep -v ${scriptName}|wc -l`
#echo ${nProc}
return ${nProc}

}

if [ -d /sys/class/gpio/gpio${ledOK} ]
then
        echo "${ledOK}" > /sys/class/gpio/unexport; WAIT_GPIO
fi

if [ -d /sys/class/gpio/gpio${ledKO}" ]
then
        echo "${ledKO}" > /sys/class/gpio/unexport; WAIT_GPIO
fi


if [ -d /sys/class/gpio/gpio${ledMonitorRunning}" ]
then
        echo "${ledMonitorRunning}" > /sys/class/gpio/unexport; WAIT_GPIO
fi

echo "${ledMonitorRunning}" > /sys/class/gpio/export; WAIT_GPIO
echo "out" > /sys/class/gpio/gpio${ledMonitorRunning}/direction; WAIT_GPIO
echo "1" > /sys/class/gpio/gpio${ledMonitorRunning}/value; WAIT_GPIO


echo "${ledOK}" > /sys/class/gpio/export; WAIT_GPIO
echo "out" > /sys/class/gpio/gpio${ledOK}/direction; WAIT_GPIO
echo "0" > /sys/class/gpio/gpio${ledOK}/value; WAIT_GPIO


echo "${ledKO}" > /sys/class/gpio/export; WAIT_GPIO
echo "out" > /sys/class/gpio/gpio${ledKO}/direction; WAIT_GPIO
echo "0" > /sys/class/gpio/gpio${ledKO}/value; WAIT_GPIO


while [ true ]
do
testProc ${processName}

result=$?

if [[ $result -gt 0 ]]
then
echo "0" > /sys/class/gpio/gpio${ledKO}/value; WAIT_GPIO
echo "1" > /sys/class/gpio/gpio${ledOK}/value; WAIT_GPIO
#echo "Proc is OK"
else
echo "0" > /sys/class/gpio/gpio${ledOK}/value; WAIT_GPIO
echo "1" > /sys/class/gpio/gpio${ledKO}/value; WAIT_GPIO
#echo "Proc is KO"
fi

sleep 10
done

🛑‼⚠ Problème : ça ne suffit pas ... Je le redirai en conclusion mais quand il y a un problème (genre déconnexion internet) le système ne repart pas. Il faudrait donc un script plus évolué qui :

  • Vérifie la connexion internet.
  • Tape l'API de TTN pour "s'auto-tester" en vérifiant le statut de la gateway sur le serveur TTN (connectée ou déconnectée en gros).
  • Redémarrer le démon en cas de pépin.
  • Ajuster l'état des LED en fonction de ces différents état.
  • Remplir un fichier de log pour avoir un meilleur suivi des dysfonctionnements.

Bref il reste un peu de boulot pour avoir un truc vraiment fiable.


Conclusion

Pour être honnête j'ai un peu galéré car le projet étant relativement récent, la documentation ne pullule pas ... Mais c'est bon la passerelle joue son rôle ! Enfin ... Je suis pas encore 100% convaincu de la fiabilité de l'ensemble, mais c'est un bon proof of concept.

Il me reste à retravailler la partie gestion du processus et monitoring pour que ça soit parfait.

👉 Affaire à suivre !

Sur ce à la prochaine !