(WS17-02) Lora-WAN

Aus Verteilte Systeme - Wiki
Wechseln zu: Navigation, Suche

Projektbeschreibung

Einleitung

Dieses Projekt befasst sich mit der Funktechnologie LoRa/LoRa-WAN und dient dem Ausloten der Anwendungsmöglichkeiten. Dazu mussten zunächst ein funktionierender Sender und ein Empfänger eingerichtet werden. Im Rahmen dessen wurde eine prototypische Anwendung entworfen und ein LoRa-Gateway für den Raum Wiesbaden in Betrieb genommen.

LoRa / LoRaWAN

LoRaWAN bedeutet Long Range Wide Area Network und ist ein Low-Power-Wireless-Netzwerkprotokoll, welches für das Internet der Dinge (IoT) entwickelt wurde. Die Spezifikation dessen unterliegt der LoRa-Alliance und nutzt die LoRa-Technologie der Semtech Corporation. Das Ziel ist es bei möglichst geringem Energieaufwand Daten über große Strecken (>10km) zu verschicken. Die Datenübertragungsrate beim Uplink beträgt zwischen 292 Bit/s und 50 Kilobit/s. Ein Downlink ist möglich, jedoch ist dieser mit erheblichen Energieaufwand beim Endgerät verbunden.

Das Netzwerk ist Sternförmig aufgebaut. Das heißt, viele Endgeräte (Nodes) kommunizieren mit einem oder mehreren Gateways, welche die Daten über das Internet an einen Netzwerkserver weiterleiten. Dieser stellt Schnittstellen bereit, damit die Daten von unterschiedlichen Anwendungen und Plattformen genutzt werden können.

LoRaWAN arbeitet auf dem regional frei-zugänglichen ISM-Band. In Europa umfasst dies die Frequenzen 433 MHz und 868 MHz.

Je nach Dichte der Bebauung werden Reichweiten zwischen 2 km und 40 km erreicht. Ein Vorteil ist, dass die Funksignale relativ gut Gebäude durchdringen können. Der Stromverbrauch von Endgeräten beträgt rund 10 mA und 100 nA im Ruhemodus. Das ermöglicht je nach Anwendungsfall eine Batterielebensdauer von 2 bis 15 Jahren. Die Kommunikation zwischen den Endgeräten und den Gateways erfolgt auf verschiedenen Frequenzkanälen mit unterschiedlichen Datenraten. Diese liegen zwischen 0,3 kbit/s und 50 kbit/s.

Um eine hohe Effizienz bei Datentransfer und Energieverbrauch zu erreichen, nutzt LoRaWAN Frequenzspreizung. Interferenzen können so weitestgehend vermieden werden. Die Datentransferraten zu den Endgeräten passt der Netzwerkserver der jeweiligen Situation an (ADR = Adaptive Data Rate). Die Kommunikation im LoRaWAN ist zweifach mit 128 bit AES verschlüsselt, zum einen bis zum Netzwerkserver und zum anderen bis zum Anwendungsserver.

Die Verbreitung dieser jungen Technologie steckt noch in den Kinderschuhen. Vorreiter beim Ausbau des LoRa-Netzes sind die Niederlande, Schweiz und Südkorea. Ungefähr die Hälfte aller in Europa installierten Gateways befinden sich in den Niederlanden oder der Schweiz (Stand 2017).

The Things Network

Das The Things Network (TTN) ist eine community basierte Initiative zur Errichtung eines globalen LPWAN IoT-Netzwerks. Die Initiative wurde 2015 durch den Niederländer Wienke Giezeman gestartet und deckt derzeit mit über 3.000 installierten LoRaWAN-Gateways in über 90 Ländern bereits große Gebiete ab. Freiwillige übernehmen die Bereitstellung, die Errichtung und die Betreuung der Gateways.

In Amsterdam ist es auf diese Weise gelungen, große Teile des Stadtgebietes in wenigen Wochen abzudecken. Die Niederlande sind bereits zum größten Teil mit TTN versorgt. Gleiches gilt für Zürich, Bern und Berlin. In Berlin dauerte es lediglich neun Monate, um rund 3.500.000 Menschen mit LoRaWAN-Zugang zu versorgen.

Mittlerweile engagieren sich global mehr als 32.000 Freiwillige bei der Errichtung des weltweit größten, vernetzten „Internet der Dinge“ (IoT) in welchem täglich bereits über 3 Millionen Datensätze verarbeitet werden.

Es ist geplant, den Zugang auch über die LEO-Satellitentechnologie bereit zu stellen.

Projektziele

Zuerst galt es, ein einfaches funktionierendes Netzwerk aufzubauen. Im Anschluss sollte galt es ein Anwendungsgebiet herauszufinden. Aus dem letzten Schritt folgte der Aufbau eines Uplinks zum TTN-Server und das Entwickeln einer prototypischen Anwendung, welche die gesendeten Daten verarbeitet.

