/ttn-gateway-containers

Fork for JP Meijers' repo to use a multi-container configuration (Prometheus exporters run in separate containers) as well as collectd support

Primary LanguagePython

TTN Gateway Containers

Contents

TL;DR

If all you need is to run a Raspberry Pi based LoRaWAN Gateway to The Things Network without Prometheus or collectd monitoring backend, click the following button:

balena deploy button

But you are still encouraged to read this page!

Introduction

This is a Docker setup to run a Raspberry Pi based LoRaWAN Gateway to The Things Network (TTN).

It is compatible with The Things Stack Community Edition, also know as The Things Network V3 (see The Things Network Quick Start for more information).

It can be run with balenaCloud or as Plain Docker on Raspbian.

The setup is made of multiple containers:

The build will use the latest Multi-protocol Packet Forwarder release.

An alternative guide to use this balenaCloud setup can be found in the official TTN documentation (deprecated).

Difference between Poly-packet-forwarder and Multi-protocol-packet-forwarder

The Multi-protocol-packet-forwarder (mp-pkt-fwd) uses the new protocolbuffers-over-mqtt-over-tcp protocol for gateways, as defined by TTN and used by the TTN Kickstarter gateway. Using this protocol the gateway is authenticated, which means it is registered under a specific user and can thus be trusted. Because it uses TCP, the chance of packet loss is much lower than with the previous protocol that used UDP. Protocolbuffers packs the data in a compact binary mode into packets, using much less space than the plaintext json that was previously used. It should therefore consume less bandwidth.

When you use this repository, the settings you set on the TTN console are taken as the primary settings. The settings from the console are read and applied at gateway startup. If you for example change the location of the gateway on the console, that setting will only be applied when the gateway restarts.

Migrating from The Things Network V2 (TTN V2) to The Things Stack Community Edition (TTN V3)

If you already run this setup on Things Network V2, migrating to The Things Stack Community Edition is straightforward!

  1. Add your Gateway to The Things Stack Community Edition. You can / should reuse the same Gateway ID, EUI, Name...
  2. Obtain an API Key as described hereunder
  3. Push the latest version of this repository to balenaCloud as you usually do (using git or the balena CLI)
  4. In balenaCloud:
    • update your GW_KEY variable with your new API key
    • if you are not in the eu1 region, define the SERVER_TTN_CLUSTER_ID variable and set it to the appropriate region (nam1 or au1)

That's it!

balenaCloud TTN Gateway Connector for Raspberry Pi

balenaCloud Dockerfile & scripts for The Things Network gateways based on the Raspberry Pi. This updated version uses the gateway connector protocol, not the old packet forwarder. See the TTN documentation on Adding Gateways.

Currently any Raspberry Pi with one of the following gateway boards, communicating over SPI, are supported, but not limited to these:

Prerequisites

  1. Build your hardware.
  2. Create and sign into an account at balena.io, which is the central "device dashboard".

Create a balenaCloud fleet

  1. On balenaCloud, create a "Fleet" for managing your TTN gateway devices. I'd suggest that you give it the name "ttngw", select the appropriate device type (i.e. Raspberry Pi 2, Raspberry Pi 3, ...), and click "Create new fleet". You only need to do this once, after which you'll be able to manage one or many gateways of that type.
  2. You'll then be brought to the Device Management dashboard for that Fleet. Click on "Add device" and follow the instructions to "Download balenaOS" and create a boot SD-card for your Raspberry Pi. (Pro Tip: Use a fast microSD card and a USB 3 adapter if you can, because it can take a while to copy all that data. Either that, or be prepared to be very patient.)
  3. When the (long) process of writing the image to the SD card completes, insert it into your Raspberry Pi, connect it to the network with Ethernet, and power it up.
  4. After several minutes, on the balenaCloud Devices dashboard you'll now see your device - first in a "Configuring" state, then "Idle". Click it to open the Devices control panel.
  5. If you like, enter any new Device Name that you'd like, such as "my-gateway-amsterdam".

Transferring TTN Gateway software to balenaCloud so that it may be downloaded on your devices

  1. On your computer, clone this git repo. For example in a terminal on Mac or Linux type:

    git clone https://github.com/AmedeeBulle/ttn-gateway-containers.git
    cd ttn-gateway-containers/
  2. Choose your monitoring backend.
    There are 3 docker-compose files available:

    • docker-compose.yml if you don't have a monitoring backend;
    • docker-compose-prometheus.yml if you want use Prometheus;
    • docker-compose-collectd.yml if you prefer collectd.

    If you have a monitoring backend, override the default docker-compose.yml file with the appropriate compose file. If you have a Coredump backplane with a fan, you can add the fan service from the docker-compose-fan.yml to your docker-compose.yml file.
    Commit your choice with git:

    cp docker-compose-<Your Backend>.yml docker-compose.yml
    # Edit to add the fan service if you have a Coredump backplane
    git add .
    git commit -m "Select monitoring backend"
  3. Now, click on "Create release" from the Fleet Summary page and follow the instructions to push the TTN software to the balenaCloud.
    There are two options (with balena CLI or with git), pick whatever you prefer!
    This triggers an incredible amount of work:

    1. It will upload a docker-compose file and build scripts to balenaCloud
    2. It will start to do a "docker-compose build" using that docker-compose file, running it within a virtual machine on the balenaCloud service.
    3. In processing this docker build, it will run a build script that downloads and builds the packet forwarder executable from source code, for RPi+iC880A-SPI.
    4. When the build is completed, you'll see a unicorn 🦄 ASCII graphic displayed in your terminal.
  4. Now, switch back to your device dashboard, you'll see that your Raspberry Pi is now "updating" by pulling the Docker containers from the balenaCloud service.
    Then, after "updating", take look at the gateway's log in the "Logs" window. You will see something like this:

