It’s nice to able to see the RSSI when running Piaware Skyaware window.
Yes that is what i also noticed. However, in a production enviroment “nice” does not justify wasting cpu cycles per upsampling channel (24 mio per second) in code that runs for weeks, months, …
There is much bigger fish to fry. And that is the multi-device support. This will need a sophisticated duplicate message removal system. Why would you do that?
- You have devices A and B.
- A and B are being demodulated separetly.
- They produce different MLAT timestamps.
We do not like that.
We want something like:
- You have devices A and B.
- A and B are being demodulated separetly.
- Have the duplicate removal system look out for ADS-B positional messages.
- A is the primary device, B is secondary.
- Adjust the MLAT counter of B to match that of A.
Now you may ask: Ok cool and… So adjusting the MLAT counter is easy.
But there is also the difficult way: You can tell the device B to catch up or slow down (by inserting 0s or skipping samples).
This will synchronize the sample streams of the devices. Not only their counters for MLAT. If the two devices are in sync you can:
- Demodulate A and B separately
- Create a new combined stream A + B that combines the samples of A and B
- Demodulate that also.
Low priority question - as I am probably only person trying to run stream1090 on macOS.
cmake seems to be working, but it is falling over when I run make.
jrg@MBPro2021 build % cmake ../ -DEND_STATS=ON
-- The C compiler identification is GNU 15.2.0
-- The CXX compiler identification is GNU 15.2.0
-- Checking whether C compiler has -isysroot
-- Checking whether C compiler has -isysroot - yes
-- Checking whether C compiler supports OSX deployment target flag
-- Checking whether C compiler supports OSX deployment target flag - yes
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /opt/homebrew/cellar/gcc/15.2.0_1/bin/aarch64-apple-darwin25-gcc-15 - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Checking whether CXX compiler has -isysroot
-- Checking whether CXX compiler has -isysroot - yes
-- Checking whether CXX compiler supports OSX deployment target flag
-- Checking whether CXX compiler supports OSX deployment target flag - yes
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /opt/homebrew/cellar/gcc/15.2.0_1/bin/aarch64-apple-darwin25-g++-15 - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- [stream1090] Build type not specified: defaulting to Release
-- Found PkgConfig: /opt/homebrew/bin/pkg-config (found version "2.5.1")
-- [stream1090] Airspy support enabled
-- [stream1090] RTL-SDR support disabled (librtlsdr not found)
-- Configuring done (6.3s)
-- Generating done (0.0s)
-- Build files have been written to: /Users/jrg/SynologyDrive/Scratch/Aircraft Tracking Notes/Stream1090_Dev/stream1090/build
jrg@MBPro2021 build % make
[ 33%] Building CXX object CMakeFiles/stream1090.dir/main.cpp.o
[ 66%] Building CXX object CMakeFiles/stream1090.dir/src/devices/AirspyDevice.cpp.o
[100%] Linking CXX executable stream1090
ld: library 'airspy' not found
collect2: error: ld returned 1 exit status
make[2]: *** [stream1090] Error 1
make[1]: *** [CMakeFiles/stream1090.dir/all] Error 2
make: *** [all] Error 2
If I have read CMakeLists.txt correctly, PkgConfig must be finding libairspy for it report “Airspy support enabled”
The Airspy directory is installed at /opt/homebrew/Cellar
That is a problem. I will look into this. It is very strange though.
I think it could be something to do with Homebrew not installing the dev branch of libairspy. I just checked an on the pi5 I ran sudo apt install libairspy-dev
brew install libairspy-dev doesn’t find anything, so I ran brew install airspy
I thought I could try to compile libairspy-dev on the Mac, but I couldn’t find the source as there only seems to be a master branch in the repository.
fwiw, the actual mlat server already does this internally (and for receivers in different physical locations).
You probably want more than just a simple offset (A = B + x). The mlat server tracks the first derivative (A = B + x + yt, i.e. the first couple of terms of a Taylor series) which handles fixed differences in the sampling clock frequency, which is sufficient for what it does. You could add another term if you wanted to try modelling sampling clock frequency drift, but in practice the clock frequency doesn’t usually drift very fast, so the “fixed” frequency difference in the model can track that.
Since the mlat server itself must already do this for the independent-receiver case, there’s not a lot of benefit to mlat if you do the work on the receiver side too.
edit: also, beware that there are lots of bit-for-bit-identical duplicate messages transmitted (less so for positional messages, but they do happen), which will confuse a naive algorithm that just tries to match up identical messages in the two streams.
You need to either use more of the flags provided by pkg-config (e.g. CFLAGS_OTHER), or use IMPORTED_TARGET to rely on the cmake module doing that for you. You’re probably losing a -L flag somewhere currently
The idea here is that you can do two things:
- Syncing up the mlat counters makes duplication detection easier.
- For example it is very hard to decide if two DF-11 messages are duplicates or not, but you know that.
- What you get from doing this: You demodulate two devices independently, BUT the demodulators share the same state (known planes and their details)
- Sharing the demodulation context can improve things. If device B picks up a single message from a plane it has never seen before, but A has. Then this will make a difference.
It is very difficult to think of another type than DF-17 position messages that actually make sense.
Yea this will take some time. There is homebrew involved and that will complicate things. I have to check the homebrew formular.
You are running rtl-sdr, right? Have you tried the -q option?
I haven’t tried the -q option yet. One thing I noticed is that when I run: ./build/stream1090 -s 2.4 -d ./configs/rtlsdr.ini | socat -u - TCP4:localhost:30001 , that the command line prompt does not return after running that command. No big deal when running from the command line, i.e. the command does work. However when I put that in a script and try to run as a service, the service doesn’t run. Is there something else I need to do to run as service? Thanks.
This is my service:
[Unit]
Description=Stream1090 service
Wants=readsb.service
After=multi-user.target
[Service]
ExecStart=/home/side/code/stream1090/start_service.sh
Type=simple
Restart=always
[Install]
WantedBy=default.target
with start_service.sh
#!/bin/bash
# Pause for 5 seconds before starting
sleep 5
# Change to the stream1090 directory; exit if the directory change fails.
cd /home/side/code/stream1090/ || { echo "Failed to change directory to /home/side/code/stream1090/"; exit 1; }
./start_6M.sh > /dev/null 2>&1 &
and start_6M.sh being
./build/stream1090 -s 6 -u 12 -d ./configs/airspy.ini -q -v | socat -u - TCP4:localhost:30001
Note that the path of the config filename is relative.
# Change to the stream1090 directory; exit if the directory change fails.
cd /home/side/code/stream1090/ || { echo "Failed to change directory to /home/side/code/stream1090/"; exit 1; }
ensures that i am in the correct directory.
Edit: (these things are separeted in so many files because i am running a more complicated backend as default compared to this)
Edit 2: Probably, your problem is the relative path of the config.
Edit 3: airspy or rltsdr does not matter here. The problem is about launching it properly.
Oh, that’s right my command line needs to be run in stream1090 directory. I’ll just run it from the command line for now, and not bother with the service setup. Will collect some data with and without the -q option and report back later.
So, I ran with and without the -q option and there doesn’t seem to be any difference in overall CPU Utilization in graphs1090. It’s about 15% either way. The command line with -q option is:
./build/stream1090 -s 2.4 -q -d ./configs/rtlsdr.ini | socat -u - TCP4:localhost:30001 It doesn’t seem like the -q option is taking effect.
I am out of my depth with cmake, etc. but offer these links in case they point you in the right direction.
When I asked AI about compiling libairspy-dev on macOS I got the following reference to AIS-catcher:
https://jvde-github.github.io/AIS-catcher-docs/installation/build-source/
The table there implies that the equivalent of
sudo apt install-dev
is
brew install airspy
I then looked at the AIS-catcher cmake file:
https://github.com/jvde-github/AIS-catcher/blob/main/CMakeLists.txt
The pkg-config stuff starts at line 107, and there are few apple specific lines at line 112.
(I run AIS-catcher with a RTL-SDXR dongle on the same pi5 as my main ADS-B feeder, and can confirm it is a vey solid piece of software.)
Also, if you want more people to test your RTL-SDR code, let me know. I have a spare Nooelec Smart v5 that I could use to replace the R2 feeding the pi4 in my test setup.
Well what about the msgs/s?
Here is a plot of Messages/sec from graphs1090.
Prior to 14:25 was stream1090 without -q option, 14:25 to 15:15 is with -q option. At 15:30 switched back to dump1090-fa as demodulator (no stream1090).
I used the default gain of 40 dB in the rtlsdr.ini file when running stream1090. That might be too high. When running dump1090-fa as demodulator it is set to use adaptive gain. It adjusts gain to about 20 dB during the day and 33 dB at night. This is with a Nooelec filtered LNA with about 30 dB gain. I’ll collect some more data tomorrow with the gain set to about 20 dB in the rtlsdr.ini file.
More messages/sec data without -q option (beginning of graph up to 14:30) and with -q option (14:30 to end of graph). This is with gain = 20 in rtlsdr.ini file.
We wiill get there. If you have the time, can you verify this on a recorded 60s sample?
Ok, got it. Just cat an IQ file to stdio then pipe to stream1090. So here’s what I got for a 60 second IQ file with and without the -q option:
With -q option:
-------------------------------------------------------------
| Type | #Msgs | %Total | Dups | Fixed | Msg/s |
-------------------------------------------------------------
| ADS-B | 1323 | 38.2% | 20.9% | 32.5% | 264.6 |
| Comm-B | 5 | 0.1% | 0% | | 1 |
| ACAS | 887 | 25.6% | 0% | | 177.4 |
| Surv | 275 | 7.9% | 0% | | 55 |
| DF-11 | 975 | 28.1% | 27.1% | 41.7% | 195 |
-------------------------------------------------------------
| 112-bit | 1378 | 39.8% | 20.3% | 31.4% | 275.6 |
| 56-bit | 2087 | 60.2% | 14.8% | 22.8% | 417.4 |
-------------------------------------------------------------
| Total | 3465 | 100% | 17.1% | 26.4% | 693 |
-------------------------------------------------------------
(Max. msgs/s 762.4)
Messages Total 42820
DF 0 : 837
DF 4 : 264
DF 5 : 11
DF 11 : 975
DF 16 : 50
DF 17 : 1303
DF 18 : 20
DF 20 : 5
Without -q option:
-------------------------------------------------------------
| Type | #Msgs | %Total | Dups | Fixed | Msg/s |
-------------------------------------------------------------
| ADS-B | 1185 | 37.9% | 20.4% | 31.8% | 237 |
| Comm-B | 5 | 0.2% | 0% | | 1 |
| ACAS | 789 | 25.2% | 0% | | 157.8 |
| Surv | 238 | 7.6% | 0% | | 47.6 |
| DF-11 | 910 | 29.1% | 24.8% | 40.2% | 182 |
-------------------------------------------------------------
| 112-bit | 1232 | 39.4% | 19.8% | 30.9% | 246.4 |
| 56-bit | 1895 | 60.6% | 13.7% | 22.1% | 379 |
-------------------------------------------------------------
| Total | 3127 | 100% | 16.2% | 25.7% | 625.4 |
-------------------------------------------------------------
(Max. msgs/s 691.8)
Messages Total 38835
DF 0 : 747
DF 4 : 229
DF 5 : 9
DF 11 : 910
DF 16 : 42
DF 17 : 1168
DF 18 : 16
DF 19 : 1
DF 20 : 5
About a 9% improvement in Messages total using the -q option. Excellent.