1. Aufbau eines simplen LoRa-WAN-Netzwerkes (Node und Gateway)

2. Herausfinden der Möglichkeiten

2.1. TTN-Gateway

2.2. Prototypische Anwendung

Realisierung

Durch die Realisierung soll eine vollständige prototypische Anwendung erstellt werden. Die Struktur des Projekts ist in folgender Abbildung ersichtlich:

WorkflowFinal.png

Im Projekt werden Wetterdaten durch einen Sensor mittels I2C ausgelesen und anschließend über das am Node angebrachte LoRa-Modul übertragen. Die Daten werden dabei über einen PackageForwarder zum TheThingsNetwork (TTN) übertragen. Das TTN dient hierbei als Broker, dessen Daten per MQTT von einer Anwendung abgefragt werden. Dazu wird im Projekt Node-Red verwendet, was anschließend die empfangenen Daten in einer InfluxDB speichert. Eine Visualisierung der Daten erfolgt durch Grafana, dass Graphen anhand der Daten aus der Datenbank erstellt.

Node

Die Aufgabe eines Nodes ist es Daten mittels LoRa an alle Gateways in der Umgebung zu senden. In unserem Projekt werden hierbei Wetterdaten ausgelesen und durch einen Arduino mit dem LoRa WiMod Shield übertragen.

Arduino Due

(Quelle)]

Als Knoten verwenden wir das Board "Arduino Due". Nähere Informationen dazu auf der Herstellerseite.


Dragino LoRa GPS HAT for Raspberry Pi

Bazaar503741 4.jpg

Die ersten Versuche führten wir mit dem LoRa GPS HAT for Raspberry Pi durch. Die Projekte, die wir zu dieser Hardware fanden, waren veraltet und/oder wurden nicht mehr weiterverfolgt. Ein Projekt erlaubte uns jedoch "Hello World"-Nachrichten zu verschicken, sodass wir zumindest ermitteln konnten, ob unser Gateway Daten empfing und diese korrekt an TTN weiterleitete. Die Dokumentation war aber derart schlecht, dass man den Source-Code analysieren und bearbeiten musste, um das Modul korrekt zu konfigurieren. Die umständliche Handhabe, die Instabilität der Testprogramme und der hohe Stromverbrauch ließen uns vom Raspberry Pi ablassen und wir wechselten auf den Arduino.

WiMod Shield

Als LoRa-Modul wird das "WiMod Shield for Arduino" verwendet.

WiMod Shield.png

(Quelle)

Das WiMod Shield unterstützt das Senden und Empfangen von LoRaWAN- und LoRa-Nachrichten, mit jeweils passender Firmware.

Herstellerwebseite

Datasheet

Für Bibliothek Benutzerkonto Erstellen und unter General Information / Downloads runterladen.

https://wireless-solutions.de/images/stories/downloads/Evaluation%20Tools/WiMOD_Shield_for_Arduino/WiMOD-ArduinoLib-V1_3_1.zip

Sensor

Im Projekt werden als Beispiel Wetterdaten übertragen. Als Sensor zum Auslesen wird der Bosch BME680 von Watterott verwendet:

BME680.jpg

(Quelle)

Weitere technische Informationen befinden sich auf der Herstellerwebseite.

Der Sensor misst die Temperatur, Luftfeuchtigkeit, Luftdruck und Luftgüte. Die Datenübertragung erfolgt mittels SPI oder I2C.

Die Library's für den Chip sind hier erhältlich: https://github.com/BoschSensortec/BME680_driver Beim Github Repository sind auch Codebeispiele für SPI und I2C vorhanden.

Source Code

Für das Projekt ist folgende Library in den Arduino Ordner zu platzieren: https://github.com/BoschSensortec/BME680_driver

Auf der Github-Seite ist auch eine Anleitung vorhanden.

Den Source Code für die .ino-Datei ist hier erhältlich:

Datei:Node Source.c

Änderungen am Original Code

Includes

#include <bme680_defs.h>
#include <bme680.h>
#include <Wire.h>

APPEUI und APPKEY eintragen

/*
   OTAA Parameters
*/

#define ARDUINO_NUM 1

// application  key (64bit)
const char APPEUI[] = { 0x70, /* 8 Werte ..... */ };

// application  key (128bit)
const char APPKEY[] = {

#if ARDUINO_NUM == 1

  0x66, // 16 Werte.....

#elif ARDUINO_NUM == 2

  0xCD, // 16 Werte.....

#else

#error Definend unsupported ARDUINO_NUM

#endif

};

Struct anlegen:

struct bme680_dev gas_sensor;

