Skip to content
This repository has been archived by the owner on Oct 6, 2021. It is now read-only.

Guide to ADS B Data Receiving, Decoding and Sharing, Leveraging RTLSDR and Docker

Mike edited this page Dec 30, 2020 · 56 revisions

Deprecation Notice

This guide is now deprecated. I've published a new one here: https://mikenye.gitbook.io/ads-b/.

I'll keep this one around for posterity.

Thanks!

Guide to ADS-B Data Reception, Decoding & Sharing with RTLSDR & Docker

Automatic Dependent Surveillance-Broadcast (ADS-B) is a surveillance technology in which an aircraft determines its position via satellite navigation and periodically broadcasts it, enabling it to be tracked.

This ADSB-B data can be received by nerds enthusiasts using Software Defined Radio (SDR), and used for fun and profit. For example:

Fun:

Profit:

This guide will go through the process to deploy and configure Docker containers to allow reception and decoding of ADS-B data, as well as submission to various flight tracking services, both open and commercial.


Table of Contents

Dedication

One day I arrived at work, sat down at my desk, probably sighed and looked wistfully into the distance as I thought about getting my morning coffee. My good friend and work colleague Jay wheeled his chair over. "I've got you something!" he said enthusiastically whilst placing a small cardboard box on the edge of my desk, completely out of the blue. "What is this?" I suspiciously said while sizing him up as I opened the box. Inside the box was a FlightAware Pro-Stick Blue with an antenna! This thoughtful gift spurred my somewhat unhealthy obsession with flight tracking.

Thanks Jay. You're a good bloke.

For the experienced

If you're new to docker-compose and/or ADS-B reception, you are encouraged to skip this section.

If you're already well versed with docker-compose and ADS-B reception, here's the complete docker-compose.yml that will be generated when using this guide:

version: '2.0'

networks:
  adsbnet:

volumes:
  graphs1090_rrd:

services:

  readsb:
    image: mikenye/readsb:latest
    tty: true
    container_name: readsb
    restart: always
    devices:
      - YOURUSBDEVICEPATH:YOURUSBDEVICEPATH
    ports:
      - 8079:8080
      - 30003:30003
      - 30005:30005
    networks:
      - adsbnet
    environment:
      - PULLMLAT=piaware:30105,adsbx:30105,rbfeeder:30105
      - TZ=YOURTIMEZONE
    command:
      - --dcfilter
      - --device-type=rtlsdr
      - --json-location-accuracy=2
      - --lat=YOURLATITUDE
      - --lon=YOURLONGITUDE
      - --modeac
      - --ppm=0
      - --net
      - --stats-every=3600
      - --quiet
      - --write-json=/run/readsb

  adsbx:
    image: mikenye/adsbexchange:latest
    tty: true
    container_name: adsbx
    restart: always
    environment:
      - BEASTHOST=readsb
      - TZ=YOURTIMEZONE
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
      - ALT=YOURALTITUDE
      - SITENAME=YOURADSBXSITENAME
      - UUID=YOURADSBXUUID
    networks:
      - adsbnet

  tar1090:
    image: mikenye/tar1090:latest
    tty: true
    container_name: tar1090
    restart: always
    environment:
      - TZ=YOURTIMEZONE
      - BEASTHOST=readsb
      - MLATHOST=readsb
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
    networks:
      - adsbnet
    ports:
      - 8078:80

  graphs1090:
    image: mikenye/graphs1090:latest
    tty: true
    container_name: graphs1090
    restart: always
    volumes:
      - graphs1090_rrd:/var/lib/collectd/rrd
    ports:
      - 8075:80
    environment:
      - BEASTHOST=readsb
      - MLATHOST=readsb
      - TZ=YOURTIMEZONE
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
    networks:
      - adsbnet

  fr24:
    image: mikenye/fr24feed:latest
    tty: true
    container_name: fr24
    restart: always
    ports:
      - 8754:8754
    environment:
      - BEASTHOST=readsb
      - FR24KEY=YOURFR24KEY
      - TZ=YOURTIMEZONE
      - MLAT=yes
    networks:
      - adsbnet

  piaware:
    image: mikenye/piaware:latest
    tty: true
    container_name: piaware
    restart: always
    ports:
      - 8080:8080
    environment:
      - TZ=YOURTIMEZONE
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
      - FEEDER_ID=YOURPIAWAREFEEDERID
      - BEASTHOST=readsb
    networks:
      - adsbnet

  rbfeeder:
    image: mikenye/radarbox:latest
    tty: true
    container_name: rbfeeder
    restart: always
    environment:
      - TZ=YOURTIMEZONE
      - BEASTHOST=readsb
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
      - ALT=YOURALTITUDE_METRES
      - SHARING_KEY=YOURRBSHARINGKEY
    networks:
      - adsbnet

  pfclient:
    image: mikenye/planefinder:latest
    tty: true
    container_name: pfclient
    restart: always
    ports:
      - 30053:30053
    environment:
      - TZ=YOURTIMEZONE
      - BEASTHOST=readsb
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
      - SHARECODE=YOURPFSHARECODE
    networks:
      - adsbnet

  opensky:
    image: mikenye/opensky-network:latest
    tty: true
    container_name: opensky
    restart: always
    environment:
      - TZ=YOURTIMEZONE
      - BEASTHOST=readsb
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
      - ALT=YOURALTITUDE_METRES
      - OPENSKY_USERNAME=YOUROPENSKYUSERNAME
      - OPENSKY_SERIAL=YOUROPENSKYSERIAL
    networks:
      - adsbnet

