Stream1090

Running here also.

stream1090 -h shows old date:

pi@raspberrypi:~ $ stream1090 -h
Stream 1090 build 251124 for standard rtl_sdr output @2.4MHz.
Internal sample rate is 8MHz
There are no parameters available

But it’s the latest version:

pi@raspberrypi:~/stream1090 $ git log -1
commit 19a29d1ee2854da49175da6b46aca2221177080a (HEAD -> main, origin/main, origin/HEAD)
Author: mgrone <226090022+mgrone@users.noreply.github.com>
Date:   Thu Nov 27 07:50:44 2025 +0100

    Added altitude and squawk checks for downlink formats 0, 4, 5, 16, 20, 21. Relaxed the constraints for sending these messages.
1 Like

I’ve had the new version running for about 11 hours. In terms of the “Other” positions ratio, there hasn’t been any significant change. The last blue bar is the ratio prior to the update and the orange bar is the ratio for positions reported after the update for the current UTC day.

Graphs 1090 is showing a big jump in tracks with a single position. But the underlying multi-position tracks (green) and the aircraft counts look similar to the same times the previous day.

I think the Tracks Seen graph defines a single message track as an aircraft that only sends one valid position in a five minute interval.

1 Like

All good. :grinning_face: You pulled directly after i pushed. I noticed the wrong version string afterwards. update version string · mgrone/stream1090@81b6ee1 · GitHub

Thank you for the feedback. So there are a couple of changes that might or might not effect you. The blue bar version was neglecting many planes without ADS-B. This includes GA without it, some military planes or commercial planes that were nice enough to turn off their broken unit instead of broadcasting crap. Maybe you are in an area where all that stuff does not really matter.
Tracks with single message will be investigated. Although your amount seems a bit excessive.

Regarding your other numbers: If you want to fiddle around a bit, have a look at the stream1090 stats output. While range and plane count is important, there is also the ratio between the 56-bit and 112-bit messages. You do not want that ratio to be too bad aka many short messages and few long messages (because the rest broke). My rule of thumb (i am not running any 2k msg/s stuff here, simple balcony antenna, 50 planes / minute today) is that if planes are in good range, you want to have around 33% long vs 66% short.

The example on the github page is a bit too good of an example (older version of stream1090):

This was taken at the sea on a bench with a mobile setup, not on my balcony.

However, if there are only a few planes around that are in range, stream1090 does quite a good job in milking them to the limit.

I’m at 60% long vs 40% short at the moment:

That’s an impressive range from your setup.

Most GA aircraft here have ASD-B and nearly all others have mode S transponders. But I have a lot less traffic than you.

Yea well you do not have probably that prime location on top of a dyke i had on vacation when i took that sample. However, your stream1090 stats are more than good. That explains a bit the previous screenshots. I was very confused about your positions throughput. Very good. Ah yea, and you have the 10msps of course. That may shift things a bit. It could also be that there are some more regulations in AUS for GA aircraft.

I’ve been running with -u 24

Is it worth trying -u 10 or -u 20 to see if that affects the single message tracks?

Simple answer: No, it does not matter.

1 Like

I have to read a bit how this whole graph1090 business work and also some other parts of the pipeline. For my personal use i have my own stats which are more barebone but i need them for the direct output of stream1090. Looks like this:

This stuff sits between the output of stream1090 and whatever comes afterwards (in my case readsb).

1 Like

I will start now testing of a another update. Besides that this fixes a nasty bug in the crc error correction for DF11 and DF17 that may show up or not, it also changes a bit the recognition logic.

Regarding the bug: Depending on compiler and the system, it may happen that stream1090 will find a fix for a broken message, but the repair goes wrong and the message sent will not have a crc of 0. This concerns all repairs which involve flipping the last bit of a message.

1 Like

Also if you are new and want to test stream1090, please be aware that Airbus has requested airlines to update the software of certain planes. This seems to already show up in the plane count due to disruptions in the flight plans.

1 Like

Yeah, things like that make it difficult to make A B comparisons of two systems. I can’t tell if there’s a difference between using stream1090/dump1090-fa and just using dump1090-fa alone. There’s too many variables that you have no control of to make a comparison.