Code für die Sensordaten des BME680:

 /*
    BME680 SETUP
 */

 Wire.begin();

 printStartMsg();

 gas_sensor.dev_id = BME680_I2C_ADDR_PRIMARY;
 gas_sensor.intf = BME680_I2C_INTF;
 gas_sensor.read = user_i2c_read;
 gas_sensor.write = user_i2c_write;
 gas_sensor.delay_ms = user_delay_ms;

 int8_t rslt = BME680_OK;
 rslt = bme680_init(&gas_sensor);
 debugMsg("bme680_init");
 debugMsg((int) rslt);
 debugMsg("\n");

 uint8_t set_required_settings;

 /* Set the temperature, pressure and humidity settings */
 gas_sensor.tph_sett.os_hum = BME680_OS_2X;
 gas_sensor.tph_sett.os_pres = BME680_OS_4X;
 gas_sensor.tph_sett.os_temp = BME680_OS_8X;
 gas_sensor.tph_sett.filter = BME680_FILTER_SIZE_3;

 /* Set the remaining gas sensor settings and link the heating profile */
 gas_sensor.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS;
 /* Create a ramp heat waveform in 3 steps */
 gas_sensor.gas_sett.heatr_temp = 320; /* degree Celsius */
 gas_sensor.gas_sett.heatr_dur = 150; /* milliseconds */

 /* Select the power mode */
 /* Must be set before writing the sensor configuration */
 gas_sensor.power_mode = BME680_FORCED_MODE;

 /* Set the required sensor settings needed */
 set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL
                         | BME680_GAS_SENSOR_SEL;

 /* Set the desired sensor configuration */
 rslt = bme680_set_sensor_settings(set_required_settings, &gas_sensor);

 /* Set the power mode */
 rslt = bme680_set_sensor_mode(&gas_sensor);

 /* Get the total measurement duration so as to sleep or wait till the
    measurement is complete */
 uint16_t meas_period;
 bme680_get_profile_dur(&meas_period, &gas_sensor);
 user_delay_ms(meas_period); /* Delay till the measurement is ready */

 /*
    BME680 SETUP END
 */

Code um den Spreading Factor anzupassen:

   TWiMODLORAWAN_RadioStackConfig radioCfg;
   radioCfg.DataRateIndex = LoRaWAN_DataRate_LoRa_SF12_125kHz;
   wimod.SetRadioStackConfig(&radioCfg);

Der Spreading Factor legt die Dauer fest, wie lange die Daten einer Nachricht gesendet werden. Der Werte liegen bei LoRa zwischen 7 und 12. Mit jeder Erhöhung des Spreading Factors verdoppelt sich diese Länge, sodass auch die Gesamtübertragungszeit einer Nachricht sich entsprechend verdoppelt. Im Projekt nutzen wir den maximalen Wert von 12 um möglichst hohe Reichweiten erzielen zu können.


Loop-Funktion von Arduino, inklusive Sensordaten und senden einer LoRa Nachricht mit den Wetterdaten des Sensors:

void loop()
{
 struct bme680_field_data data;

 // check of OTAA procedure has finished
 if (RIB.ModemState == ModemState_Connected) {

   // send out a hello world every 30 sec ( =6* 50*100 ms)
   // (due to duty cycle restrictions 30 sec is recommended
   if ((loopCnt % (6 * 50)) == 0) {
     loopCnt = 0;


     int8_t rslt = bme680_set_sensor_mode(&gas_sensor);

     /* Get the total measurement duration so as to sleep or wait till the
        measurement is complete */
     uint16_t meas_period;
     bme680_get_profile_dur(&meas_period, &gas_sensor);
     user_delay_ms(meas_period); /* Delay till the measurement is ready */

     rslt = bme680_get_sensor_data(&data, &gas_sensor);

     debugMsg("T: ");
     debugMsg(data.temperature / 100.0f);
     debugMsg("degC, P: ");
     debugMsg(data.pressure);
     debugMsg("hPa, H: ");
     debugMsg(data.humidity);
     debugMsg("%%rH ");
     debugMsg("\n");
     /* Avoid using measurements from an unstable heating setup */
     if (data.status & BME680_GASM_VALID_MSK)
       debugMsg(", G: ");
     debugMsg(data.gas_resistance);
     debugMsg(" ohms");

     debugMsg("\r\n");


     // send out a simple HelloWorld messsage
     debugMsg(F("Sending message...\n"));

     uint8_t* point8;

     // prepare TX data structure
     txData.Port = 0x02;
     txData.Length = 14;


     point8 = (uint8_t*) &data.temperature;
     txData.Payload[0] = point8[1];
     txData.Payload[1] = point8[0];

     point8 = (uint8_t*) &data.pressure;
     txData.Payload[2] = point8[3];
     txData.Payload[3] = point8[2];
     txData.Payload[4] = point8[1];
     txData.Payload[5] = point8[0];

     point8 = (uint8_t*) &data.humidity;
     txData.Payload[6] = point8[3];
     txData.Payload[7] = point8[2];
     txData.Payload[8] = point8[1];
     txData.Payload[9] = point8[0];

     point8 = (uint8_t*) &data.gas_resistance;
     txData.Payload[10] = point8[3];
     txData.Payload[11] = point8[2];
     txData.Payload[12] = point8[1];
     txData.Payload[13] = point8[0];

     int i;
     for (i = 0; i < 14; i++)
     {
       debugMsgHex((uint8_t)txData.Payload[i]);
       debugMsg(" ");
     }
     debugMsg(" : txData\n");

     // try to send a message
     if (false == wimod.SendUData(&txData)) {
       // an error occurred

       // check if we have got a duty cycle problem
       if (LORAWAN_STATUS_CHANNEL_BLOCKED == wimod.GetLastResponseStatus()) {
         // yes; it is a duty cycle violation
         // -> try again later
         debugMsg(F("TX failed: Blocked due to DutyCycle...\n"));
       }
     }
   }
 }

 // check for any pending data of the WiMOD
 wimod.Process();

 delay(100);
 loopCnt++;
}