Replacing:

  • YOURUSBDEVICEPATH with the USB device path to your RTL-SDR
  • YOURTIMEZONE with your local timezone in "TZ database name" format (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
  • YOURLATITUDE with the latitude of your antenna, to 5 decimal places
  • YOURLONGITUDE with the longitude of your antenna, to 5 decimal places
  • YOURALTITUDE_FEET with the altitude of your antenna above sea level, in feet
  • YOURALTITUDE_METRES with the altitude of your antenna above sea level, in metres
  • YOURALTITUDE with the altitude of your antenna above sea level, with either m or ft suffix. Note: negative altitudes MUST be in meters, with no suffix.
  • YOURADSBXSITENAME with your ADSBExchange site name
  • YOURADSBXUUID with your ADSBExchange UUID
  • YOURFR24KEY with your FlightRadar24 key
  • YOURPIAWAREFEEDERID with your Piaware feeder ID
  • YOURRBSHARINGKEY with your RadarBox sharing key
  • YOURPFSHARECODE with your PlaneFinder share code
  • YOUROPENSKYUSERNAME with your OpenSky Network Username
  • YOUROPENSKYSERIAL with your OpenSky Network feeder serial

After bringing this environment up, you'll be feeding ADSBExchange, FlightRadar24, FlightAware, RadarBox, PlaneFinder and OpenSky Network.

You should be able to point a web browser at:

  • http://dockerhost:8079/ for readsb's web interface
  • http://dockerhost:8078/ for tar1090's web interface (My visualisation of choice)
  • http://dockerhost:8754/ for fr24feed's web interface
  • http://dockerhost:8080/ for piaware's web interface (SkyAware)
  • http://dockerhost:30053/ for pfclient's web interface

Furthermore, dockerhost will be listening on ports 30003 and 30005 to provide BaseStation (30003) and Beast (30005) data to external services/applications.

Introduction

Overview

This document aims to guide you through:

The core set of containers consists of: readsb, adsbexchange and tar1090. This will provide you with:

  • ADS-B reception via readsb
  • Feed ADSBExchange, and also receive MLAT data
  • Local visualisation of ADS-B and MLAT data with tar1090

These are deployed (in conjunction with RTL-SDR hardware) as follows:

To explain the flowchart above:

  • ADS-B transmissions are received bia the 1090MHz antenna and RTL-SDR dongle
  • The RTL-SDR dongle device is mapped through to a readsb container, this container's function is to decode the ADS-B transmissions and makes them available via several protocols (BaseStation, Beast, BeastReduce, raw, VRS)
  • There are then three feeder containers:
    • piaware - this container reads Beast protocol data from readsb and submits flight data to the FlightAware service, and get their "Enterprise" feature set in return.
    • adsbx - this container reads Beast protocol data from readsb and submits flight data to the ADSBExchange service.
    • fr24 - this container reads Beast protocol data from readsb and submits flight data to the FlightRadar24 service, and get their "Business Plan" in return.
  • Flight data is visualised using tar1090, presenting a web interface allowing you to view the flight data received by you set-up in real time.

There are other feeder packages available (eg: OpenSky Network, Radarbox, etc) that you may wish to consider too. They are all explained in this document.

There are also other visualisation packages available (eg: FlightAirMap/VirtualRadarServer/Grafana) that you may wish to consider, however keep in mind that these may require quite a bit more horsepower than a Raspberry Pi can provide. tar1090 is very lightweight which is why it is recommended here.

All of the containers I list below will run on:

  • linux/amd64 ("modern" Intel/AMD PCs/servers)
  • linux/arm/v7 (Most Raspberry Pis operating systems)
  • linux/arm64 (Raspberry Pis running aarch64 operating systems)

This mix of architectures allows you to run this set-up this on almost any Linux machine.

If there's another feeder you'd like added as a container, please reach out to me via the methods outlined below.

How to Get Help

You can get help by joining my Discord, and asking your question in the #adsb-containers channel. I'm in Western Australia so if you don't get a response immediately it might be due to timezones/sleep.

Furthermore, I welcome any feedback on this document. If you think a section needs better instructions or further explanation, or if anything doesn't work for you, please let me know through the channels above so that I can continue to improve this document.

Why Docker

Mainly for Isolation. Dependencies or settings within a container will not affect any installations or configurations on the host computer, or on any other containers that may be running. By using separate containers for different parts of the ADSB reception/decode/submission processes, it means the multiple types and versions of software used for each process will not interfere with each other. Bringing online the ability to feed your ADSB data to another service becomes very simple - just starting another container without having to worry about software conflicts.

Furthermore, the machine running ADSB containers can also function as a Plex Server, an OwnCloud Server, a VM Host etc, meaning that you don't need a separate machine just for feeding ADSB data. This means there's less equipment to break and less power used.

Equipment Needed

To get started, you'll need:

  • A SDR that can receive 1090MHz. I personally use a FlightAware Pro Stick Plus. However, a $20 USB DVB-T RTL2832U dongle will do the job.
  • An antenna optimised for 1090MHz. I use a cheap eBay version of this. You could also make your own.
  • A computer running Linux, capable of running Docker, with a USB port. This can be a Raspberry Pi or an x86 desktop.
  • Cables:
    • USB cable to connect the SDR to the computer. I use a 20m active USB cable (similar to this) which runs from the Linux computer in my study up into my roof, where the SDR and antenna are located.
    • Coaxial cable to connect the antenna to the SDR. As my SDR is located just below my antenna, I use a "pigtail" similar to this.

There's a whole bunch of additional equipment that you could purchase and use, such as 1090MHz bandpass filters, amplifiers, etc etc. This is somewhat outside the scope of this document. If you want more information, I'd refer you to: https://flightaware.com/adsb/piaware/build

Information Needed

During this process, you'll need:

  • The latitude and longitude of your antenna (to at least five decimal places). To find this, you can either use a GPS, or use maps.google.com to zoom in on the exact spot of your antenna, and click to get the latitude and longitude.
  • The altitude (above sea level) of your antenna. To find this, you can either use a GPS, or use something like https://www.freemaptools.com/elevation-finder.htm to zoom in on the exact spot of your antenna, and then add the distance above ground level your antenna is located.

Setting up the Host System

Install Docker

Follow the instructions located here: https://docs.docker.com/install/

In short, you should be able to enter the following commands at your shell, which will automate the docker installation process:

curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh

After the above installation script finishes running, you should be able to test your docker installation by issuing the command:

docker run --rm hello-world

You should be presented with the following output:

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Install Docker Compose

Follow the instructions located here: https://docs.docker.com/compose/install/

In short, you should be able to enter the following commands at your shell, which will install the latest version of docker-compose:

sudo apt-get install -y libffi-dev libssl-dev python3 python3-pip
sudo apt-get remove python-configparser
sudo pip3 install docker-compose

After performing the above commands, you can test docker-compose by having it print its version:

docker-compose --version

...which should return something similar to:

docker-compose version 1.25.4, build unknown

Configure Docker

Before starting any containers, you'll want to configure docker container log rotation. This is important, as without log rotation, each container's log will grow in size until it consumes all the disk space available to /var/lib/docker/containers.

To configure docker log rotation, follow the instructions located here: https://success.docker.com/article/how-to-setup-log-rotation-post-installation

It should be noted that on your system the file /etc/docker/daemon.json will likely not exist. Just create a new file at that path and proceed with the instructions.

Blacklist RTL-SDR Kernel Modules

You can skip this step if you're not using an RTLSDR radio (ie: bladeRF).

Before we can plug in our RTLSDR dongle, we need to blacklist the kernel modules for the RTL-SDR USB device from being loaded into the host's kernel and taking ownership of the device.

To do this, create a file /etc/modprobe.d/blacklist-rtl2832.conf containing the following:

blacklist rtl2832
blacklist dvb_usb_rtl28xxu
blacklist rtl2832_sdr

Failure to do this will result in the error below being spammed to the readsb container log.

usb_claim_interface error -6
rtlsdr: error opening the RTLSDR device: Device or resource busy

If you get the error above even after blacklisting the kernel modules as outlined above, the modules may still be loaded. You can unload them by running the following commands:

sudo rmmod rtl2832_sdr
sudo rmmod dvb_usb_rtl28xxu
sudo rmmod rtl2832

Deploying readsb

Readsb (Portmanteau of Read ADSB) is a Mode-S/ADSB/TIS decoder for RTLSDR, BladeRF, Modes-Beast and GNS5894 devices. I've created a docker image mikenye/readsb that contains readsb and all of its required prerequisites and libraries. This is the foundation of our ADSB environment, as it receives and decodes the ADSB data, making it available for all other applications.

To do this, perform the following:

Connect SDR hardware

Plug in your RTLSDR dongle, bladeRF or whatever SDR you're using.

Run the command lsusb and find your radio. It'll look something like this:

For RTL-SDR:

Bus 001 Device 004: ID 0bda:2832 Realtek Semiconductor Corp. RTL2832U DVB-T

For bladeRF:

Bus 001 Device 004: ID 1d50:6066 OpenMoko, Inc. Nuand BladeRF

Take note of the bus number, and device number. In each output above, its 001 and 004 respectively.

Create a directory to host our docker-compose.yml file

I'm using /opt/adsb.

mkdir -p /opt/adsb
cd /opt/adsb

Create docker-compose.yml file

In your favourite text editor, create a file named docker-compose.yml.

Place the following text into it:

version: '2.0'

networks:
  adsbnet:

services:

  readsb:
    image: mikenye/readsb:latest
    tty: true
    container_name: readsb
    restart: always
    devices:
      - /dev/bus/usb/BUSNUMBER/DEVICENUMBER:/dev/bus/usb/BUSNUMBER/DEVICENUMBER
    ports:
      - 8080:8080
      - 30005:30005
    networks:
      - adsbnet
    environment:
      - TZ=YOURTIMEZONE
    command:
      - --dcfilter
      - --device-type=rtlsdr
      - --json-location-accuracy=2
      - --lat=YOURLATITUDE
      - --lon=YOURLONGITUDE
      - --modeac
      - --ppm=0
      - --net
      - --stats-every=3600
      - --quiet
      - --write-json=/run/readsb

Note: if you're using bladeRF, you'll need to change --device-type=rtlsdr to --device-type=bladerf.

Be sure to change the following:

  • Replace BUSNUMBER with the bus number of your radio, from the lsusb output from earlier
  • Replace DEVICENUMBER with the device number of your radio, from the lsusb output from earlier
  • Replace YOURTIMEZONE with your local timezone in "TZ database name" format (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)

So, assuming:

  • Output from lsusb shows the RTLSDR as Bus 001 Device 004: ID 0bda:2832 Realtek Semiconductor Corp. RTL2832U DVB-T, BUSNUMBER would be 001 and DEVICENUMBER would be 004.
  • Our latitude is -33.33333 and longitude is 111.11111
  • Our timezone is Australia/Perth

...then our docker-compose.yml file would be as follows:

version: '2.0'

networks:
  adsbnet:

services:

  readsb:
    image: mikenye/readsb:latest
    tty: true
    container_name: readsb
    restart: always
    devices:
      - /dev/bus/usb/001/004:/dev/bus/usb/001/004
    ports:
      - 8080:8080
      - 30005:30005
    networks:
      - adsbnet
    environment:
      - TZ=Australia/Perth
    command:
      - --dcfilter
      - --device-type=rtlsdr
      - --json-location-accuracy=2
      - --lat=-33.33333
      - --lon=111.11111
      - --modeac
      - --ppm=0
      - --net
      - --stats-every=3600
      - --quiet
      - --write-json=/run/readsb

Note: if you're using bladeRF, you'll need to change --device-type=rtlsdr to --device-type=bladerf.

To explain what's going on in this file:

  • We're creating a new docker network called adsbnet, which will be used to allow other containers to communicate with this container.
  • We're creating a container called readsb, from the image mikenye/readsb:latest.
  • We're passing through the RTLSDR (USB device 004 on bus 001) to the container.
  • We're passing through TCP port 8080 on the host to port 8080 on the container, so we can view the web interface at http://dockerhost:8080/.
  • We're passing through TCP port 30005 on the host to port 30005 on the container, so other applications can receive the ADSB data generated by readsb.
  • We're connecting the container to the docker network adsbnet.
  • We're passing an environment variable to the container:
    • TZ=Australia/Perth to tell the container our timezone.
  • We're passing several command line arguments to readsb, most notably:
    • --device-type=rtlsdr to inform readsb to look for an RTLSDR device. If you use a bladeRF device, you should change this to --device-type=bladerf.
    • --lat=-33.33333 to inform readsb of the antenna's latitude
    • --lon=111.11111 to inform readsb of the antenna's longitude
    • --write-json=/run/readsb to inform readsb to output JSON data to /run/readsb (for the web interface and container healthcheck to function correctly). If you don't plan on using the readsb web interface (and will instead use tar1090 or another visualisation (see below), then feel free to omit this line)

If you're using bladeRF, you may need some additional settings depending on your hardware, eg:

      - --device-type=bladerf
      - --bladerf-fpga=/usr/share/readsb/bladerf/decimate8-x40.rbf
      - --bladerf-decimation=8
      - --bladerf-bandwidth=14000000

Once the file is created, issue the command docker-compose up -d to bring up the ADSB environment. You should see the following output:

Creating network “adsb_adsbnet” with the default driver
Creating readsb

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. At this stage, the logs will be fairly unexciting and look like this:

readsb   | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
readsb   | [s6-init] ensuring user provided files have correct perms...exited 0.
readsb   | [fix-attrs.d] applying ownership & permissions fixes...
readsb   | [fix-attrs.d] done.
readsb   | [cont-init.d] executing container initialization scripts...
readsb   | [cont-init.d] done.
readsb   | [services.d] starting services
readsb   | [services.d] done.
readsb   | Wed Feb 19 07:23:48 2020 UTC Mictronics v3.8.1 starting up.
readsb   | rtlsdr: using device #0: Generic RTL2832U (Realtek, RTL2832U, SN 00001000)
readsb   | Found Rafael Micro R820T tuner
readsb   | Allocating 16 zero-copy buffers
readsb   | Failed to allocate zero-copy buffer for transfer 0
readsb   | Falling back to buffers in userspace

We can see our container running with the command docker ps, and see the adsb_adsbnet network with the command docker network ls.

Viewing live data from readsb

To see the data being received and decoded by our new container, run the command docker exec -it readsb viewadsb. This should display a real-time departure-lounge-style screen showing all the aircraft being tracked, for example:

 Hex    Mode  Sqwk  Flight   Alt    Spd  Hdg    Lat      Long   RSSI  Msgs  Ti -
────────────────────────────────────────────────────────────────────────────────
 7CF86F S     2061  BFRT22   10025  219  286  -31.871  116.586 -28.6    14  1
 7C79CA S     1200  YCC       2975  126  152  -32.490  115.887 -28.2    68  0
 7C79CB S     3000  YCD       1525  118  352  -32.221  115.948 -25.6   269  0
 7C79D1 S     1200  YCJ       3575  113  185  -32.375  115.837 -29.2   289  1
 7C79DB S     3000  YCT       1375  119  358  -32.176  115.940 -25.1   126  0
 7C79DC S     1200  YCU       3000   96  229  -32.437  115.929 -28.5   260  5
 7CF9E1 S     2055            1250  178  084                   -29.8    18  0
 7C822A S     3730  ZZW       1500                             -23.5   258  0
 7C7A3F S     1273  VOZ1485    grnd   0                        -25.4    11  3
 7C7A6E S     1200  YGW       2575   99  191  -32.296  115.813 -20.3   522  0
 7C1ABD S     4265  UTY6071  33125  398  197  -30.535  116.638 -23.6   363  0
 7C42D2 S     3664  NWK1663    grnd  59  239  -31.936  115.968 -21.6   258 12
 7C1B35 S                      grnd   9  281                   -28.3     4 15
 7C1B3C S     4306  VOZ9224  34000  405  192  -30.804  116.239 -22.5   150  0
 7C1C68 S     3646  FWA       5000  191  253  -31.803  116.299 -25.4   396  0
 7C6CA2 S     3760  NWK1885   7825  239  193  -31.609  116.244 -13.1   509  0
 7C6CA4 S     4035  NWK2873   3075  141  239  -31.846  116.143 -20.8   566  0
 7C4518 S     1464  QJE1928  13225  437  037  -31.840  116.316 -10.7   516  0
 7C0DAB S     3000  CZH        800   71  303  -32.085  115.923 -18.3   273  0
 7C6DB5 S                    36975                             -31.8    11 32
 7C3F19 S     4063  MQZ       1325  105  240  -31.898  116.043 -16.8   601  0
 7C7F72 S                                                      -31.5     7 37
 7C7796 S     4310  UTY734   34000  381  181  -30.327  116.639 -25.8    82  0
 7CF7C4 S           PHRX1A                                     -20.3    22  1
 7CF7C5 S           PHRX1B                                     -21.6    15  9
 7CF7C6 S           PHRX2A                                     -21.3    15  1
 7CF7C7 S           PHRX2B                                     -28.1     3  2
 7C2FD6 S     4223  NWK2878   4025  212  176  -32.006  115.948  -2.1   831  0

Press CTRL-C to escape this screen.

You should also be able to point your web browser at http://dockerhost:8080/ to view the web interface. At the time of writing this readme (readsb v3.8.3), the webapp is still being developed. I was able to get a usable interface with Firefox.

If you need to bring the environment down (for example, if you need to unplug the RTLSDR USB dongle for maintenance), you can issue the command docker-compose down from the directory containing your docker-compose.yml file.

Feeding adsbexchange.com

ADSBexchange.com is a co-op of ADS-B/Mode S/MLAT feeders from around the world, and the world’s largest source of unfiltered flight data.

Generating a UUID for your receiver

In order to generate a site UUID, initially run the container with the following command:

docker run --rm -it --entrypoint uuidgen mikenye/adsbexchange -t

Take note of the UUID returned.

Deploying adsbexchange.com feeder container

Open the docker-compose.yml file that was created when deploying readsb.

Append the following lines to the end of the file:

  adsbx:
    image: mikenye/adsbexchange:latest
    tty: true
    container_name: adsbx
    restart: always
    environment:
      - BEASTHOST=readsb
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
      - ALT=YOURALTITUDE
      - SITENAME=YOURSITENAME
      - UUID=YOURUUID
      - TZ=YOURTIMEZONE
    networks:
      - adsbnet

Be sure to change the following:

  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)
  • Replace YOURALTITUDE with the altitude above sea level of your antenna. If specified in feet, add the suffix ft. If specified in metres, add the suffix m. Note: negative altitudes MUST be in meters, with no suffix.
  • Replace YOURSITENAME with a unique name for your receiver, using only the characters "A-Z", "a-z", (-) and (_)
  • Replace YOURUUID with the UUID that was generated in the previous step
  • Replace YOURTIMEZONE with your local timezone in "TZ database name" format (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).