Probably the most accurate method for an A B comparison would be to have one antenna connected to two strings of identical hardware. That way both systems would be seeing the same available planes at the same moment in time. But that would require lots of hardware.

1 Like

Not that much :slight_smile:
Also splitting after a filtered LNA is perfectly acceptable for comparisons.
Actually i’d prefer that.

Really it would be optimal to just split the raw samples from the SDR and give it to multiple decoders.
But don’t think dump1090-fa or readsb can do it like that currently.

Hi,
I had read a good part of these threads (also a few other related threads but I ended up in here…) and I would like to make a couple of questions about stream1090 and interoperability, I am pretty new to these subjects and I am pretty much scratching the surface, but I think I can also give a bit from what I already have done here.

First off, I’d like to say that the ease it was to use stream1090 was absolutely fantastic and did what I wanted in a couple of tries and it is being shown to be utterly stable and quite reliable indeed, but, hence, questions.

My idea – out of my lack of knowledge, Im thinking after reading several threads – was to put up a couple of antenas at both sides of the house in rpis, and transmit what the dongles are collecting to a “central” server that would run the feeders.

So I build one that uses:
Bus 001 Device 002: ID 0bda:2838 Realtek Semiconductor Corp. RTL2838 DVB-T

Then stream1090 is collecting data and sending out.

Differently from the ideas above I built something slightly different, because I also like to see the small console dashboard from stream1090, therefore I run him in a screen method – first lets start him with this script:

#!/bin/bash

SESSION_NAME="adsb-stream"
STREAM_COMMAND='rtl_sdr -f 1090000000 -s 2400000 - | stream1090 | socat -u - TCP4:192.168.1.31:30001'

case "$1" in
start)
if screen -list | grep -q "$SESSION_NAME"; then
echo "Session $SESSION_NAME already running"
else
echo "Starting ADS-B stream in screen session: $SESSION_NAME"
screen -dmS "$SESSION_NAME" bash -c "$STREAM_COMMAND"
echo "Started. Use 'screen -r $SESSION_NAME' to view stats"
fi
;;
stop)
echo "Stopping ADS-B stream session"
screen -S "$SESSION_NAME" -X quit
;;
status)
if screen -list | grep -q "$SESSION_NAME"; then
echo "ADS-B stream is RUNNING in screen session: $SESSION_NAME"
echo "Use 'screen -r $SESSION_NAME' to view stats"
else
echo "ADS-B stream is NOT running"
fi
;;
restart)
$0 stop
sleep 2
$0 start
;;
view)
screen -r "$SESSION_NAME"
;;
*)
echo "Usage: $0 {start|stop|status|restart|view}"
exit 1
;;
esac

This will start a screen (could possibly be tmux as well) with stream inside:

There is a screen on:
1774870.adsb-stream (11/28/2025 11:24:09 PM) (Detached)

To access it you just run “screen -r adsb-stream” (or if no other screen exists just “screen -r”)

With that working fine, I added a service like:

[Unit]
Description=ADS-B Stream in Screen Session
After=network.target
Wants=network.target

[Service]
Type=forking
User=root
ExecStart=/install/adsb-screen-manager.sh start
ExecStop=/install/adsb-screen-manager.sh stop
ExecReload=/install/adsb-screen-manager.sh restart
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

As such he will start, stop, restart normally.

What I need then is to have on the server 192.168.1.31 (which is a VM Debian Trixie server running on proxmox) the dump10190-fa running , who will expose the port 30001 out, for such I just declared “RECEIVER=none” on its configuration and he automatically start in net-only mode.

Fine! stream1090 + socat will start sending data when it finds the port 30001 listening properly…. and voila, it just works!

Now… I did built the first one out of curiosity and because I had a RTL-SDR Blog V4 lingering around… Also with a BS telescopic antena, and he got some things..

Then I got a rpi4 with a proper antenna and the blue dongle from FlightAware:
Bus 001 Device 003: ID 0bda:2832 Realtek Semiconductor Corp. RTL2832U DVB-T