...
 gateway  *******************
 gateway  *** Configuration:
 gateway  *******************
 gateway  GW_EUI:       xxxxxxFFFExxxxxx
...
 gateway  ERROR: GW_KEY required
 gateway  Container will terminate in 30s.
...

It is time to configure your gateway, take note of the "Gateway EUI" displayed in the Logs window.

Create a new gateway on The Things Network

From the TTN Console for your region, select "Go to Gateways" and click on "Add gateway".

Enter a "Gateway ID" of your choice and use the "Gateway EUI" from the previous step.

Once created, go to "Location" and set the location and altitude of your gateway.

Last but not least, you will need to create an API key for authentication. You can create such a key at gateway level, it will be valid only for this gateway; or at user level (Personal API key), in this case the same key can be used for all your gateways. The key must include at least the following rights:

  • View gateway information
  • Link as Gateway to a Gateway Server for traffic exchange, i.e. write uplink and read downlink
  • View gateway location

Take good note of the API key, you will not be able to retrieve it afterwards!

Configure the gateway device on balenaCloud

We have now all the information required to configure our device on balenaCloud

From the Device screen for your gateway, click the "Device Variables" section at the left side of the screen. This will allow you to configure this and only this device. These variables will be used to pull information about this gateway from TTN, and will be used to create a configuration file for this gateway.

Once the variables are set, you'll see your gateway initializing, and will also see log output each time a packet is forwarded to TTN.

For a more complete list of possible environment variables, see CONFIGURATION.

Device environment variables - no GPS

For example, for an IMST iC880A or RAK831 with no GPS, the MINIMUM environment variables that you should configure at this screen should look something like this:

Name Value
GW_ID Your gateway ID from the TTN console
GW_KEY Your API KEY created in previous step
SERVER_TTN_CLUSTER_ID Your regional TTN cluster (eu1, nam1, au1; default: eu1)
GW_RESET_PIN 22 (optional)

GW_RESET_PIN can be left out if you are using Gonzalo Casas' backplane board, or any other setup using pin 22 as reset pin. This is because pin 22 is the default reset pin used by this balenaCloud setup.

Device environment variables - with GPS

For example a LinkLabs gateway, which has a built-in GPS, you need:

Name Value
GW_ID Your gateway ID from the TTN console
GW_KEY Your API KEY created in previous step
SERVER_TTN_CLUSTER_ID Your regional TTN cluster (eu1, nam1, au1; default: eu1)
GW_GPS true
GW_RESET_PIN 29

Reset pin values

Depending on the way you connect the concentrator board to the Raspberry Pi, the reset pin of the concentrator might be on a different GPIO pin of the Raspberry Pi. Here follows a table of the most common backplane boards used, and the reset pin number you should use in the GW_RESET_PIN environment variable.

Note that the reset pin you should define is the physical pin number on the Raspberry Pi. To translate between different numbering schemes you can use pinout.xyz.

Backplane Reset pin
Gonzalo Casas backplane (Tindie) 22
ch2i 11
Linklabs Raspberry Pi Hat 29 (untested)
Rising HF Board 26
IMST backplane or Lite gateway 29 (untested)
Coredump backplane (Coredump) 22
RAK backplane 11
Pi Supply IoT LoRa Gateway HAT for Raspberry Pi 15

If you get the message ERROR: [main] failed to start the concentrator after balenaCloud is finished downloading the application, or when restarting the gateway, it most likely means the GW_RESET_PIN you defined is incorrect. Alternatively the problem can be caused by the hardware, typically for the IMST iC880A-SPI board with insufficient voltage, try another power supply or slightly increase the voltage.

Special note for using a Raspberry Pi 3

There is a backward incompatibility between the Raspberry Pi 1 and 2 hardware, and Raspberry Pi 3. For Raspberry Pi 3, it is necessary to make a small additional configuration change.

From the Fleet Summary page, click on "Configuration" and "Add custom variables" as follows:

Fleet custom configuration variables

Name Value
BALENA_HOST_CONFIG_core_freq 250
BALENA_HOST_CONFIG_dtoverlay pi3-miniuart-bt

Troubleshooting

If you get the error below please check if your ssh public key has been added to you balenaCloud account. In addition verify whether your private key has the correct permissions (i.e. chmod 400 ~/.ssh/id_rsa).