So, assuming:

  • Our latitude is -33.33333 and longitude is 111.11111
  • Our altitude is 95m
  • Our site name is My_Cool_ADSB_Receiver
  • Our generated UUID is 4e8413e6-52eb-11ea-8681-1c1b0d925d3g
  • Our timezone is Australia/Perth

...then our docker-compose.yml file would be appended with the following:

  adsbx:
    image: mikenye/adsbexchange:latest
    tty: true
    container_name: adsbx
    restart: always
    environment:
      - BEASTHOST=readsb
      - LAT=-33.33333
      - LONG=111.11111
      - ALT=95m
      - SITENAME=My_Cool_ADSB_Receiver
      - UUID=4e8413e6-52eb-11ea-8681-1c1b0d925d3g
      - TZ=Australia/Perth
    networks:
      - adsbnet

To explain what's going on in this addition:

  • We're creating a container called adsbx, from the image mikenye/adsbexchange:latest.
  • We're connecting the container to the docker network adsbnet.
  • We're passing several environment variables to the container:
    • BEASTHOST=readsb to inform the feeder to get its ADSB data from the container readsb over our private adsbnet network.
    • LAT=-33.33333 to inform the feeder of the antenna's latitude
    • LONG=111.11111 to inform the feeder of the antenna's longitude
    • ALT=95m to inform the feeder of the antenna's altitude
    • SITENAME=My_Cool_ADSB_Receiver to inform the feeder of our site name
    • UUID=4e8413e6-52eb-11ea-8681-1c1b0d925d3g to inform the feeder of our UUID
    • TZ=Australia/Perth to inform the feeder of our local timezone.

Once the file is created, issue the command docker-compose up -d to bring up the ADSB environment. You should see the following output:

readsb is up-to-date
Creating adsbx

You can see from the output above that the readsb container was left alone (as the configuration for this container did not change), and a new container adsbx was created.

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. We should now see logs from our newly created adsbx container:

adsbx   | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
adsbx   | [s6-init] ensuring user provided files have correct perms...exited 0.
adsbx   | [fix-attrs.d] applying ownership & permissions fixes...
adsbx   | [fix-attrs.d] done.
adsbx   | [cont-init.d] executing container initialization scripts...
adsbx   | [cont-init.d] 01-adsbexchange: executing...
adsbx   | Statistics will be available at: https://www.adsbexchange.com/api/feeders/?feed=4e8413e6-52eb-11ea-8681-1c1b0d925d3g
adsbx   | [cont-init.d] 01-adsbexchange: exited 0.
adsbx   | [cont-init.d] done.
adsbx   | [services.d] starting services
adsbx   | [services.d] done.
adsbx   | [adsbexchange-stats] Using UUID 4e8413e6-52eb-11ea-8681-1c1b0d925d3g for stats uploads...
adsbx   | [adsbexchange-stats] Using JSON directory /run/readsb for source data...
adsbx   | [adsbexchange-feed] Wed Feb 19 15:47:22 2020 AWST Mictronics v3.8.1 starting up.
adsbx   | [adsbexchange-feed] Net-only mode, no SDR device or file open.
adsbx   | [mlat-client] Wed Feb 19 15:47:22 2020 mlat-client 0.2.10 starting up
adsbx   | [adsbexchange-feed] Beast TCP input: Connection established: readsb (192.168.213.98) port 30005
adsbx   | [mlat-client] Wed Feb 19 15:47:23 2020 Connected to multilateration server at feed.adsbexchange.com:31090, handshaking
adsbx   | [adsbexchange-feed] BeastReduce TCP output: Connection established: feed.adsbexchange.com (167.114.60.74) port 30005
adsbx   | [mlat-client] Wed Feb 19 15:47:23 2020 Beast-format results connection with 192.168.213.98:30005: connection established
adsbx   | [mlat-client] Wed Feb 19 15:47:38 2020 Server says:
adsbx   | [mlat-client]
adsbx   | [mlat-client]     In-development v2 server. Expect odd behaviour.
adsbx   | [mlat-client]
adsbx   | [mlat-client]     The multilateration server source code is available under
adsbx   | [mlat-client]     the terms of the Affero GPL (v3 or later). You may obtain
adsbx   | [mlat-client]     a copy of this server’s source code at the following
adsbx   | [mlat-client]     location: https://github.com/adsbexchange/mlat-server
adsbx   | [mlat-client]
adsbx   | [mlat-client] Wed Feb 19 15:47:38 2020 Handshake complete.
adsbx   | [mlat-client] Wed Feb 19 15:47:38 2020  Compression:    zlib2
adsbx   | [mlat-client] Wed Feb 19 15:47:38 2020  UDP transport:   disabled
adsbx   | [mlat-client] Wed Feb 19 15:47:38 2020  Split sync:    disabled
adsbx   | [mlat-client] Wed Feb 19 15:47:38 2020 Input connected to readsb:30005
adsbx   | [mlat-client] Wed Feb 19 15:47:38 2020 Input format changed to BEAST, 12MHz clock

After a few minutes, point your browser at https://adsbexchange.com/myip/. You should see two green smiley faces indicating that you are successfully sending data.

Deploying tar1090 for improved visualisation