Registrieren bei TTN

Das Node muss im TTN angelegt werden. Eine Anleitung dazu befindet sich im Kapitel TTN Broker.

PackageForwarder

Raspberry Pi 3

(Quelle)
iC880A

(Quelle)

Das Lora-Gateway besteht Hardware-seitig aus einem Raspberry Pi 3, welcher mit einem iC880A-Funkchip über die serielle Schnittstelle SPI verbunden ist. Wie die Komponenten zu verbinden sind, findet sich hier.
Im Grund ist das Gateway ein reiner Package Forwarder, d.h. er leitet die empfangenen Packete direkt weiter, ohne sie zu bearbeiten.

Quick Start Guide

Ein gezipptes TAR-Archiv mit den zwei zusammenpassenden Repositorys ist hier zur Verfügung gestellt: Datei:Gateway.tar.gz
Neben den Ordnern für die Gateway-Software enthält das Archiv auch einige Skripte, welche beim Betrieb des Gateways nützlich sind (z.B. den Watchdog).

  1. TAR-Archiv runter laden und entpacken
    tar -xzf Gateway.tar.gz
  2. Installation durchführen und über JSON-Datei konfigurieren
    Siehe hier
  3. TTN-Registrierung
    Siehe hier
  4. Startskript einrichten
    Siehe hier

Proxy einrichten

Apt

$ vi /etc/apt/apt.conf
Acquire::http::proxy "http://myproxy.de:80";
Acquire::ftp::proxy "ftp://myproxy.de:80";
Acquire::https::proxy "https://myproxy.de:80";

Git eintragen

$ git config --global http.proxy http://myproxy.de:80

Git löschen

$ git config --global --unset http.proxy

Sonstiges

$ sudo vi /etc/profile.d/proxy.sh
export http_proxy=http://myproxy.de:80
export https_proxy=https://myproxy.de:80
export ftp_proxy=ftp://myproxy.de:80

export HTTP_PROXY=$http_proxy
export HTTPS_PROXY=$https_proxy
export FTP_PROXY=$ftp_proxy

Installation und Konfiguration

Überordner anlegen für Gateway:

mkdir Gateway

Der Semtech Package Forwarder kann hier runtergeladen werden. Zusätzlich wird das Lora-Gateway hier runtergeladen.
Alternativ können die Repositories per GIT gezogen werden:

cd Gateway
git clone https://github.com/Lora-net/lora_gateway.git
git clone https://github.com/Lora-net/packet_forwarder.git

Installieren:

cd lora_gateway
make
cd ../packet_forwarder
make

Das 'make' im Gateway-Ordner muss zuerst ausgeführt werden, da das 'make' des Packetforwarder auf zuvor generierte Dateien zurückgreift.
Zum Einstellen des Gateways wird eine JSON-Datei verwendet:

cd packet_forwarder/lora_pkt_fwd/
vi local_conf.json

Vorher sieht local_conf.json so aus:

{
/* Put there parameters that are different for each gateway (eg. pointing one gateway to a test server while the others stay in production) */
/* Settings defined in global_conf will be overwritten by those in local_conf */    "gateway_conf": {
          "gateway_ID": "AA555A0000000101" /* you must pick a unique 64b number for each gateway (represented by an hex string) */
        }
}

Folgende Felder sollten eingetragen werden:

{
/* Put there parameters that are different for each gateway (eg. pointing one gateway to a test server while the others stay in production) */
/* Settings defined in global_conf will be overwritten by those in local_conf */    "gateway_conf": {
          "gateway_ID": "AA555A0000000101", /* you must pick a unique 64b number for each gateway (represented by an hex string) */
          "server_address": "52.169.76.203",//"router.eu.thethings.network",
          "serv_port_up": 1700,
          "serv_port_down": 1700,
          "servers": [{
          "server_address": "52.169.76.203",//"router.eu.thethings.network",
          "serv_port_up": 1700,
          "serv_port_down": 1700,
          "serv_enabled": true
          }]
        }
}