And I applied exactly the same idea from the first one, he is using stream1090 to stream data towards the same IP and on the same port.

I actually works, and he collects and display data from both, but then upon checking closely Im getting:

Nov 29 22:08:17 debian-apoc piaware[722]: mlat-client(405210): Warning: the timestamps provided by your receiver do
not seem to be self-consistent. This can happen if you feed data from multiple receivers to a single mlat-client, wh
ich is not supported; use a separate mlat-client for each receiver.

Which I bet that, while someone more experienced reading my thread had already on the back of their heads this information waiting to get out ahaha bingo!

Although MLAT seems to be working most of the time, from time to time the FA system seems confused.

From this same server I am running adsbexchange feeder and he is giving a slightly more cryptic but seemingly the same type of message, that reads:

Nov 29 22:14:53 debian-apoc adsbexchange-mlat[593316]: outlier detected with ts: 82242.930, last_ts: 173372.753, ts_elapsed: -91129.823, sys_elapsed: 0.000 (values in seconds)
Nov 29 22:14:59 debian-apoc adsbexchange-mlat[593316]: outlier detected with ts: 82249.082, last_ts: 173378.919, ts_elapsed: -91129.837, sys_elapsed: 0.402 (values in seconds)
Nov 29 22:15:04 debian-apoc adsbexchange-mlat[593316]: outlier detected with ts: 82254.351, last_ts: 173384.268, ts_elapsed: -91129.917, sys_elapsed: 0.503 (values in seconds)

Hence my question (which might be two within it self)

Either I should run two dump10190-fa, which probably in consequence two adsbexchange?

How do I would do that? As the only port I put up is the dump1090-fa (30001) how would I go to add a second one? would adbsexchange that runs in paralelel , seemingly reading data from dump1090-fa would deal with both instances of dump1090-fa at the same time?

I am pretty sure that I am doing other things that are probably wrong but I am pretty happy with the results so far ahaha anyway, sorry for the long reply.

From a noise figure standpoint – yes, the right place to do the split. Course then you can’t power the LNA using the bias-t in the RTL-SDR dongle. Need to provide a separate power supply.

But more generally, lots of hardware – for example, if you’re using WiFi to connect to your network, you need two WiFi antennas. If you’re using a USB powered hub, two of those etc.

Edit to add:
You could avoid a lot of the extra hardware by doing the data collection locally. Just take the outputs of dump1090-fa or readsb into a 3rd RPi. I think that’s what @spctrmn is trying to accomplish, but I couldn’t follow completely what he is doing.

So i will try to answer your question the best i can. I personally do not do any MLAT, but i have a bit of understanding how it works. Stream1090 will timestamp every message. The counter for the timestamp starts with the first sample the dongle sends. From there on it is 12 mio ticks per second or 12MHz. Regardless of the sampling speed, stream1090 will compute the timestamp based on the samples received and makes sure that it is 12MHz based.

HOWEVER, this timestamp is soley based on when the first sample was received. So if you have two or more instances of stream1090 feeding sth, the timestamps of different instances will be totally out of sync and mixed up.

So why is the server now complaining? The server has to figure out the offset of your timestamps (when the first sample arrived) in relation to the offsets of the other peers that are used for MLAT later. This of course is not possible if you send message 1 with a timestamp from instance 1 and then sending message 2 from instance 2 which have total different offsets in time.

I don’t know the details, but you need for each instance a separate MLAT client id. Otherwise the server cannot pin point your offset. Edit: the correct word here is: sync the offsets of the peers.

Edit 2: To explain this a bit more. SunExpress XYZ comes back from Mallorca, Spain with plenty of drunken tourists on board. It will fly by and several peers will receive an ADS-B message which say for the example also includes the position. These messages will also be timestamped and end up at the server. The server now has several messages for SunExpress XYZ including its position, it also knows the positions of the receiver stations. And it got a timestamped message for the position messages of SunExpress XYZ per peer. The server can now do the reverse math: That is offset of x that is offset of y. They received the message at x,y PLUS the time it takes to get there. The server knows the distance between plane and receiving station.

