Skip to content


Repository files navigation

Clair Things Network Application

Clair-TTN is part of the Clair Platform1, a system to collect measurements from networked CO2-sensors for indoor air-quality monitoring. It is developed and run by the Clair Berlin Initiative, a non-profit, open-source initiative to help operators of public spaces lower the risk of SARS-CoV2-transmission amongst their patrons.

Technically speaking, Clair-TTN is a service in the Clair Stack, which is the infrastructure-as-code implementation of the Clair Platform.

The application for The Things Network (TTN) supports the new TTN V3 stack. It can be run in the following modes:

  • Clairchen forwarding: subscribes to uplink messages of Clairchen nodes, decodes them and forwards measurement samples to the ingest endpoint of the backend API.
  • ERS forwarding: does the sampe for Elsys ERS CO2 nodes.
  • ERS configuration: subscribes to uplink messages of ERS nodes and sends downlink messages to update the sensor's parameters to meet the TTN's airtime constraints.
  • OY1012 forwarding: forwarding for Talkpool OY1012.

In addition to the TTN application, this repository also contains a couple of TTN device management tools documented below.

Development Setup

python3 -m venv env
. env/bin/activate
pip install wheel
pip install --editable .

Afterwards, the clairttn command should be available (source).


pytest tests can be run like this:

python3 test

Clair-TTN Usage

Usage: clair-ttn [OPTIONS]

  Clair TTN application that can be run in one of the following modes:

  * Clairchen forwarding
  * ERS forwarding
  * ERS configuration
  * OY1012 forwarding

  -i, --app-id TEXT               [default: clair-berlin-ers-co2]
  -k, --access-key-file FILENAME  [required]
  -m, --mode [clairchen-forward|ers-forward|ers-configure|oy1012-forward]
  -r, --api-root TEXT             [default: http://localhost:8888/ingest/v1/]
  -s, --stack [ttn-v2|ttn-v3]     [default: ttn-v2]
  --help                          Show this message and exit.

The following parameters can also be specified as environment variables:

  • app id: CLAIR_TTN_APP_ID
  • mode: CLAIR_MODE
  • api root: CLAIR_API_ROOT
  • stack: CLAIR_TTN_STACK

TTN Node Management Tools

The Node Management allow batch registration of sensor nodes in both the clair stack and a corresponding TTN-v3 application, as well as importing sensor data from the TTN storage integration.

Device Registration

Registering a specific sensor node with a given device EUI is a three-step process:

  1. Register the sensor node in the clair stack's managair application using clair-register-device-in-managair.
  2. Register the sensor node in your TTN-V3 application using ttn-lw-cli, the command line interface provide by The Things Industries.
  3. Use clair-generate-nfc-config to create a configuration file with the TTN join EUI, key material, and device settings, and encode this configuration in a QR code that can be applied to Elsys ERS devices by means of the NFC Tools app for iOS.

Currently, only the ERS CO2 and ERS CO2 Lite sensors by ELSYS are supported by these tools.


To register a sensor node in the managair application, the device model, the communication protocol it uses, and the owning organization all must be set up already.

clair-register-device-in-managair computes a universal device id from the device's TTN EUI and creates a corresponding node owned by the organization identified by OWNER_ID.

Usage: clair-register-device-in-managair [OPTIONS] PROTOCOL_ID MODEL_ID
                                         OWNER_ID [DEVICE_EUI]...

  Register Clair TTN nodes in the managair.

  PROTOCOL_ID is the id of the (existing) node protocol in the managair.
  MODEL_ID is the id of the (existing) node model in the managair.
  OWNER_ID is the id of the (existing) owner organization in the managair.
  DEVICE_EUI is the TTN device EUI.

  You will be prompted to enter usename and password of an account which needs
  to be a member of the owner organization. The account needs to have the
  right to create a node.

  -r, --api-root TEXT      [default: http://localhost:8888/api/v1/]
  -a, --alias-prefix TEXT
  --help                   Show this message and exit.


clair-generate-nfc-config writes the TTN application EUI, the TTN application key, and sensor and transmission configuration compatible with the TTN Fair Use Policy to a text file and a PNG-file QR code that can be read using the NFC Tools app for iOS. Both files are created in the working directory as ${DEV_EUI}-nfc-config.txt and ${DEV_EUI}-nfc-config.png, respectively. Existing files are overwritten!

Usage: clair-generate-nfc-config [OPTIONS] JOIN_EUI DEV_EUI APP_KEY

  Create NFC config files for Elsys ERS CO2 sensors..

  JOIN_EUI to join a specific TTN application.
  DEV_EUI is the TTN device EUI.
  APP_KEY is the TTN's app_key root key.

  --help  Show this message and exit.


clair-get-device-id converts the device EUI of an Elsys ERS sensor node to the internal Clair device id.

Usage: clair-get-device-id [OPTIONS] DEV_EUI

  Convert a device EUI of an Elsys ERS sensor node to the corresponding
  managair device id.

  DEV_EUI is the LoraWAN device EUI.

  --help  Show this message and exit.

Registering devices with TTN-V3 using ttn-lw-cli

ttn-lw-cli is the TTN's official command-line interface. Clair sensor nodes can be registered with a TTN application using the end-devices create command as follows:

ttn-lw-cli end-devices create $app_id $dev_id \
  --dev-eui $dev_eui \
  --join-eui $join_eui \
  --frequency-plan-id EU_863_870 \
  --with-root-keys \
  --lorawan-version 1.0.3 \
  --lorawan-phy-version 1.0.3-a

The following variables must be provided:

  • $app_id: the id of your TTN application,
  • $dev_id: the managair device id as returned by clair-get-device-id.
  • $join_eui: the TTN device's JoinEUI, which may be specific to the device or the application.

We add the --with-root-keys option to have root keys generated. The application key needs to be passed on to clair-generate-nfc-config. To read back the key you can use the following command:

app_key=`ttn-lw-cli end-devices get $app_id $dev_id --root-keys | \
  python3 -c "import sys, json; print(json.load(sys.stdin)['root_keys']['app_key']['key'])"` is an exemplary wrapper script written for the Berlin COMo project.

Restoring data from the TTN's Storage Integration (TTN v3 only)

The TTN Storage Integration, if enabled, persists your TTN application's data for seven days. clair-generate-fixtures-from-storage reads this data and converts it to fixtures which can be read by Django's loaddata command.


Usage: clair-generate-fixtures-from-storage [OPTIONS] APPLICATION_ID

  Generate fixtures from the TTN's Storage integration (v3).

  APPLICATIION_ID is the id of the TTN app.
  ACCESS_KEY_FILE is the file containing the TTN app's access key.

  -b, --base-url TEXT  [default:]
  -d, --duration TEXT  [default: 24h]
  --help               Show this message and exit.


  1. The Clair Platform and the Clair-Berlin initiative are now part of the CO2-Monitoring (COMo) project, funded by a grant from the Senate Chancellery of the Governing Mayor of Berlin.