tar1090 is an excellent tool by wiedehopf that improves on the dump1090-fa interface (used by PiAware's "SkyAware").

This is my personal preference for displaying real-time ADS-B information.

Deploying tar1090 container

Open the docker-compose.yml file that was created when deploying readsb.

Append the following lines to the end of the file:

  tar1090:
    image: mikenye/tar1090:latest
    tty: true
    container_name: tar1090
    restart: always
    environment:
      - TZ=YOURTIMEZONE
      - BEASTHOST=readsb
      - MLATHOST=adsbx
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
    networks:
      - adsbnet
    ports:
      - 8078:80

Be sure to change the following:

So, assuming:

  • Our timezone is Australia/Perth

...then our docker-compose.yml file would be appended with the following:

  tar1090:
    image: mikenye/tar1090:latest
    tty: true
    container_name: tar1090
    restart: always
    environment:
      - TZ=Australia/Perth
      - BEASTHOST=readsb
      - MLATHOST=adsbx
      - LAT=-33.33333
      - LONG=111.11111
    networks:
      - adsbnet
    ports:
      - 8078:80

To explain what's going on in this file:

  • We're creating a container called tar1090, from the image mikenye/tar1090:latest.
  • We're passing through TCP port 8078 on the host to port 80 on the container, so we can get to the tar1090 web interface at http://dockerhost:8078/.
  • We're connecting the container to the docker network adsbnet.
  • We're passing several environment variables to the container:
    • TZ=Australia/Perth to tell the container our timezone.
    • LAT and LONG to tell the container our home position.
    • BEASTHOST=readsb to inform graphs1090 to get its ADSB data from the container readsb over our private adsbnet network.
    • MLATHOST=adsbx to inform graphs1090 to get its MLAT data from the container adsbx over our private adsbnet network.

Once the file is created, issue the command docker-compose up -d to bring up the new tar1090 container. You should see the following output:

readsb is up-to-date
adsbx is up-to-date
graphs1090 is up-to-date
piaware is up-to-date
fr24 is up-to-date
Creating tar1090

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. At this stage, the logs will be fairly unexciting and look like this:

tar1090           | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
tar1090           | [s6-init] ensuring user provided files have correct perms...exited 0.
tar1090           | [fix-attrs.d] applying ownership & permissions fixes...
tar1090           | [fix-attrs.d] done.
tar1090           | [cont-init.d] executing container initialization scripts...
tar1090           | [cont-init.d] 01-tar1090-update: executing...
tar1090           | tar1090 database version: fed120f
tar1090           | tar1090 version: e4f6b2b
tar1090           | [cont-init.d] 01-tar1090-update: exited 0.
tar1090           | [cont-init.d] 02-tar1090-copy: executing...
tar1090           | [cont-init.d] 02-tar1090-copy: exited 0.
tar1090           | [cont-init.d] 03-tar1090-configure: executing...
tar1090           | [cont-init.d] 03-tar1090-configure: exited 0.
tar1090           | [cont-init.d] 04-tar1090-gzip: executing...
tar1090           | [cont-init.d] 04-tar1090-gzip: exited 0.
tar1090           | [cont-init.d] done.
tar1090           | [services.d] starting services
tar1090           | [readsb] Tue Mar 31 22:35:13 2020 AWST  Mictronics v3.8.2 starting up.
tar1090           | [readsb] Net-only mode, no SDR device or file open.
tar1090           | [services.d] done.
tar1090           | [readsb] Beast TCP input: Connection established: readsb (172.22.7.8) port 30005
tar1090           | [readsb] Beast TCP input: Connection established: adsbx (172.22.7.9) port 30005

We can see our container running with the command docker ps.

Once running, you can visit http://dockerhost:8078/ to access the tar1090 web interface.

If you need to bring the environment down, you can issue the command docker-compose down from the directory containing your docker-compose.yml file.

Deploying graphs1090 for visualising ADSB reception stats

graphs1090 is an excellent tool by wiedehopf that generates graphs for dump1090/readsb and their variants.

This container receives:

  • Beast data from a provider such as readsb
  • MLAT data from a provider such as mlat-client, which is present in the ADSBExchange container we just created

This can help highlight improvement or deterioration in reception performance when adjusting receiver settings (such as gain), or changing antennas.

Deploying graphs1090 container

Open the docker-compose.yml file that was created when deploying readsb.

Add the following lines below the networks: section, and above the services: section:

volumes:
  graphs1090_rrd:

...so the beginning of the file looks like this:

version: '2.0'

networks:
  adsbnet:

volumes:
  graphs1090_rrd:

services:

Then, append the following lines to the end of the file:

  graphs1090:
    image: mikenye/graphs1090:latest
    tty: true
    container_name: graphs1090
    restart: always
    volumes:
      - graphs1090_rrd:/var/lib/collectd/rrd
    ports:
      - 8079:80
    environment:
      - BEASTHOST=readsb
      - MLATHOST=adsbx
      - TZ=YOURTIMEZONE
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
    networks:
      - adsbnet

Be sure to change the following:

So, assuming:

  • Our latitude is -33.33333 and longitude is 111.11111
  • Our timezone is Australia/Perth

...then our docker-compose.yml file would be appended with the following:

  graphs1090:
    image: mikenye/graphs1090:latest
    tty: true
    container_name: graphs1090
    restart: always
    volumes:
      - graphs1090_rrd:/var/lib/collectd/rrd
    ports:
      - 8079:80
    environment:
      - BEASTHOST=readsb
      - MLATHOST=adsbx
      - TZ=Australia/Perth
      - LAT=-33.33333
      - LONG=111.11111
    networks:
      - adsbnet

To explain what's going on in this addition:

  • We're creating a container called graphs1090, from the image mikenye/graphs1090:latest.
  • We're connecting the container to the docker network adsbnet.
  • We're providing persistent storage in the form of a docker volume named graphs1090_rrd, where the round robin databases containing historical statistics will be stored. By providing persistent storage, our statistics will not be lost when the container is recreated by docker-compose.
  • We're passing several environment variables to the container:
    • BEASTHOST=readsb to inform graphs1090 to get its ADSB data from the container readsb over our private adsbnet network.
    • MLATHOST=adsbx to inform graphs1090 to get its MLAT data from the container adsbx over our private adsbnet network.
    • LAT=-33.33333 to inform graphs1090 of the antenna's latitude.
    • LONG=111.11111 to inform graphs1090 of the antenna's longitude.
    • TZ=Australia/Perth so that the graphs generated are in our local timezone.

Once the file is created, issue the command docker-compose up -d to bring up the ADSB environment. You should see the following output:

readsb is up-to-date
adsbx is up-to-date
Creating graphs1090

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. At this stage, the logs will be fairly unexciting and look like this:

graphs1090        | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
graphs1090        | [s6-init] ensuring user provided files have correct perms...exited 0.
graphs1090        | [fix-attrs.d] applying ownership & permissions fixes...
graphs1090        | [fix-attrs.d] done.
graphs1090        | [cont-init.d] executing container initialization scripts...
graphs1090        | [cont-init.d] 01-sanitycheck: executing...
graphs1090        | [cont-init.d] 01-sanitycheck: exited 0.
graphs1090        | [cont-init.d] done.
graphs1090        | [services.d] starting services
graphs1090        | [graphs1090] Generating all graphs
graphs1090        | collectd[226]: plugin_load: plugin "syslog" successfully loaded.
graphs1090        | [services.d] done.
graphs1090        | [readsb] Tue May  5 15:35:48 2020 AWST  Mictronics v3.8.3 starting up.
graphs1090        | [readsb] Net-only mode, no SDR device or file open.
graphs1090        | collectd[226]: plugin_load: plugin "rrdtool" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "table" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "interface" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "cpu" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "aggregation" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "match_regex" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "df" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "disk" successfully loaded.
graphs1090        | collectd[226]: plugin_load: plugin "python" successfully loaded.
graphs1090        | [readsb] Beast TCP input: Connection established: readsb (192.168.176.8) port 30005
graphs1090        | [readsb] Beast TCP input: Connection established: adsbx (192.168.176.6) port 30105
graphs1090        | collectd[226]: Initialization complete, entering read-loop.

We can see our container running with the command docker ps.

Once running, you can visit http://dockerhost:8079/ to access the graphs1090 graphs.

If you need to bring the environment down, you can issue the command docker-compose down from the directory containing your docker-compose.yml file.

Feeding FlightAware

PiAware is a FlightAware client program to securely transmit ADS-B and Mode S data to the commercial entity FlightAware.

In exchange for your data, FlightAware will give you an Enterprise Membership. If this is something of interest, you may wish to feed your data to them.

The docker image mikenye/piaware contains piaware and all of its required prerequisites and libraries. This can run standalone (without the readsb container), however for flexibility it is recommended to run with readsb.

Already running PiAware

You'll need your feeder-id from your existing feeder.

To get your feeder-id, log onto your feeder and issue the command:

piaware-config -show feeder-id

New to PiAware

If you're already running PiAware and you've followed the steps in the previous command, you can skip this section.

You'll need a feeder-id. To get one, you can temporarily run the container, to allow it to communicate with the FlightAware servers and get a new feeder ID.

Run the command:

docker pull mikenye/piaware:latest
timeout 60 docker run --rm -e LAT=YOURLATITUDE -e LONG=YOURLONGITUDE mikenye/piaware:latest | grep "my feeder ID"

Be sure to change the following:

  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)

The command will run the container for 30 seconds, which should be ample time for the container to receive a feeder-id.

For example:

$ timeout 30 docker run --rm -e LAT=-33.33333 -e LONG=111.11111 mikenye/piaware:latest | grep "my feeder ID"
Set allow-mlat to yes in /etc/piaware.conf:1
Set allow-modeac to yes in /etc/piaware.conf:2
Set allow-auto-updates to no in /etc/piaware.conf:3
Set allow-manual-updates to no in /etc/piaware.conf:4
2020-03-06 06:16:11.860212500  [piaware] my feeder ID is acbf1f88-09a4-3a47-a4a0-10ae138d0c1g
write /dev/stdout: broken pipe
Terminated

As you can see from the output above, the feeder-id given to us from FlightAware is acbf1f88-09a4-3a47-a4a0-10ae138d0c1g.

You'll now want to "claim" this feeder.

To do this, go to: https://flightaware.com/adsb/piaware/claim and follow the instructions there.

Deploying PiAware feeder container

Open the docker-compose.yml file that was created when deploying readsb.

Append the following lines to the end of the file:

  piaware:
    image: mikenye/piaware:latest
    tty: true
    container_name: piaware
    restart: always
    ports:
      - 8081:8080
    networks:
      - adsbnet
    environment:
      - TZ=YOURTIMEZONE
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
      - FEEDER_ID=YOURFEEDERID
      - BEASTHOST=readsb

Be sure to change the following:

  • Replace YOURTIMEZONE with your local timezone in "TZ database name" format (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)
  • Replace YOURFEEDERID with the feeder-id from your original receiver or the one you generated in the previous step.

So, assuming:

  • Our latitude is -33.33333 and longitude is 111.11111
  • Our timezone is Australia/Perth
  • Our feeder ID is acbf1f88-09a4-3a47-a4a0-10ae138d0c1g

...then our docker-compose.yml file would be appended with the following:

  piaware:
    image: mikenye/piaware:latest
    tty: true
    container_name: piaware
    restart: always
    ports:
      - 8081:8080
    networks:
      - adsbnet
    environment:
      - TZ=Australia/Perth
      - LAT=-33.33333
      - LONG=111.11111
      - FEEDER_ID=acbf1f88-09a4-3a47-a4a0-10ae138d0c1g
      - BEASTHOST=readsb

To explain what's going on in this file:

  • We're creating a container called readsb, from the image mikenye/readsb:latest.
  • We're passing through TCP port 8081 on the host to port 8080 on the container, so we can view SkyAware at http://dockerhost:8081/.
  • We're connecting the container to the docker network adsbnet.
  • We're passing several environment variables to the container:
    • TZ=Australia/Perth to tell the container our timezone.
    • BEASTHOST=readsb to inform the feeder to get its ADSB data from the container readsb over our private adsbnet network.
    • LAT=-33.33333 to inform the feeder of the antenna's latitude
    • LONG=111.11111 to inform the feeder of the antenna's longitude
    • FEEDER_ID=acbf1f88-09a4-3a47-a4a0-10ae138d0c1g to identify ourself to FlightAware

