Skip to content
A server for The Things Network to store and display your devices on a map
Go HTML Makefile Dockerfile
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
geottnsvc added list devices Nov 23, 2019
web fly to device Nov 23, 2019
go.sum started web views Nov 21, 2019


An application for The Things Network moving devices.

This is an all in one server, that will store historical data of your devices and display them on a map, also exposing an API to query.

The idea is to have a self hosted IOT solution that works without sending your data to a third party.

The assumed encoding from your device is Cayenne

Current web interface

Technical Details

GeoTTN is a multi components app put together:

  • A Badger storage database using S2 as a geographical indexing system
  • A client of the Things Network gRPC API to receive uplink messages
  • A gRPC API to query the Badger database
  • A web frontend to display the devices on a map

It's shipped in one app on purpose to run inside a one Docker instance, without resorting to complex admin task.
It should be fine for thousands of devices until you want to break the components apart, contact me for a more robust clustered solution.

The code is modular so you can change it for your own purpose.


You need to have some existing devices registered in the Things Network.

Simply pass your appID & appAccessKey on the command line or via environment.

You can also use the docker image as follow:

docker run -it akhenakh/geottn:latest -e TILESKEY=pk.eyJxxxxxxxxxxxxxxxxxxxx  -e APPID=myappid -e APPACCESSKEY=xxxxxxxxxx -e DBPATH=/data/geo.db -v /mysafesotorage/volume:/data

For the map to show up register with MapBox for a free token and pass it as tilesKey.
Note that you can use a self hosted map solution with selfHostedMap=true.


You'll need the packr2 command:

go get -u
make geottnd
make geottnd-image


A gRPC API is exposed

service GeoTTN {
  rpc Store (DataPoint) returns (google.protobuf.Empty) {}
  rpc RadiusSearch(RadiusSearchRequest) returns (DataPoints) {}
  rpc RectSearch(RectSearchRequest) returns (DataPoints) {}
  rpc Get(GetRequest) returns (DataPoint) {}
  rpc GetAll(GetRequest) returns (DataPoints) {}
  rpc Keys(google.protobuf.Empty) returns (KeyList) {}

There is a demo cli in cmd/geottncli

 ./cmd/geottncli/geottncli -radius=1000
2019/11/22 14:28:03 query ok 2
2019/11/22 14:28:03 map[device_id:ttgo00 gps_1:[48.4 2.45 0] time:seconds:1574438932 nanos:728890266 ]
2019/11/22 14:28:03 map[device_id:ttgosens00 gps_1:[48.8821 2.28 0] time:seconds:1574434228 nanos:790831992 ]

./cmd/geottncli/geottncli -key ttgosens00  
2019/11/22 14:28:19 map[device_id:ttgosens00 gps_1:[48.8821 2.28 0] time:seconds:1574434228 nanos:790831992 ]

A very simple web API (used for the web interface):

r.HandleFunc("/api/devices", s.DevicesQuery)
r.HandleFunc("/api/data/{key}", s.DataQuery)
r.HandleFunc("/api/rect/{urlat}/{urlng}/{bllat}/{bllng}", s.RectQuery)


Some stats are available on the metrics ports httpMetricsPort eg http://localhost:8888/metrics


  • UDP semtech gw
  • Register devices with the web interface
  • Vuejs web interface
  • end to end TLS certs
  • support no GPS data


This is a work in progress, help and ideas are welcome.


  • If you don't set your appAccessKey right the error message will show up 1mn later.
You can’t perform that action at this time.