$ git push -f balena master
Connection closed by xxx.xxx.xxx.xxx port 22
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
$

Pro Tips

  • At some point if you would like to add a second gateway, third gateway, or a hundred gateways, all you need to do is to add a new device to your existing Application. You needn't upload any new software to balenaCloud, because balenaCloud already knows what software belongs on the gateway. So long as the environment variables are configured correctly for that new device, it'll be up and running immediately after you burn an SD card and boot it.

  • balenaCloud will automatically restart the gateway software any time you change the environment variables. You'll see this in the log. Also, note that balenaCloud restarts the gateway properly after power failures. If the packet forwarder fails because of an error, it will also automatically attempt to restart.

  • If you'd like to update the software across all the gateways in your device fleet, use balena push or if using git:

    git add .
    git commit -m "Updated gateway version"
    git push -f balena master
  • For devices without a GPS, the location that is configured on the TTN console is used. This location is only read at startup of the gateway. Therefore, after you set or changed the location, restart the application from the balenaCloud console.

Device statistics

If you want to show nice looking statistics for your gateway(s) there are a couple of additional steps to take.

Prometheus

Once the new image is deployed, go to the balenaCloud dashboard for your devices and select 'Enable Public device URL' in the drop down menu (the one to the right of the light bulb). That is all that is required to provide metrics. Now you will need to install a metrics collector on a separate system as outlined in Fleet-wide Machine Metrics Monitoring in 20mins.

(To show packet forwarder graphs you need to add your own graphs to the provided templates)

Collectd

Collectd will typically send its data to an InfluxDB/Grafana backend.
Minimal configuration requires the IP of the collectd server:

Name Value
GW_COLLECTD_SERVER The IP address of the collectd server

See CONFIGURATION - Collectd variables for additional configuration options.

Docker setup

If you do not want to use the balena.io services, you can run the exact same configuration directly on your Raspberry Pi.

Prepare the Raspberry Pi

Download and install Raspbian Stretch Lite to your Pi (Follow the instructions from the Foundation).
Although it will work with the full Desktop environment, I strongly recommend the Lite version.

Using raspi-config enable SPI and I2C (if needed for your backplane).

On raspberry Pi 3B(+), add the following lines to /boot/config.txt:

core_freq=250
dtoverlay=pi3-miniuart-bt

As root, install git, docker and docker-compose:

# apt-get update
# apt-get install git curl python-pip
# curl -sSL https://get.docker.com | sh
# pip install docker-compose

Ensure your linux user (pi or whatever you choose) is in the docker group:

# usermod -a -G docker <YourLinuxUser>

At this point you need to completely logout and re-login to activate the new group.

From here, you don't need root access anymore.

Clone this repository:

git clone https://github.com/AmedeeBulle/ttn-gateway-containers.git
cd ttn-gateway-containers/

There are three docker-compose files available:

  • docker-compose.yml if you don't have a monitoring backend;
  • docker-compose-prometheus.yml: Prometheus monitoring;
  • docker-compose-collectd.yml: collectd monitoring.

If you have a monitoring backend, override the default docker-compose.yml file:

cp docker-compose-<Your Backend>.yml docker-compose.yml

Alternatively you can specify the file to use on each docker-compose command. E.g.:

docker-compose -f docker-compose-collectd.yml up

If you have a Coredump backplane with a fan, you can use the additional docker-compose-fan.yml override file to control the fan. E.g.:

docker-compose -f docker-compose-gateway.yml -f docker-compose-fan.yml up

Note that you can use the COMPOSE_FILE environment variable instead of using the -f option. E.g.:

export COMPOSE_FILE="docker-compose-gateway.yml:docker-compose-fan.yml"

The sample code blocks below omit the -f <compose file> for the sake of clarity

Get the containers

You have 2 options: download the pre-build containers or re-build them.

Option 1: Download the containers

This is the easiest and fastest way. It is also the recommended way on the Raspberry Pi Zero as a build will take quite some time!
The pull command will download the containers from the Docker Hub:

docker-compose pull

Note for Raspberry Pi Zero: multiarch build does not work properly on ARM variants (See moby/moby#34875).
For the Raspberry Zero you need to amend the docker-compose files to pull the correct images:

sed -e 's/\(image:.*\)/\1:arm32v6-latest/' -i.orig docker-compose*.yml

Option 2: Re-Build the containers

If for whatever reason you want to re-build the containers on your Pi, run:

docker-compose build

Configure and run the TTN Gateway

To customise your setup, create a file named .env with the environment variables described in the balenaCloud section. Use the file .env-distr as template.

Run the TTN Gateway:

docker-compose up

This will start the containers and remain attached to your terminal. If everything looks good, you can cancel it and restart the service in detached mode:

docker-compose up -d

This will keep he containers running, even after a reboot.

Updates

To update your setup with a newer version, get the latest code and containers and restart the service:

docker-compose down
git pull origin master
docker-compose pull # or build
docker-compose up

Credits