Once the file is created, issue the command docker-compose up -d to bring up the new piaware container. You should see the following output:

readsb is up-to-date
adsbx is up-to-date
graphs1090 is up-to-date
Creating piaware

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. At this stage, the logs will be fairly unexciting and look like this:

piaware         | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
piaware         | [s6-init] ensuring user provided files have correct perms...exited 0.
piaware         | [fix-attrs.d] applying ownership & permissions fixes...
piaware         | [fix-attrs.d] done.
piaware         | [cont-init.d] executing container initialization scripts...
piaware         | [cont-init.d] 01-piaware: executing...
piaware         | Set feeder-id to acbf1f88-09a4-3a47-a4a0-10ae138d0c1g in /etc/piaware.conf:1
piaware         | Set allow-mlat to yes in /etc/piaware.conf:2
piaware         | Set allow-modeac to yes in /etc/piaware.conf:3
piaware         | Set allow-auto-updates to no in /etc/piaware.conf:4
piaware         | Set allow-manual-updates to no in /etc/piaware.conf:5
piaware         | [cont-init.d] 01-piaware: exited 0.
piaware         | [cont-init.d] done.
piaware         | [services.d] starting services
piaware         | [beastrelay] 2020/03/06 14:01:29 socat[267] N listening on AF=2 0.0.0.0:30005
piaware         | [services.d] done.
piaware         | 2020-03-06 14:01:29.742018500  [httpd] 2020-03-06 14:01:29: (server.c.1521) server started (lighttpd/1.4.54)
piaware         | 2020-03-06 14:01:29.828330500  [dump1090-fa] Fri Mar  6 14:01:29 2020 AWST  dump1090-fa  starting up.
piaware         | 2020-03-06 14:01:29.830284500  [dump1090-fa] Net-only mode, no SDR device or file open.
piaware         | 2020-03-06 14:01:29.835375500  [piaware] ****************************************************
piaware         | 2020-03-06 14:01:29.835417500  [piaware] piaware version 3.8.0 is running, process ID 273
piaware         | 2020-03-06 14:01:29.836659500  [piaware] your system info is: Linux ee1f452gf232 4.4.0-174-generic #204-Ubuntu SMP Wed Jan 29 06:41:01 UTC 2020 x86_64 Linux
piaware         | 2020-03-06 14:01:31.337622500  [piaware] Connecting to FlightAware adept server at piaware.flightaware.com/1200
piaware         | 2020-03-06 14:01:31.588615500  [piaware] Connection with adept server at piaware.flightaware.com/1200 established
piaware         | 2020-03-06 14:01:32.119913500  [piaware] TLS handshake with adept server at piaware.flightaware.com/1200 completed
piaware         | 2020-03-06 14:01:32.161723500  [piaware] FlightAware server certificate validated
piaware         | 2020-03-06 14:01:32.161732500  [piaware] encrypted session established with FlightAware
piaware         | 2020-03-06 14:01:32.861649500  [piaware] ADS-B data program 'socat' is listening on port 30005, so far so good
piaware         | 2020-03-06 14:01:32.869657500  [piaware] Starting faup1090: /usr/lib/piaware/helpers/faup1090 --net-bo-ipaddr localhost --net-bo-port 30005 --stdout
piaware         | 2020-03-06 14:01:32.873773500  [piaware] Started faup1090 (pid 298) to connect to socat
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[267] N accepting connection from AF=2 127.0.0.1:54032 on AF=2 127.0.0.1:30005
piaware         | 2020-03-06 14:01:32.875876500  [piaware] UAT support disabled by local configuration setting: uat-receiver-type
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N opening connection to AF=2 172.99.7.4:30005
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N successfully connected from local address AF=2 172.99.7.3:56186
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N starting data transfer loop with FDs [6,6] and [5,5]
piaware         | 2020-03-06 14:01:32.919203500  [piaware] adept reported location: -33.33333, 111.11111, 90ft AMSL
piaware         | 2020-03-06 14:01:32.921957500  [piaware] Receiver location changed, restarting dump1090 and skyaware978
piaware         | 2020-03-06 14:01:32.922717500  [piaware] attempting to restart dump1090..
piaware         | 2020-03-06 14:01:32.927936500  [piaware] attempting to restart dump1090 using '/etc/init.d/dump1090 restart < /dev/null &'...
piaware         | 2020-03-06 14:01:32.932117500  [piaware] dump1090 restart appears to have been successful
piaware         | 2020-03-06 14:01:32.932906500  [piaware] attempting to restart skyaware978..
piaware         | 2020-03-06 14:01:32.933667500  [piaware] can't restart skyaware978, no services that look like skyaware978 found
piaware         | 2020-03-06 14:01:32.934225500  [piaware] Restarting faup1090
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] W read(6, 0x5586c963d020, 8192): Connection reset by peer
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N socket 1 to socket 2 is in error
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N socket 1 (fd 6) is at EOF
piaware         | 2020-03-06 14:01:32.935602500  [piaware] faup1090 exited with SIG SIGHUP
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N socket 1 (fd 6) is at EOF
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N socket 2 (fd 5) is at EOF2020-03-06 14:01:32.936314500  [piaware] will reconnect to socat in 5 seconds
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[299] N exiting with status 0
piaware         | [beastrelay] 2020/03/06 14:01:32 socat[267] N childdied(): handling signal 17
piaware         | 2020-03-06 14:01:32.937608500  [dump1090-fa] Fri Mar  6 14:01:32 2020 AWST  Caught SIGTERM, shutting down..
piaware         | 2020-03-06 14:01:32.937631500  [dump1090-fa]
piaware         | 2020-03-06 14:01:32.937643500  [dump1090-fa] Fri Mar  6 14:01:32 2020 AWST  Normal exit.
piaware         | 2020-03-06 14:01:32.938035500  [piaware] logged in to FlightAware as user mikenye
piaware         | 2020-03-06 14:01:32.938810500  [piaware] my feeder ID is acbf1f88-09a4-3a47-a4a0-10ae138d0c1g

We can see our container running with the command docker ps.

Once running, you can visit http://dockerhost:8081/ to access PiAware's "SkyAware". You can also log onto FlightAware's website and click on the "My ADSB" link at the top of the page, and see your statistics, configure your location, configure your altitude, etc etc.

If you need to bring the environment down, you can issue the command docker-compose down from the directory containing your docker-compose.yml file.

Feeding FlightRadar24

fr24feed is a FlightRadar24 client program to securely transmit ADS-B and Mode S data to the commercial entity FlightRadar24.

In exchange for your data, FlightAware will give you a Business Plan. If this is something of interest, you may wish to feed your data to them.

I've created a docker image mikenye/fr24feed that contains fr24feed and all of its required prerequisites and libraries. This needs to run in conjunction with readsb (or another Beast provider).

Already running fr24feed

You'll need your fr24key from your existing feeder.

To get your fr24key, log onto your feeder and issue the command:

cat /etc/fr24feed.ini | grep fr24key

New to fr24feed

If you're already running fr24feed and you've followed the steps in the previous command, you can skip this section.

First-time users should obtain a FlighRadar24 sharing key (a fr24key). To get one, you can run through the signup process. This will ask a series of questions allowing you to sign up with FlightRadar24 and get a fr24key.

Run the command:

docker run --rm -it --entrypoint fr24feed mikenye/fr24feed --signup

This will take you through the signup process. At the end of the signup process, you'll be presented with:

Congratulations! You are now registered and ready to share ADS-B data with Flightradar24.
+ Your sharing key (xxxxxxxxxxxx) has been configured and emailed to you for backup purposes.
+ Your radar id is X-XXXXXXX, please include it in all email communication with us.

Take a note of the sharing key, as you'll need it when launching the container.

Deploying fr24feed container

Open the docker-compose.yml file that was created when deploying readsb.

Append the following lines to the end of the file:

  fr24:
    image: mikenye/fr24feed:latest
    tty: true
    container_name: fr24
    restart: always
    ports:
      - 8754:8754
    networks:
      - adsbnet
    environment:
      - TZ=YOURTIMEZONE
      - MLAT=yes
      - FR24KEY=YOURFR24KEY
      - BEASTHOST=readsb

Be sure to change the following:

So, assuming:

  • Our timezone is Australia/Perth
  • Our fr24key is 10ae138d0c1g

...then our docker-compose.yml file would be appended with the following:

  fr24:
    image: mikenye/fr24feed:latest
    tty: true
    container_name: fr24
    restart: always
    ports:
      - 8754:8754
    networks:
      - adsbnet
    environment:
      - TZ=Australia/Perth
      - MLAT=yes
      - FR24KEY=10ae138d0c1g
      - BEASTHOST=readsb

To explain what's going on in this file:

  • We're creating a container called fr24, from the image mikenye/fr24feed:latest.
  • We're passing through TCP port 8754 on the host to port 8754 on the container, so we can get to the fr24feed web interface at http://dockerhost:8754/.
  • We're connecting the container to the docker network adsbnet.
  • We're passing several environment variables to the container:
    • TZ=Australia/Perth to tell the container our timezone.
    • BEASTHOST=readsb to inform the feeder to get its ADSB data from the container readsb over our private adsbnet network.
    • MLAT=yes to enable multilateration.
    • FR24KEY=10ae138d0c1g sets our fr24key.

Once the file is created, issue the command docker-compose up -d to bring up the new fr24 container. You should see the following output:

readsb is up-to-date
adsbx is up-to-date
graphs1090 is up-to-date
piaware is up-to-date
Creating fr24

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. At this stage, the logs will be fairly unexciting and look like this:

