- TL;DR
- Introduction
- Migrating from The Things Network V2 TTN V2 to The Things Stack Community Edition TTN V3
- balenaCloud TTN Gateway Connector for Raspberry Pi
- Prerequisites
- Create a balenaCloud fleet
- Transferring TTN Gateway software to balenaCloud so that it may be downloaded on your devices
- Create a new gateway on The Things Network
- Configure the gateway device on balenaCloud
- Reset pin values
- Special note for using a Raspberry Pi 3
- Troubleshooting
- Pro Tips
- Device statistics
- Docker setup
- Credits
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:
But you are still encouraged to read this page!
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:
gateway
: runs the Multi-protocol Packet Forwarder by Jac Kersing.- If you use Prometheus monitoring:
prom-exporter
: the Prometheus exporterexporter
: exporter add-on for the gateway statistics
- If you use collectd monitoring:
collectd
: the collectd daemon, with a gateway monitoring pluginfan
: fan controller (optional)
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).
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.
If you already run this setup on Things Network V2, migrating to The Things Stack Community Edition is straightforward!
- Add your Gateway to The Things Stack Community Edition. You can / should reuse the same Gateway ID, EUI, Name...
- Obtain an API Key as described hereunder
- Push the latest version of this repository to balenaCloud as you usually do (using
git
or the balena CLI) - In balenaCloud:
- update your
GW_KEY
variable with your new API key - if you are not in the
eu1
region, define theSERVER_TTN_CLUSTER_ID
variable and set it to the appropriate region (nam1
orau1
)
- update your
That's it!
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:
- IMST iC880A-SPI. Preferable configured as described by TTN-ZH. You do not need to follow the Setting up the software step, as the setup scripts in this repository does it for you.
- LinkLabs Raspberry Pi "Hat"
- RisingHF IoT Discovery
- RAK831
- RAK833 PCIe LoRa Gateway Concentrator Module
- Build your hardware.
- Create and sign into an account at balena.io, which is the central "device dashboard".
- 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.
- 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.)
- 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.
- 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.
- If you like, enter any new Device Name that you'd like, such as "my-gateway-amsterdam".
-
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/
-
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 thefan
service from thedocker-compose-fan.yml
to yourdocker-compose.yml
file.
Commit your choice withgit
: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"
-
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:- It will upload a docker-compose file and build scripts to balenaCloud
- It will start to do a "docker-compose build" using that docker-compose file, running it within a virtual machine on the balenaCloud service.
- 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.
- When the build is completed, you'll see a unicorn 🦄 ASCII graphic displayed in your terminal.
-
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.
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!
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.
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.
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 |
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.
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:
Name | Value |
---|---|
BALENA_HOST_CONFIG_core_freq | 250 |
BALENA_HOST_CONFIG_dtoverlay | pi3-miniuart-bt |
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.
$
-
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 usinggit
: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.
If you want to show nice looking statistics for your gateway(s) there are a couple of additional steps to take.
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 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.
If you do not want to use the balena.io services, you can run the exact same configuration directly on your 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
You have 2 options: download the pre-build containers or re-build them.
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
If for whatever reason you want to re-build the containers on your Pi, run:
docker-compose build
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.
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
- Gonzalo Casas on the iC880a-based gateway
- Ruud Vlaming on the Lorank8 installer
- Jac Kersing on the Multi-protocol packet forwarder
- JP Meijers on the latest balenaCloud setup
- Ray Ozzie on the original balenaCloud setup
- The Team at balena.io