Als 'gateway_ID' kann sich eine einmalige ID überlegt werden. 'server_address' sollte auf den nächstgelegenen TTN-Server (hier: router.eu.thethings.network) gesetzt werden.
Die möglichen Router von TTN können hier nachgelesen werden.
GPIO
Zum Ansteuern des Boards muss verwendete GPIO-Pin (hier: GPIO17) einmalig auf high und wieder auf low gesetzt werden. Das kann man entweder von Hand machen oder man verwendet ein Shell-Skript:

#!/bin/bash

# Only run with root-privileges
if ! [ $(id -u) = 0 ]; then
  echo "The script need to be run as root." >&2
  exit 1
fi

if [ ! -e /sys/class/gpio/gpio17 ]
then
  # Only export if not allready exported
  echo "17"  > /sys/class/gpio/export
fi

echo "Exporting GPIO17.."
echo "out" > /sys/class/gpio/gpio17/direction
echo "1"   > /sys/class/gpio/gpio17/value
sleep 5 
echo "0"   > /sys/class/gpio/gpio17/value
sleep 1 
echo -n "This value should be 0: "
cat /sys/class/gpio/gpio17/value

Es genügt diesen Vorgang einmal nach dem Start des Pi's durchzuführen. Mehr zum Thema Startskript findet sich hier.

Registrieren bei TTN

Wie das Gateway bei TTN eingetragen wird ist im TTN-Kapitel anschaulich dargestellt.

Watchdog

Ein Watchdog (englisch für Wachhund) soll das Lora-Gateway starten und während seiner Laufzeit überwachen.
Diese Kontrollinstanz ist aus zweierlei Gründen notwendig geworden. Auf der einen Seite muss das Programm mehrfach gestartet werden, da der Funkchip nicht immer beim ersten Versuch erreichbar ist. Meist ist nach 2-3 Versuchen das Gateway am Laufen. Um festzustellen, ob das Gateway läuft, wird mit pgrep die Prozess-ID des Package Forwarder herausgesucht. Der Prozess hat den Namen lora_pkt_fwd.
Auf der anderen Seite hängt sich das Gateway teilweise nach einer Zeit auf und sendet keine Daten mehr an TTN, obwohl der Gateway-Prozess noch am Laufen ist. Da es uns nicht möglich war diesen Fehler exakt zu reproduzieren, prüft der Wachtdog regelmäßig, ob das Gateway innerhalb der letzten 5 Minuten erfolgreich TTN erreicht hat.
TTN bietet hierzu - in Form eines JSON-Objekt - an, die aktuellen Daten über ein spezifisches Gateway abzufragen. Dazu wird folgender Adresse die EUI des Gateways angefügt, von welchem die Daten gewünscht werden:

http://noc.thethingsnetwork.org:8085/api/v2/gateways/eui-

Dieses JSON-Objekt enthält einen Timestamp wann das Gateway sich zuletzt beim TTN gemeldet hat. Normalerweise sollte dieser Zeitpunkt um die 30 Sekunden in der Vergangenheit liegen. Liegt er oberhalb einer Minute kann vermutet werden, dass die Verbindung unterbrochen ist. Der hier ermittelte Wert stimmt nicht immer mit dem Wert aus der Console der TTN-Seite überein. Als TTN Probleme mit ihrer Website hatten, konnte über das JSON-Objekt weiterhin ermittelt werden, wann das Gateway zuletzt aktiv war.
Dieser Watchdog ist in Perl geschrieben, zur Nutzung auf einem handelsüblichen Pi, muss das Packet JSON verfügbar sein:

#!/usr/bin/perl

use warnings;
use strict;

use JSON;
use Time::Local;
use Sys::Syslog;
use Sys::Syslog qw(:standard :macros);

my ($EUI,$LOOKUP,$START_TIME,$CHECK_TIME,$URL,$CHECK_ACTIVE,$START_GATEWAY,$STOP_GATEWAY,$jsonResponse,$jsonConverter,$scalarResponse,%result,$running); 


# Cycletime for start and check-cycle
$START_TIME = 10; # seconds
$CHECK_TIME = 60; # seconds
$EUI = "aa555a0000000101";


$URL = "http://noc.thethingsnetwork.org:8085/api/v2/gateways/eui-$EUI";
$LOOKUP = "wget --quiet --output-document=- $URL";
$CHECK_ACTIVE = "pgrep lora_pkt_fwd";
$START_GATEWAY = "cd packet_forwarder/lora_pkt_fwd/ && ./lora_pkt_fwd &";
$STOP_GATEWAY = "pgrep 'lora_pkt_fwd' | xargs kill";
$jsonConverter = JSON->new->allow_nonref;
openlog("","cons,perror,pid",LOG_USER);


