The ADS-B receiver server component for the MyPreflight platform. It listens for position reports over HTTP, from flight-simulator-based transponders.
MyPreflight is a briefing service and electronic flight board app for your virtual flights, providing you realistic figures, checklists, procedures and data to perform your flight like a real pilots do. You can customize your experience, integrate with SimBrief and other tools. Check out our homepage at mypreflight.io.
This module is the ground station. Real ADS-B receiver listens to 1090 MHz, and this one listens to HTTP:
- accepts position reports from the transponder app running on a player's PC,
- keeps the track of every callsign in memory, ordered by time,
- serves that track to anything that wants to process these data.
It is as close as it gets ADS-B over HTTP implementation.
No database. Positions live in a cache-manager store keyed by callsign, so the receiver restarts empty — exactly like
a real one does when you power-cycle it.
This app uses docker-based virtualization to run. To set up the project, follow these steps:
-
Clone the project by running:
git clone git@github.com:oskarbarcz/adsb-receiver-api.git
-
Prepare an environment variable file by copying
.env.distto.envand fill it with your data.cd adsb-receiver-api cp .env.dist .env -
Use docker compose to set up the environment
docker compose up -d --build
Packages and dependencies will be configured automatically.
-
Your project should be up and running. Open the browser and go to http://localhost/api to see the api documentation. You can preview app logs by running:
docker compose logs -f app
Do not execute NPM or any other commands regarding project from your host machine, use container shell instead. For example, to lint the project run:
docker compose exec app npm run lint
To shut the containers down run:
docker compose downThere are two bearer tokens, both set in .env. There are no user accounts and nothing is persisted.
| Token | Who holds it | What it unlocks |
|---|---|---|
CLIENT_TOKEN |
the transponder app | publishing position reports |
ADMIN_TOKEN |
the platform | clearing the track of a given callsign |
Reading a track needs no token at all — a real ADS-B signal is not authenticated either.
The full endpoint reference is generated from the code and published at adsb.mypreflight.io.
A position report carries the fields a Mode S transponder would broadcast:
curl -X POST http://localhost/api/v1/position \
-H 'Authorization: Bearer client-token' \
-H 'Content-Type: application/json' \
-d '{
"callsign": "DLH1234",
"date": "2025-08-08T15:46:38.250Z",
"latitude": 51.47115,
"longitude": -0.47351,
"altitude": 91.95,
"verticalRate": 0,
"squawk": "6222",
"groundSpeed": 0.32,
"track": 179.07,
"alert": false,
"emergency": false,
"spi": false,
"isOnGround": true
}'Every field is required and the payload is validated on the way in: latitude and longitude have to be on the globe, and
squawk has to be four octal digits — 7700 is a valid emergency code, 7800 is not a code at all. Unknown
properties are rejected outright, so a malformed report gets a 400 instead of being silently trimmed.
Reports accumulate per callsign rather than overwriting, so GET /api/v1/position/DLH1234 returns the whole track in
chronological order. An unknown callsign returns an empty array, not a 404.
To run tests, execute the following commands:
# unit tests
$ docker compose exec app npm run test
# functional tests
$ docker compose exec app npm run test:functionalWe use Jest for unit tests, and cucumber-js for functional tests. Unit tests are stored in the src directory
just near the tested module, while functional tests are stored in the features directory.
This project uses semantic versioning.
Continuous integration and deployment run on GitHub Actions, configured in the .github/workflows directory. Every pull
request is audited, formatted, linted and tested; every merge to main tags the repository, cuts a release and pushes
the production image to ghcr.io.
My name is Oskar, an experienced programmer, cybersecurity enthusiast, and conference speaker from Poland. Feel free to contact me via the platforms below:
A public domain under the Unlicense. Do what you want with it. I am an experienced software engineer, but I am not connected anyhow with the airline industry. This project is created for educational purposes only and should not be used for real-world aviation operations.