Edit 3: @wiedehopf explained it to me. I am grateful for that. Before i was really like: No way you can do that. But the sample count is quite an accurate clock. More accurate then the internal clock of your device.

I’ve taken advantage of the Black Friday sales to order a splitter, AirSpy mini and a RasPi 5 so I can do some proper comparisons.

Apart from airspy_adsb versus Stream1090 the differences will be an AirSpy Mini / AirSpy R2 into RasPi 4 / RasPi 5. I’m assuming that with the same software settings, the differences in hardware won’t be an issue?

1 Like

So i pushed a dirty hot fix for the above bug. I was not aware that shifting a 64 bit unsigned int by 64 bits to the left results in undefined behaviour. The other changes need further testing.

2 Likes

Stream1090 does not care about the hardware. However, for reception, hardware might be an issue. So if you do tests, i would cycle things through. For sure the airspy stuff is of higher quality compared to my noolec v5s. There the difference between sticks (all v5’s) outweighed the improvement i was trying to make. Also different devices may introduce different amount of noise.

One way to cut down on configs is probably to try to run everything on the RP5. In my setup with rtl_sdr (so 8 Msps internal speed) it sits comfortable at <17% single core usage while having throttled down to 1.6Ghz (sometimes 1.7Ghz). Be aware that when you look at the CPU usage that this is with respect to the current clock speed of the CPU. I can easily make stream1090 to use only 10% by wasting more CPU so then it does not clock down and stays at 2.4Ghz.

vcgencmd measure_clock arm

is your friend there.

1 Like

I’ve been digging in to the increase Tracks with Single Message from Stream1090 on my set up. The 2-hour graph with the latest version of Stream1090 looks dramatic, but it may not be important.

The ADSB-B Tracks Seen graph is based on information from the readsb stats.json

https://github.com/wiedehopf/readsb/blob/dev/README-json.md

What is actually being captured is NEW tracks created in the time interval. I went down a rabbit hole trying to understand this graph at the start of the year. It smooths out the raw Tracks Seen data by spreading it over 8 minutes. This is what one new track in stats.json theoretically looks like on the chart:

Add to that the way rrd tool handles plotting data and you get something like this:

This is a single new single message track at approximately 16:03 - the magnitudes match the theoretical pattern except for first small initial impulse - there are 9 rather than 8 contributions. (This my main feeder that runs airspy_adsb and has a much better view of the sky than my test setup.)

All of this is to say that this is a difficult graph to interpret - the main use of high levels of single message tracks is as a diagnostic that your gain setting is too high on RTL-SDR sticks.

It occurred to me that I could look at the aircraft.json that readsb also produces search for the single message tracks. So I wrote a script to run on my Mac and query aircraft.json every 60 seconds and write the results to a text file. Readsb keeps aircraft in the aircraft.json for 60 seconds after they are last seen, so this interval ensures you will capture all aircraft seen. With my small aircraft counts an hour of aircraft.json data was only 700KB. The sample interval starts at 13:23 on the top group of three graphs.

I first tried searching the text file for “messages”: 1, and got no matches! So I then tried “messages”:2, and got 11 matches. (I seem to remember reading somewhere that readsb needs two valid messages before putting an aircraft in the json.) The json for each of the two-message matches looks like this:

{
    "hex": "d6338a",
    "type": "mode_s",
    "mlat": [],
    "tisb": [],
    "messages": 2,
    "seen": 56.8,
    "rssi": -49.5
  }

Finding “messages”:2, does not guarantee the hex code is from an aircraft with a “single-message”Track because more messages could be received in later intervals. Searching the file using the “hex”: “d6338a”, term found only one entry - confirming it was a single-message track aircraft. Repeating the hex search revealed four of the eleven aircraft had sent more than two messages.

I then checked the 11 hex codes with hexdatabase.com the seven single-track message hexes did not find any results, so these were phantom aircraft.

If I conservatively assume a message rate of 50 messages per second, that’s 180,000 messages per hour and the seven phantoms are only 0.004% of the total. That seems pretty good to me.

(Sorry for the long post.)

1 Like