# Mainloop
while(1) {
  $running = qx{$CHECK_ACTIVE};

  if ($running eq "") {
    syslog("info","Starting gateway");
    system($START_GATEWAY);
    sleep($START_TIME);
  }

  # Gateway running
  else {
    # Check if gateway still connected to TTN
    if ($jsonResponse = qx{$LOOKUP}) {
      if ($scalarResponse = $jsonConverter->decode($jsonResponse)) {
        %result = %{$scalarResponse};

        # Timestamp-example: 2018-02-28T08:19:24.370222221Z
        if ($result{"timestamp"} =~ /(\d{4})-(\d{2})-(\d{2}).*(\d{2}):(\d{2}):(\d{2})/) {
          # month-1 (localtime-conversion), hour (timestamp from other timezone)
          my $timeDiff = time - timelocal($6,$5,$4,$3,($2-1),$1);
          if($timeDiff >= (300)) {
            # restart gateway if not seen in last 5min
            syslog("warning","Gateway offline since $timeDiff seconds. Stopping gateway");
            system($STOP_GATEWAY);
            next;
          } else {
            syslog("info","Gateway running and connected to TTN. Last seen $timeDiff seconds ago");
          }
        } else {
          syslog("warning","Can't parse timestamp");
        }
      } else {
        syslog("err","Can't decode received JSON");
      }
    } else {
      syslog("err","Can't reach $URL");
    }
    sleep($CHECK_TIME);
  }
}

closelog();

Zuerst wird versucht das Gateway zu starten, wenn nötig auch mehrfach. Hiernach wird regelmäßig geprüft, ob der Timestamp aus dem JSON-Objekt höchstens 5 Minuten alt ist.
Sollte er älter sein, so wird das Gateway angehalten und neu gestartet. Das Logging des Watchdogs läuft über das Syslog, zu finden unter /var/log/syslog. Konfiguriert wird der Watchdog über die drei Konstanten am Anfang des Quellcodes: $START_TIME, $CHECK_TIME und $EUI.

Startskript

Wenn das Gateway aktiv betrieben werden soll, so müssen der GPIO-Export und der Watchdog nach dem Hochfahren des Pi's automatisiert gestartet werden. Dazu genügen ein paar Zeilen in der rc.local. Wichtig hierbei ist, dass die Skripte mit einem & im Hintergrund gestartet werden. Sonst wird das abschließende exit 0 nicht erreicht, da der Watchdog (im Normalfall) nie returned!

sudo vi /etc/rc.local

Am Ende werden vor exit 0 folgende Zeilen eingefügt:

# Start Lora-Gateway
(
  cd /home/pi/Gateway
  ./exportGpio17.sh &
  ./watchdogLoraGateway.pl &
)

Beim Verwenden dieser Zeilen sollten absolute Pfade zu den Skripten verwendet werden.
Damit ist es geschafft. Das Gateway ist nun vollständig einsatzbereit.

TTN Broker

Das TTN empfängt die Daten über den Packet Forwarder (Gateway). Diese Daten werden durch die Decoder Funktion (siehe unten) entschlüsselt und anschließend mittels MQTT übertragen and die Application, die die Daten auswertet.

Einrichtung TTN-Application

Die Application muss im TTN angelegt werden:

TTN Application.jpg

Die Application im TTN beinhaltet lediglich die einzelnen Devices (also unsere Nodes). Diese Application ist nicht zur verwechseln mit der Application, die die Daten durch die Integration (MQTT) zur Verfügung gestellt bekommt und damit eine grafische Übersicht über die Wetterdaten erzeugt.

Jedes Node muss dabei einzeln hinzugefügt werden:

TTN Node.jpg

Einrichtung Gateway

Nach dem Erstellen eines Accounts auf https://www.thethingsnetwork.org, kann auf die Console zugegriffen werden:
TTN1.JPG
Hier sind alle Applications und Gateways zu sehen, welche zum Account gehören. Unter Gateways findet sich eine Übersicht über die angelegten Gateways:
TTN2.JPG
Unter Register Gateway wird ein neues Gateway angelegt:
TTN3.JPG
Ist das Gateway angelegt, werden alle Parameter angezeigt:
TTN4.JPG
Wenn das Gateway in Produktion ist, sollten die Parameter wie folgt aussehen:
TTN5.JPG

Decoder

Der Decoder im TTN entschlüsselt die empfangene LoRa-Message. Dabei unterscheidet die Funktion zwischen Port1 und Port2: Port1 wird zur normalen Nutzung verwendet (also mit Wetterdaten) und Port2 um eine Testnachricht "Hello World" zu versenden. Die empfangenen Bytes werden in ihre ursprünglichen Typen konvertiert und in ihre entsprechende Einheit (z.B. °C umgerechnet).