fr24              | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
fr24              | [s6-init] ensuring user provided files have correct perms...exited 0.
fr24              | [fix-attrs.d] applying ownership & permissions fixes...
fr24              | [fix-attrs.d] done.
fr24              | [cont-init.d] executing container initialization scripts...
fr24              | [cont-init.d] 01-fr24feed: executing...
fr24              | [cont-init.d] 01-fr24feed: exited 0.
fr24              | [cont-init.d] done.
fr24              | [services.d] starting services
fr24              | 2020-03-23 16:36:19 | [feed][i]sent 8,6 AC
fr24              | 2020-03-23 16:36:24 | [feed][i]sent 7,7 AC
fr24              | 2020-03-23 16:36:25 | [feed][i]filtering out 9 overlapping AC (saving bandwidth)
fr24              | 2020-03-23 16:36:29 | [main][i]Terminating on user request
fr24              | 2020-03-23 16:36:29 | [main][i]Terminating worker threads
fr24              | 2020-03-23 16:36:30 | [reader][i]Connection terminated
fr24              | 2020-03-23 16:36:30 | [reader][i]Terminating on request
fr24              | 2020-03-23 16:36:31 | [bs][i]Server terminated!
fr24              | 2020-03-23 16:36:31 | [raw][i]Server terminated!
fr24              | 2020-03-23 16:36:33 | [main][i]Forcing process termination
fr24              | [services.d] done.
fr24              | 2020-03-23 16:36:37 | ______  _  _         _      _                    _              _____    ___
fr24              | 2020-03-23 16:36:37 | |  ___|| |(_)       | |    | |                  | |            / __  \  /   |
fr24              | 2020-03-23 16:36:37 | | |_   | | _   __ _ | |__  | |_  _ __  __ _   __| |  __ _  _ __`' / /' / /| |
fr24              | 2020-03-23 16:36:37 | |  _|  | || | / _` || '_ \ | __|| '__|/ _` | / _` | / _` || '__| / /  / /_| |
fr24              | 2020-03-23 16:36:37 | | |    | || || (_| || | | || |_ | |  | (_| || (_| || (_| || |  ./ /___\___  |
fr24              | 2020-03-23 16:36:37 | \_|    |_||_| \__, ||_| |_| \__||_|   \__,_| \__,_| \__,_||_|  \_____/    |_/
fr24              | 2020-03-23 16:36:37 |                __/ |
fr24              | 2020-03-23 16:36:37 |               |___/
fr24              | 2020-03-23 16:36:37 | [main][i]FR24 Feeder/Decoder
fr24              | 2020-03-23 16:36:37 | [main][i]Version: 1.0.25-2/generic
fr24              | 2020-03-23 16:36:37 | [main][i]Built on Mar 11 2020 12:48:08 (FRBACKEND-2065-6d31545.git/Linux/static_amd64)
fr24              | 2020-03-23 16:36:37 | [main][i]Running on: debian10
fr24              | 2020-03-23 16:36:37 | [main][i]Local IP(s): 172.92.4.85
fr24              | 2020-03-23 16:36:37 | [main][i]Copyright 2012-2020 Flightradar24 AB
fr24              | 2020-03-23 16:36:37 | [main][i]https://www.flightradar24.com
fr24              | 2020-03-23 16:36:37 | [main][i]DNS mode: PING
fr24              | 2020-03-23 16:36:37 | [main][i]Automatic updates are DISABLED
fr24              | 2020-03-23 16:36:37 | info | [httpd]Server started, listening on 0.0.0.0:8754
fr24              | 2020-03-23 16:36:37 | [i]PacketSenderConfiguration::fetch_config(): Yoda configuration for this receiver is disabled
fr24              | 2020-03-23 16:36:37 | [d]TLSConnection::ctor(): Enable verify_peer in production code!
fr24              | 2020-03-23 16:36:37 | [main][i]Reader thread started
fr24              | 2020-03-23 16:36:37 | [master][i]Starting processing thread
fr24              | 2020-03-23 16:36:37 | [reader][i]Initializing reader
fr24              | 2020-03-23 16:36:37 | [reader][i]Connecting to unknown receiver via (tcp://readsb:30005)
fr24              | 2020-03-23 16:36:37 | [main][i]Socket server started
fr24              | 2020-03-23 16:36:37 | [main][i]MLAT data feed started

We can see our container running with the command docker ps.

Once running, you can visit http://dockerhost:8754/ to access the fr24feed web interface. You can also log onto FlightAware's website and click on the your profile button, and then "My data sharing" link to see your statistics.

If you need to bring the environment down, you can issue the command docker-compose down from the directory containing your docker-compose.yml file.

It is worth noting that fr24feed is extremely noisy when it comes to logging. If you haven't set up Docker log rotation as outlined earlier, consider doing this, lest your /var/lib/docker become full.

Feeding AirNav RadarBox

rbfeeder is a RadarBox client program to transmit ADS-B and Mode S data to the commercial entity RadarBox.

In exchange for your data, RadarBox will give you a Business Plan. If this is something of interest, you may wish to feed your data to them.

Personally, I really like their visualisation. Overlaying the flight data with precipitation and cloud cover look fantastic.

The docker image mikenye/radarbox contains rbfeeder and all of its required prerequisites and libraries. This needs to run in conjunction with readsb (or another Beast provider).

Already running rbfeeder

You'll need your sharing key from your existing feeder.

To get your sharing key, log onto your feeder and issue the command:

rbfeeder --showkey --no-start

New to rbfeeder

If you're already running rbfeeder and you've followed the steps in the previous command, you can skip this section.

You'll need a sharing key. To get one, you can temporarily run the container, to allow it to communicate with the RadarBox servers generate a new sharing key.

Run the command:

timeout 300s docker run \
    --rm \
    -it \
    -e BEASTHOST=YOURBEASTHOST \
    -e LAT=YOURLATITUDE \
    -e LONG=YOURLONGITUDE \
    -e ALT=YOURALTITUDE \
    mikenye/radarbox

Be sure to change the following:

  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)
  • Replace YOURALTITUDE with the altitude of your antenna in metres
  • Replace YOURBEASTHOST with the IP address of your readsb instance (you may need to include --network=<network>, you can find your ADSB network with docker network ls)

The command will run the container for 5 minutes, which should be ample time for the container to receive a sharing key.

For example:

$ timeout 300s docker run --rm -it -e BEASTHOST=192.168.69.35 -e LAT=-31.897798 -e LONG=115.92858 -e ALT=90m mikenye/radarbox
[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] 01-rbfeeder: executing...
WARNING: TZ environment variable not set

WARNING: SHARING_KEY environment variable was not set!
Please make sure you note down the key generated.
Pass the key as environment var SHARING_KEY on next launch!

[cont-init.d] 01-rbfeeder: exited 0.
[cont-init.d] done.
[services.d] starting services
[services.d] done.
[rbfeeder] [2020-04-03 08:57:39]  Starting RBFeeder Version 0.2.6 (build 20180313082038)
[rbfeeder] [2020-04-03 08:57:39]  Using configuration file: /etc/rbfeeder.ini
[rbfeeder] [2020-04-03 08:57:39]  Network-mode enabled.
[rbfeeder] [2020-04-03 08:57:39]                Remote host to fetch data: 172.99.7.4
[rbfeeder] [2020-04-03 08:57:39]                Remote port: 30005
[rbfeeder] [2020-04-03 08:57:39]                Remote protocol: BEAST
[rbfeeder] [2020-04-03 08:57:39]  System: raspberry
[rbfeeder] [2020-04-03 08:57:39]  Start date/time: 2020-04-03 08:57:39
[rbfeeder] [2020-04-03 08:57:39]  Socket for ANRB created. Waiting for connections on port 32088
[rbfeeder] [2020-04-03 08:57:41]  Connection established.
[rbfeeder] [2020-04-03 08:57:41]  Empty sharing key. We will try to create a new one for you!
[rbfeeder] [2020-04-03 08:57:42]  Your new key is g45643ab345af3c5d5g923a99ffc0de9. Please save this key for future use. You will have to know this key to link this receiver to your account in RadarBox24.com. This key is also saved in configuration file (/etc/rbfeeder.ini)

As you can see from the output above, the sharing key given to us from Radarbox is g45643ab345af3c5d5g923a99ffc0de9.

You should now claim your receiver:

  1. Go to https://www.radarbox.com/
  2. Create an account or sign in
  3. Claim your receiver by visiting https://www.radarbox.com/raspberry-pi/claim and following the instructions

Deploying rbfeeder container

Open the docker-compose.yml file that was created when deploying readsb.

Append the following lines to the end of the file:

  rbfeeder:
    image: mikenye/radarbox:latest
    tty: true
    container_name: rbfeeder
    restart: always
    environment:
      - TZ=YOURTIMEZONE
      - BEASTHOST=readsb
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
      - ALT=YOURALTITUDE
      - SHARING_KEY=YOURSHARINGKEY
    networks:
      - adsbnet

Be sure to change the following:

  • Replace YOURTIMEZONE with your local timezone in "TZ database name" format (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)
  • Replace YOURALTITUDE with the altitude of your antenna in metres
  • Replace YOURSHARINGKEY with the fr24key from your original receiver or the one you generated in the previous step.

So, assuming:

  • Our latitude is -33.33333, longitude is 111.11111 and altitude is 90m
  • Our timezone is Australia/Perth
  • Our sharing key is g45643ab345af3c5d5g923a99ffc0de9

...then our docker-compose.yml file would be appended with the following:

  rbfeeder:
    image: mikenye/radarbox:latest
    tty: true
    container_name: rbfeeder
    restart: always
    environment:
      - TZ=Australia/Perth
      - BEASTHOST=readsb
      - LAT=-33.33333
      - LONG=111.11111
      - ALT=90
      - SHARING_KEY=g45643ab345af3c5d5g923a99ffc0de9
    networks:
      - adsbnet

To explain what's going on in this file:

  • We're creating a container called rbfeeder, from the image mikenye/radarbox:latest.
  • We're connecting the container to the docker network adsbnet.
  • We're passing several environment variables to the container:
    • TZ=Australia/Perth to tell the container our timezone.
    • BEASTHOST=readsb to inform the feeder to get its ADSB data from the container readsb over our private adsbnet network.
    • LAT=-33.33333, LONG=111.11111 and ALT=90 to specify our antenna location.
    • SHARING_KEY=g45643ab345af3c5d5g923a99ffc0de9 to specify our sharing key.

Once the file is created, issue the command docker-compose up -d to bring up the new rbfeeder container. You should see the following output:

readsb is up-to-date
adsbx is up-to-date
graphs1090 is up-to-date
piaware is up-to-date
fr24 is up-to-date
Creating rbfeeder

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. At this stage, the logs will be fairly unexciting and look like this:

rbfeeder          | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
rbfeeder          | [s6-init] ensuring user provided files have correct perms...exited 0.
rbfeeder          | [fix-attrs.d] applying ownership & permissions fixes...
rbfeeder          | [fix-attrs.d] done.
rbfeeder          | [cont-init.d] executing container initialization scripts...
rbfeeder          | [cont-init.d] 01-rbfeeder: executing...
rbfeeder          | [cont-init.d] 01-rbfeeder: exited 0.
rbfeeder          | [cont-init.d] done.
rbfeeder          | [services.d] starting services
rbfeeder          | [mlat-client] Delaying mlat-client startup until rbfeeder receives station sn...
rbfeeder          | [services.d] done.
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]  Starting RBFeeder Version 0.2.6 (build 20180313082038)
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]  Using configuration file: /etc/rbfeeder.ini
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]  Network-mode enabled.
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]            Remote host to fetch data: 172.99.7.4
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]            Remote port: 30005
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]            Remote protocol: BEAST
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]  System: raspberry
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]  Start date/time: 2020-04-06 05:12:28
rbfeeder          | [rbfeeder] [2020-04-06 05:12:28]  Socket for ANRB created. Waiting for connections on port 32088
rbfeeder          | [rbfeeder] [2020-04-06 05:12:29]  Connection established.
rbfeeder          | [rbfeeder] [2020-04-06 05:12:40]  Could not start connection. Timeout.
rbfeeder          | [mlat-client] Delaying mlat-client startup until rbfeeder receives station sn...
rbfeeder          | [rbfeeder] [2020-04-06 05:12:58]  ******** Statistics updated every 30 seconds ********
rbfeeder          | [rbfeeder] [2020-04-06 05:12:58]  Packets sent in the last 30 seconds: 0, Total packets sent since startup: 0
rbfeeder          | [rbfeeder] [2020-04-06 05:13:10]  Connection established.
rbfeeder          | [rbfeeder] [2020-04-06 05:13:11]  Connection with RadarBox24 server OK! Key accepted by server.
rbfeeder          | [mlat-client] Mon Apr  6 05:13:28 2020 mlat-client 0.2.11 starting up
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020 Connected to multilateration server at mlat1.rb24.com:40900, handshaking
rbfeeder          | [rbfeeder] [2020-04-06 05:13:29]  ******** Statistics updated every 30 seconds ********
rbfeeder          | [rbfeeder] [2020-04-06 05:13:29]  Packets sent in the last 30 seconds: 87, Total packets sent since startup: 87
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020 Server says:
rbfeeder          | [mlat-client]
rbfeeder          | [mlat-client]         AirNAv Server
rbfeeder          | [mlat-client]
rbfeeder          | [mlat-client]         The multilateration server source code is available under
rbfeeder          | [mlat-client]         the terms of the Affero GPL (v3 or later). You may obtain
rbfeeder          | [mlat-client]         a copy of this server's source code at the following
rbfeeder          | [mlat-client]         location: https://github.com/mutability/mlat-server
rbfeeder          | [mlat-client]
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020 Handshake complete.
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020   Compression:       zlib2
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020   UDP transport:     disabled
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020   Split sync:        disabled
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020 Input connected to readsb:30005
rbfeeder          | [mlat-client] Mon Apr  6 05:13:29 2020 Input format changed to BEAST, 12MHz clock
rbfeeder          | [rbfeeder] [2020-04-06 05:14:00]  ******** Statistics updated every 30 seconds ********
rbfeeder          | [rbfeeder] [2020-04-06 05:14:00]  Packets sent in the last 30 seconds: 148, Total packets sent since startup: 235

We can see our container running with the command docker ps.

Once running, you can visit the RadarBox website, and go to "Account" > "Stations" and click your station to see your live data.

If you need to bring the environment down, you can issue the command docker-compose down from the directory containing your docker-compose.yml file.

It is worth noting that rbfeeder is extremely noisy when it comes to logging. If you haven't set up Docker log rotation as outlined earlier, consider doing this, lest your /var/lib/docker become full.

Feeding PlaneFinder

pfclient is a PlaneFinder client program to transmit ADS-B and Mode S data to the commercial entity PlaneFinder.

In exchange for your data, PlaneFinder will give you a "Gifted Sharer Subscription". If this is something of interest, you may wish to feed your data to them.

The docker image mikenye/planefinder contains pfclient and all of its required prerequisites and libraries. This needs to run in conjunction with readsb (or another Beast provider).

Already running pfclient

You'll need your share code from your existing feeder.

To get your share code, log into your planefinder.net account, and go to "Your Receivers". Your share code will be listed next to your existing receiver.

You will need to make sure your existing receiver is shutdown prior to continuing.

New to pfclient

If you're already running pfclient and you've followed the steps in the previous command, you can skip this section.

You'll need a share code. In order to obtain a PlaneFinder Share Code, we will start a temporary container running pfclient, which will run through a configuration wizard and generate a share code.

Run the command:

docker run \
    --rm \
    -it \
    --name pfclient_temp \
    --entrypoint pfclient \
    -p 30053:30053 \
    mikenye/planefinder

Once the container has started, you should see a message such as:

2020-04-11 06:45:25.823307 [-] We were unable to locate a configuration file and have entered configuration mode by default. Please visit: http://172.22.7.12:30053 to complete configuration.

At this point, open a web browser and go to http://dockerhost:30053. Replace dockerhost with the IP address of your host running Docker. You won't be able to use the URL given in the log output, as the IP address given will be the private IP of the docker container.

In your browser, go through the configuration wizard. When finished, you'll be given a PlaneFinder Share Code. Save this in safe place.

You can now kill the container by pressing CTRL-C.

You should now claim your receiver:

  1. Go to https://www.planefinder.net/
  2. Create an account and/or sign in
  3. Go to "Account" > "Manage Receivers"
  4. Click "Add receiver" and enter your share code when prompted

Deploying pfclient container

Open the docker-compose.yml file that was created when deploying readsb.

Append the following lines to the end of the file:

  pfclient:
    image: mikenye/planefinder:latest
    tty: true
    container_name: pfclient
    restart: always
    ports:
      - 30053:30053
    environment:
      - TZ=YOURTIMEZONE
      - BEASTHOST=readsb
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
      - SHARECODE=YOURSHARECODE
    networks:
      - adsbnet

Be sure to change the following:

  • Replace YOURTIMEZONE with your local timezone in "TZ database name" format (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)
  • Replace YOURALTITUDE with the altitude of your antenna in metres
  • Replace YOURSHARECODE with the share code from your original receiver or the one you generated in the previous step.

So, assuming:

  • Our latitude is -33.33333, longitude is 111.11111 and altitude is 90m
  • Our timezone is Australia/Perth
  • Our share code is zg84632abhf231

...then our docker-compose.yml file would be appended with the following:

  pfclient:
    image: mikenye/planefinder:latest
    tty: true
    container_name: pfclient
    restart: always
    ports:
      - 30053:30053
    environment:
      - TZ=Australia/Perth
      - BEASTHOST=readsb
      - LAT=-33.33333
      - LONG=111.11111
      - SHARECODE=zg84632abhf231
    networks:
      - adsbnet

To explain what's going on in this file:

  • We're creating a container called pfclient, from the image mikenye/planefeeder:latest.
  • We're connecting the container to the docker network adsbnet.
  • We're passing several environment variables to the container:
    • TZ=Australia/Perth to tell the container our timezone.
    • BEASTHOST=readsb to inform the feeder to get its ADSB data from the container readsb over our private adsbnet network.
    • LAT=-33.33333 and LONG=111.11111 to specify our antenna location.
    • SHARECODE=zg84632abhf231 to specify our sharing key.

Once the file is created, issue the command docker-compose up -d to bring up the new pfclient container. You should see the following output:

readsb is up-to-date
adsbx is up-to-date
graphs1090 is up-to-date
piaware is up-to-date
fr24 is up-to-date
rbfeeder is up-to-date
Creating pfclient

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. At this stage, the logs will be fairly unexciting and look like this:

pfclient          | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.
pfclient          | [s6-init] ensuring user provided files have correct perms...exited 0.
pfclient          | [fix-attrs.d] applying ownership & permissions fixes...
pfclient          | [fix-attrs.d] done.
pfclient          | [cont-init.d] executing container initialization scripts...
pfclient          | [cont-init.d] 01-pfclient: executing...
pfclient          | [cont-init.d] 01-pfclient: exited 0.
pfclient          | [cont-init.d] done.
pfclient          | [services.d] starting services
pfclient          | [services.d] done.
pfclient          | 2020-04-11 09:14:33.361261 [-] pfclient (4.1.1 i386) started with the following options:
pfclient          | 2020-04-11 09:14:33.361432 [-]      connection_type = 1
pfclient          | 2020-04-11 09:14:33.361437 [-]      tcp_address = readsb
pfclient          | 2020-04-11 09:14:33.361440 [-]      tcp_port = 30005
pfclient          | 2020-04-11 09:14:33.361442 [-]      data_format = 1
pfclient          | 2020-04-11 09:14:33.361445 [-]      aircraft_timeout = 30
pfclient          | 2020-04-11 09:14:33.361448 [-]      select_timeout = 10
pfclient          | 2020-04-11 09:14:33.361450 [-]      web_server_port = 30053
pfclient          | 2020-04-11 09:14:33.361454 [-]      user_latitude = -33.33333
pfclient          | 2020-04-11 09:14:33.361458 [-]      user_longitude = 111.11111
pfclient          | 2020-04-11 09:14:33.361539 [V] Performing NTP sync (1.planefinder.pool.ntp.org)...
pfclient          | 2020-04-11 09:14:33.361679 [-] Web server is now listening on: http://172.99.7.64:30053
pfclient          | 2020-04-11 09:14:33.361698 [-] Echo port is now listening on: 172.99.7.64:30054
pfclient          | 2020-04-11 09:14:33.362179 [-] TCP connection established: readsb:30005
pfclient          | 2020-04-11 09:14:33.723215 [V] NTP sync succeeded with settings:
pfclient          | 2020-04-11 09:14:33.723269 [V]      Stratum: 3
pfclient          | 2020-04-11 09:14:33.723287 [V]      System clock time: 1586596473.7232
pfclient          | 2020-04-11 09:14:33.723299 [V]      Corrected clock time: 1586596473.7181
pfclient          | 2020-04-11 09:14:33.723310 [V]      NTP offset: -0.0052s
pfclient          | 2020-04-11 09:15:38.239652 [-] User location has been verified.
pfclient          | 2020-04-11 09:16:23.809962 [-] Successfully sent 46 aircraft updates across 10 packets (8.00KB)
pfclient          | 2020-04-11 09:18:14.117198 [-] Successfully sent 57 aircraft updates across 10 packets (9.00KB)
pfclient          | 2020-04-11 09:20:04.389081 [-] Successfully sent 53 aircraft updates across 10 packets (8.00KB)

We can see our container running with the command docker ps.

Once running, you can:

  • Go to http://dockerhost:30053 to see your live data and statistics
  • Visit the PlaneFinder website, and go to "Account" > "Manage Receivers" and click your receiver to see your live data and statistics

If you need to bring the environment down, you can issue the command docker-compose down from the directory containing your docker-compose.yml file.

Feeding OpenSky Network

opensky-feeder is a client program that transmits ADS-B and Mode S data to the non-profit association OpenSky Network.

The docker image mikenye/opensky-network contains opensky-feeder and all of its required prerequisites and libraries. This needs to run in conjunction with readsb (or another Beast provider).

Already running opensky-feeder

You'll need your OpenSky Network username and the serial from your existing feeder.

To get your username and serial, log into your OpenSky Network account, and go to your "Dashboard". Your username and feeder serial will be shown.

You will need to make sure your existing feeder is shutdown prior to continuing.

New to opensky-feeder

First-time users should obtain a feeder serial number.

Firstly, make sure you have registered for an account on the (OpenSky Network website)[https://opensky-network.org/], and have your username on-hand.

In order to obtain a feeder serial number, we will start a temporary container running opensky-feeder, which will connect to OpenSky Network and be issued a serial number. The container will automatically be stopped and cleaned up after 60 seconds.

To do this, run the command:

timeout 60s docker run \
    --rm \
    -it \
    -e LAT=YOURLATITUDE \
    -e LONG=YOURLONGITUDE \
    -e ALT=YOURALTITUDE \
    -e BEASTHOST=readsb \
    -e OPENSKY_USERNAME=YOUROPENSKYUSERNAME \
    mikenye/opensky-network

Be sure to change the following:

  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)
  • Replace YOURALTITUDE with the altitude above sea level of your antenna in metres
  • Replace YOUROPENSKYUSERNAME with your OpenSky Network username

Once the container has started, you should see a message such as:

[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] 01-opensky-network: executing...

WARNING: OPENSKY_SERIAL environment variable was not set!
Please make sure you note down the serial generated.
Pass the key as environment var OPENSKY_SERIAL on next launch!

[cont-init.d] 01-opensky-network: exited 0.
[cont-init.d] done.
[services.d] starting services
[services.d] done.
[opensky-feeder] [INFO] [COMP] Initialize STAT
[opensky-feeder] [INFO] [COMP] Initialize POS
[opensky-feeder] [INFO] [COMP] Initialize DEVTYPE
[opensky-feeder] [INFO] [COMP] Initialize NET
[opensky-feeder] [INFO] [COMP] Initialize TB
[opensky-feeder] [INFO] [COMP] Initialize SERIAL
[opensky-feeder] [INFO] [COMP] Initialize BUF
[opensky-feeder] [INFO] [COMP] Initialize RELAY
[opensky-feeder] [INFO] [COMP] Initialize RC
[opensky-feeder] [INFO] [COMP] Initialize FILTER
[opensky-feeder] [INFO] [COMP] Initialize RECV
[opensky-feeder] [INFO] [COMP] Start STAT
[opensky-feeder] [INFO] [COMP] Start POS
[opensky-feeder] [INFO] [COMP] Start DEVTYPE
[opensky-feeder] [INFO] [COMP] Start NET
[opensky-feeder] [INFO] [COMP] Start TB
[opensky-feeder] [INFO] [COMP] Start SERIAL
[opensky-feeder] [INFO] [COMP] Start RELAY
[opensky-feeder] [INFO] [COMP] Start RC
[opensky-feeder] [INFO] [COMP] Start FILTER
[opensky-feeder] [INFO] [COMP] Start RECV
[opensky-feeder] [INFO] [INPUT] Trying to connect to '10.0.0.1': [10.0.0.1]:30005
[opensky-feeder] [INFO] [INPUT] connected to '10.0.0.1'
[opensky-feeder] [INFO] [NET] Trying to connect to 'collector.opensky-network.org': [194.209.200.6]:10004
[opensky-feeder] [INFO] [NET] connected to 'collector.opensky-network.org'
[opensky-feeder] [INFO] [LOGIN] Sending Device ID 5, Version 2.1.7
[opensky-feeder] [INFO] [SERIAL] Requesting new serial number
[opensky-feeder] [INFO] [SERIAL] Got a new serial number: -1408234269
[opensky-feeder] [INFO] [LOGIN] Sending Serial Number -1408234269
[opensky-feeder] [INFO] [GPS] Sending position -33.3333°, +111.1111°, +100.8m
[opensky-feeder] [INFO] [LOGIN] Sending Username 'johnnytightlips'
[cont-finish.d] executing container finish scripts...
[cont-finish.d] done.
[s6-finish] waiting for services.
[s6-finish] sending all processes the TERM signal.
[s6-finish] sending all processes the KILL signal and exiting.

As you can see from the output above, we've been allocated a serial number of -1408234269.

Deploying opensky container

Open the docker-compose.yml file that was created when deploying readsb.

Append the following lines to the end of the file:

  opensky:
    image: mikenye/opensky-network:latest
    tty: true
    container_name: opensky
    restart: always
    environment:
      - TZ=YOURTIMEZONE
      - BEASTHOST=readsb
      - LAT=YOURLATITUDE
      - LONG=YOURLONGITUDE
      - ALT=YOURALTITUDE
      - OPENSKY_USERNAME=YOUROPENSKYUSERNAME
      - OPENSKY_SERIAL=YOUROPENSKYSERIAL
    networks:
      - adsbnet

Be sure to change the following:

  • Replace YOURTIMEZONE with your local timezone in "TZ database name" format (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
  • Replace YOURLATITUDE with the latitude of your antenna (xx.xxxxx)
  • Replace YOURLONGITUDE with the longitude of your antenna (xx.xxxxx)
  • Replace YOURALTITUDE with the altitude of your antenna in metres
  • Replace YOUROPENSKYUSERNAME with your OpenSky Network username
  • Replace YOUROPENSKYSERIAL with your feeder's OpenSky serial

So, assuming:

  • Our latitude is -33.33333, longitude is 111.11111 and altitude is 90m
  • Our timezone is Australia/Perth
  • Our OpenSky username is johnnytightlips and serial is -1408234269

...then our docker-compose.yml file would be appended with the following:

  opensky:
    image: mikenye/opensky-network:latest
    tty: true
    container_name: opensky
    restart: always
    environment:
      - TZ=Australia/Perth
      - BEASTHOST=readsb
      - LAT=-33.33333
      - LONG=111.11111
      - ALT=90
      - OPENSKY_USERNAME=johnnytightlips
      - OPENSKY_SERIAL=-1408234269
    networks:
      - adsbnet

To explain what's going on in this file:

  • We're creating a container called opensky, from the image mikenye/opensky-network:latest.
  • We're connecting the container to the docker network adsbnet.
  • We're passing several environment variables to the container:
    • TZ=Australia/Perth to tell the container our timezone.
    • BEASTHOST=readsb to inform the feeder to get its ADSB data from the container readsb over our private adsbnet network.
    • LAT=-33.33333, LONG=111.11111 and ALT=90 to specify our antenna location.
    • OPENSKY_USERNAME=johnnytightlips to specify our OpenSky Network username.
    • OPENSKY_SERIAL=-1408234269 to specify our OpenSky feeder serial.

Once the file is created, issue the command docker-compose up -d to bring up the new pfclient container. You should see the following output:

readsb is up-to-date
adsbx is up-to-date
graphs1090 is up-to-date
piaware is up-to-date
fr24 is up-to-date
rbfeeder is up-to-date
pfclient is up-to-date
Creating opensky

We can view the logs for the environment with the command docker-compose logs, or continually "tail" them with docker-compose logs -f. At this stage, the logs will be fairly unexciting and look like this:

[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] 01-opensky-network: executing...
[cont-init.d] 01-opensky-network: exited 0.
[cont-init.d] done.
[services.d] starting services
[services.d] done.
[opensky-feeder] [INFO] [COMP] Initialize STAT
[opensky-feeder] [INFO] [COMP] Initialize POS
[opensky-feeder] [INFO] [COMP] Initialize DEVTYPE
[opensky-feeder] [INFO] [COMP] Initialize NET
[opensky-feeder] [INFO] [COMP] Initialize TB
[opensky-feeder] [INFO] [COMP] Initialize SERIAL
[opensky-feeder] [INFO] [COMP] Initialize BUF
[opensky-feeder] [INFO] [COMP] Initialize RELAY
[opensky-feeder] [INFO] [COMP] Initialize RC
[opensky-feeder] [INFO] [COMP] Initialize FILTER
[opensky-feeder] [INFO] [COMP] Initialize RECV
[opensky-feeder] [INFO] [COMP] Start STAT
[opensky-feeder] [INFO] [COMP] Start POS
[opensky-feeder] [INFO] [COMP] Start DEVTYPE
[opensky-feeder] [INFO] [COMP] Start NET
[opensky-feeder] [INFO] [COMP] Start TB
[opensky-feeder] [INFO] [COMP] Start SERIAL
[opensky-feeder] [INFO] [COMP] Start RELAY
[opensky-feeder] [INFO] [COMP] Start RC
[opensky-feeder] [INFO] [COMP] Start FILTER
[opensky-feeder] [INFO] [COMP] Start RECV
[opensky-feeder] [INFO] [NET] Trying to connect to 'collector.opensky-network.org': [194.209.200.6]:10004
[opensky-feeder] [INFO] [NET] connected to 'collector.opensky-network.org'
[opensky-feeder] [INFO] [LOGIN] Sending Device ID 5, Version 2.1.7
[opensky-feeder] [INFO] [LOGIN] Sending Serial Number -1408234269
[opensky-feeder] [INFO] [GPS] Sending position -33.3333°, +111.1111°, +90m
[opensky-feeder] [INFO] [LOGIN] Sending Username 'johnnytightlips'
[opensky-feeder] [INFO] [TB] Setting sync filter: 0
[opensky-feeder] [INFO] [TB] Setting ext squitter only filter: 0
[opensky-feeder] [INFO] [INPUT] Trying to connect to 'readsb': [10.1.2.9]:30005
[opensky-feeder] [INFO] [INPUT] connected to 'readsb'

We can see our container running with the command docker ps.

Once running, you can:

  • Visit the OpenSky Network website, and go to "My OpenSky" > "Receiver Profile" to see your live data and statistics

If you need to bring the environment down, you can issue the command docker-compose down from the directory containing your docker-compose.yml file.

References