function Decoder(bytes, port) {
 // Decode an uplink message from a buffer
 // (array) of bytes to an object of fields.
 if(port == 0x02){
   var decoded = {temperature : 0, pressure : 0, humidity : 0, gas_resistance : 0};
 
 decoded.temperature       = intFromBytes(bytes.slice(0,2)) / 100;
 decoded.pressure          = intFromBytes(bytes.slice(2,6)) / 100;
 decoded.humidity          = intFromBytes(bytes.slice(6,10)) / 1000;
 decoded.gas_resistance    = intFromBytes(bytes.slice(10,14));
 }else{
   var decoded = {msg :"Hello World"};
 }
 
 return decoded;
}

function intFromBytes( x ){
   var val = 0;
   for (var i = 0; i < x.length; ++i) {        
       val += x[i];        
       if (i < x.length-1) {
           val = val << 8;
       }
   }
   return val;
}

Map

Eine Karte mit allen Gateways die bei TTN registriert sind befindet sich hier.

In der Region Wiesbaden findet man im Norden das Gateway am Campus Unter den Eichen, im Südosten das Gateway bei den Freifunkern Wiesbaden und im Südwesten ein Gateway von einem uns unbekannten Dritten.

TTN Map.jpg

Application

Um auf die Daten der Nodes zuzugreifen bietet das TheThingsNetwork unterschiedliche Möglichkeiten an.

  • HTTP
  • gRPC
  • MQTT
    • Go
    • Java
    • Python
    • Node.js
    • Node-RED
  • Cayenne
  • AllThingsTalk Maker
  • Collos
  • EVRYTHNG
  • IFTTT Maker
  • OpenSensors

Die Application empfängt die Daten mittels MQTT. Node-Red abonniert dazu das entsprechende Topic im TTN und schreibt die empfangen Daten in die InfluxDB, eine Datenbank speziell für IOT. Zur grafischen Darstellung wird zum Abschluss Grafana verwendet, da dort die Visualisierung übersichtlicher und besser gestaltet werden kann als in Node-Red.

Node-RED

Node-RED aktualisieren:

sudo update-nodejs-and-nodered

Autostart zu Node-RED hinzufügen:

sudo systemctl enable nodered.service

TTN-Node installiren:

cd $HOME/.node-red
npm install node-red-contrib-ttn

InfluxDB

influxDB-Node installieren:

npm install node-red-contrib-influxdb

influxDB installieren:

https://docs.influxdata.com/influxdb/v1.4/introduction/installation/

Grafana

Grafana installieren:

sudo wget https://github.com/fg2it/grafana-on-raspberry/releases/download/v5.0.0/grafana_5.0.0_armhf.deb
sudo dpkg -i grafana_5.0.0_armhf.deb
sudo systemctl enable grafana-server.service

Einrichten

In InfluxDB eine Datenbank anlegen, in userem Fall "temperature"

influx
CREATE DATABASE temperature

In Node-RED einen "ttn uplink"-node erstellen und diesen mit einem "influxdb out"-node verbinden. Ein Debug-Node als Hilfe schadet auch nie.

LoRaApp4.png

In dem "ttn uplink"-node müssen zunächst die Application Daten aus der TTN-Console eingetragen werden. Über Deviece ID kann sich auf nur bestimmte Geräte beschränkt werden und über Fieleds auf bestimmte Felder der Nachricht, anstatt auf die ganze Nachricht selbst.

LoRaApp6.png LoRaApp5.png

In den "influxdb out"-node müssen die Anmeldedaten und die Datenbank eintragen. Ein Measurement ist eine Untermenge unter der die Daten in die Datenbank eingetragen werden.

LoRaApp7.png LoRaApp8.png

In Grafana muss nun die Datenbank als Datenquelle hinzugefügt werden.

LoRaApp3.png

In dem Dashboard können nun Graphen erstellt werden. In den Einstellungen des Graphen wird nun eine Quary auf die Datenbank und das Measurement gemacht.

LoRaApp2.png

Dies wird für alle Felder wiederholt und je nach belieben kann das Aussehen des Dashboards noch verbessert werden.

LoRaApp1.png

LoRa in Wiesbaden

In Wiesbaden sind jetzt zwei Gateways vorhanden: Das Gateway am Campus "Unter den Eichen", welches vor allem zum Testen verwendet wurde sowie das Gateway in der Hans-Bredow-Straße. Dieses wurde mit Hilfe der Freifunker Wiesbaden auf einem Bürohochhaus platziert. Beide Gateways auf einer Karte von Wiesbaden:


LoRa WB.jpg


Campus Unter den Eichen

Um Tests durchzuführen, ist am Campus der Hochschule RheinMain ein LoRa-Gateway aufgebaut:


Gateway Overview.jpg


Mit diesem Gateway wurden auch erste Reichweitentests durchgeführt. Hierbei wurde das Gateway auf dem Balkon platziert. Da es an dem Tag feucht war, wurde es zum Schutz vor Nässe in eine Box gelegt.


VersuchsaufbauUdE.JPG

So konnte eine Reichweite von 1655 Metern gemessen werden. Hierbei ist zu beachten, dass die Reichweiten sich je nach Himmelsrichtung stark unterschieden. Dies hängt mit den Wänden des Gebäudes zusammen, welche die Übertragungsweite einschränken. Die Ergebnisse sind hier dargestellt (je rötlicher desto besser der Empfang; je bläulicher desto schlechter):


LoRaWanReichweite1.png

Freifunk Wiesbaden

Von den Freifunkern Wiesbaden wurde uns ein Platz auf einem Hochhaus zur Verfügung gestellt. Vor Ort sieht es nun folgendermaßen aus:


LoRa Montage.jpg


Ansicht vor der Montage des Gateways mit Hülle:


LoRa G.jpg


Aussicht vom Bürogebäude aus:


LoRa Aussicht.jpg


Mit dem Gateway in der Hans-Bredow-Straße wurden einige Reichweitentests durchgeführt. Das Ergebnis davon ist in folgendem Bild zu sehen:


LoRa Freifunker.jpg


Dabei erhielten wir als maximale Reichweite eine Distanz von 2265 Metern.
Die Reichweite variiert allerdings sehr stark, vor allem im dichten Stadtgebiet ist sie deutlich niedriger. Sind Häuser in Luftlinie zum Gateway verringert sich die maximale Reichweite auf einige hundert Meter. Im Wohngebiet war das Maximum mit rund 400 Metern erreicht.
Die höchste Distanz erhielten wir von einer hohen Position, von der man auch auf andere Hochhäuser in der Umgebung blicken konnte.
Allgemein lässt sich sagen, je weniger Häuser oder sonstige Störer zwischen Node und Gateway sind, desto höhere Reichweiten lassen sich erzielen. Wird von Erhebung zu Erhebung über ein Tal hinweg gefunkt, lassen sich die offiziellen Reichweiten in Städten von 2 Kilometern messen. In dicht besiedeltem Wohngebiet sind diese 2 Kilometer - nach unseren Versuchen - als unrealistisch zu betrachten.

TTN Mapper

Die Tests wurden mit der App "TTN Mapper" durchgeführt. Die App muss dazu mit den entsprechenden Daten aus dem TTN konfiguriert werden:


TTN App Config.png


Die Testergebnisse werden dort ebenfalls in einer Heatmap dargestellt:


TTN App.png


Das GPS-Signal des Smartphones gibt hierbei den Punkt auf der Karte an und die App muss gleichzeitig beim Senden einer Nachricht offen sein.


Alle Daten zum Experiment sind hier zu finden.

Fazit

Zum Abschluss soll ein kurzes Gesamtfazit zum Projekt gegeben werden. Zu Beginn des Projekts mussten wir feststellen, dass LoRa in Deutschland noch nicht weit verbreitet ist. Es gibt allerdings viele angefangene Projekte, welche zum Teil unvollständig und schlecht dokumentiert sind, sodass zum Einstieg ein hohes Maß an Selbsteinarbeitung nötig war. Zu Beginn haben wir vieles probiert und ebenso viel verworfen, bis wir eine erste lauffähige Version gefunden hatten.

Als das Gateway am laufen war erschwerte der an der Hochschule verwendete Proxy die arbeiten enorm(!). Da wir hinter dem Proxy arbeiten mussten, ging ein Großteil der Arbeitszeit für die Bewältigung der Probleme, welche mit dem Proxy zusammenhingen, drauf.

Bedanken möchten wir uns an dieser Stelle bei den Freifunkern Wiesbaden, die uns einen Platz zur Verfügung gestellt haben, um auch einen Gateway-Standwort in Wiesbaden zu ermöglichen. Mit ihrer Hilfe und Möglichkeit zu einem Zugang zu einem Hochhaus konnte ein wesentlich aussagekräftigerer Reichweitentest durchgeführt werden und absofort dauerhaft ein Gateway für jeden zur Verfügung gestellt werden.

Insgesamt lässt sich über das Projekt sagen, dass es zunächst schwer ist, einen Anfang zu finden. Sobald man eine erste funktionierende Version eines Gateways und eines Nodes erstellt hat, lässt sich jedoch viel mit testen und durchprobieren lösen. Zum Ende hin haben wir eine gesamte prototypische Anwendung erstellt, die unsere Daten über das TTN überträgt und an eine Application weitergibt, um die Daten auszuwerten. Somit ist das Projekt auch für uns ein Erfolg :)