Reading the piAware output over the network

Howdy all,

I have Raspberry Pi4 running with PiAware, dump1090 en some others to feed four different flight tracker websites.

Now I have written a Python program (on Windows PC) to do some ‘time to conflict’ calculations on the tracks of the aircraft. For that I want to read the output of the Raspberry over my own internal network. The Pi has address 192.168.1.168. I would need to read the output every second or so.

How can I achieve that?

Greetings from the Netherlands,
Job

1 Like

What type of data does your program expect (in particular - raw ADS-B messages, or something else?)

Try polling /skyaware/data/aircraft.json
Probably the easiest.

Any data that I can read.
In the meantime, I managed to read datablocks that are coming out rapidly of my Pi, such as:

b’MSG,4,1,1,868012,1,2021/12/16,20:55:42.941,2021/12/16,20:55:42.996,480,56,0,0\r\nMSG,8,1,1,485870,1,2021/12/16,20:55:42.944,2021/12/16,20:55:42.996,0\r\nMSG,7,1,1,440589,1,2021/12/16,20:55:42.945,2021/12/16,20:55:42.996,1800,\r\nMSG,5,1,1,485870,1,2021/12/16,20:55:42.950,2021/12/16,20:55:42.997,2850,-960,0,0,\r\nMSG,8,1,1,471F34,1,2021/12/16,20:55:42.959,2021/12/16,20:55:42.999,0\r\nMSG,5,1,1,485870,1,2021/12/16,20:55:42.964,2021/12/16,20:55:43.000,2850,0,0,\r\nMSG,4,1,1,4CA27A,1,2021/12/16,20:55:42.969,2021/12/16,20:55:43.001,235,82,-1344,0\r\nMSG,3,1,1,484CB4,1,2021/12/16,20:55:42.979,2021/12/16,20:55:43.003,3350,52.29916,4.63756,0,0,0\r\nMSG,3,1,1,780AC8,1,2021/12/16,20:55:42.979,2021/12/16,20:55:43.003,38600,52.99864,3.00041,0,0,0\r\nMSG,7,1,1,868012,1,2021/12/16,20:55:42.983,2021/12/16,20:55:43.003,33000,\r\nMSG,4,1,1,471F34,1,2021/12/16,20:55:42.987,2021/12/16,20:55:43.004,404,302,-64,0\r\nMSG,5,1,1,484133,1,2021/12/16,20:55:42.989,2021/12/16,20:55:43.004,25825,0,0,\r\nMSG,3,1,1,471F34,1,2021/12/16,20:55:42.992,2021/12/16,20:55:43.005,38000,53.51273,2.88359,0,0,0\r\nMSG,5,1,1,440589,1,2021/12/16,20:55:43.022,2021/12/16,20:55:43.059,1800,194,92,0,0,\r\n’

I understand these are of type ‘byte’ in Python which I can subsequently decode into a list.
And so currently I am puzzling these datablocks into dictionaries and see how I can manipulate these block with time to spare to build a DataFrame, and be ready to receive the next datablock!

Should have specified http :slight_smile:
This might be useful i suppose.

graphs1090/dump1090.py at master · wiedehopf/graphs1090 · GitHub

The file is updated once a second but you can increase that.

Download and read this old file written in python2 which polls data from dump1090-fa, port 30003, stores it in variable d for 62 seconds, then splits the stored data. It may give you some insight.

Optimize-Gain-dump-fa-on-Raspbian-Jessie.docx

 

From above file, I have quoted below that part of python2 code which polls data from dump1090-fa port 30003 for 62 sec, stores the polled data in variable d, splits stored data & finallyprints data to stdout/terminal.

NOTE
The code was written using python2 syntax. Needs updating for python3. Some examples below:

First line #!/usr/bin/python2 should be changed to #!/usr/bin/python3

The concatenation of string with integer in line d += s.recv(32) should be done by first changing integer to string, like this: d += str(s.recv(32))

The print statement arguments are without paranthesis. These should be added for example print "Flightaware" should be written `print (“Flightaware”)

#!/usr/bin/python2
import time, socket, subprocess, fileinput, os

measure_duration = 62  #duration of one pass, seconds
g = 49.6  #gain setting
results = {}

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   s.connect(('localhost',30003))
   t = time.time()
   d = ''
   while 1:
      d += s.recv(32)
      if time.time() - t > measure_duration:
         break
   s.close()
   messages = 0
   positions = 0
   planes = {}
   for l in d.split('\n'):
      a = l.split(',')
      messages += 1
      if len(a) > 4:
         if a[1] == '3':
            positions += 1
         planes[a[4]] = 1
   print "gain=",g, "messages=", messages, "positions=", positions, "planes=", len(planes.keys())
   results[g][0] += messages
   results[g][1] += positions
   for hex in planes.keys():
      results[g][2][hex] = 1

Nice work!
Many thanks,
Greetings,
Job

Thanks… but ouch! That is a seriously long file to study.
I’ll enjoy myself getting to grips with the byte blocks for a while first.
:slight_smile:

Then your main two choices are

  1. aircraft.json (as wiedehopf suggests) for decoded data
  2. port 30005 Beast-format output (Mode-S Beast:Data Output Formats - Beast Wiki) for raw messages

Processing the aircraft.json should actually be much easier than the SBS output.

It’s a complete state that is written every second.
That way you don’t need to keep a state in your own program you can operate on the existing state.

I linked to a line for a reason, it’s how you can easily get and open the json:
But i’m in a good mood so i’ll make a simpler example in python:

from contextlib import closing
from urllib.request import urlopen, URLError
import json


url="http://192.168.2.14/tar1090/data/aircraft.json"
with closing(urlopen(url, None, 5.0)) as aircraft_file:
    aircraft_data = json.load(aircraft_file)

for a in aircraft_data['aircraft']:
   hex = a.get('hex')
   lat = a.get('lat')
   lon = a.get('lon')
   if lat and lon:
      print("Icao 24 bit id: {hex} Latitude: {lat:.4f} Longitude: {lon:.4f}".format(hex=hex, lat=lat, lon=lon))

Output:

Icao 24 bit id: 4d2213 Latitude: 50.7587 Longitude: 11.5152
Icao 24 bit id: 3c66aa Latitude: 50.0729 Longitude: 11.6045
Icao 24 bit id: 471f02 Latitude: 50.5106 Longitude: 11.7830
Icao 24 bit id: 394c14 Latitude: 50.7946 Longitude: 12.2310

Obviously adapt the URL so it works with whatever aircraft.json you have available.

You could also print all the data entries for an aircraft:

      for item in a.items():
          print(item)

But just so you get an idea what values are present.

Icao 24 bit id: 3455d9 Latitude: 49.9406 Longitude: 11.8768
('hex', '3455d9')
('type', 'adsb_icao')
('flight', 'VOE6HX  ')
('alt_baro', 28425)
('alt_geom', 29150)
('gs', 390.0)
('ias', 270)
('tas', 408)
('mach', 0.696)
('oat', -47)
('tat', -25)
('track', 90.44)
('track_rate', -0.03)
('roll', -0.53)
('mag_heading', 81.04)
('true_heading', 84.99)
('baro_rate', -1024)
('geom_rate', -992)
('squawk', '1000')
('category', 'A3')
('nav_qnh', 1012.8)
('nav_altitude_mcp', 24992)
('lat', 49.940643)
('lon', 11.876799)
('nic', 8)
('rc', 186)
('seen_pos', 20.9)
('version', 2)
('nic_baro', 1)
('nac_p', 9)
('nac_v', 1)
('sil', 3)
('sil_type', 'perhour')
('gva', 2)
('sda', 2)
('alert', 0)
('spi', 0)
('mlat', [])
('tisb', [])
('messages', 46948)
('seen', 20.9)
('rssi', -34.6)
Icao 24 bit id: 48418c Latitude: 50.2608 Longitude: 12.4454
('hex', '48418c')
('type', 'adsb_icao')
('flight', 'KLM28Q  ')
('alt_baro', 40000)
('alt_geom', 40225)
('gs', 428.4)
('ias', 239)
('tas', 454)
('mach', 0.788)
('oat', -55)
('tat', -27)
('track', 307.03)
('track_rate', 0.0)
('roll', 0.35)
('mag_heading', 309.73)
('true_heading', 313.85)
('baro_rate', -160)
('geom_rate', 0)
('squawk', '1000')
('category', 'A0')
('nav_qnh', 1013.2)
('nav_altitude_mcp', 40000)
('lat', 50.260803)
('lon', 12.445414)
('nic', 6)
('rc', 926)
('seen_pos', 0.8)
('version', 0)
('nac_p', 6)
('nac_v', 0)
('sil', 2)
('sil_type', 'unknown')
('alert', 0)
('spi', 0)
('mlat', [])
('tisb', [])
('messages', 139)
('seen', 0.6)
('rssi', -31.3)

This output is from readsb … some extra fields but you’ll get something similar.

https://github.com/flightaware/dump1090/blob/master/README-json.md

2 Likes

Wow, fantastic.
Obviously reading a complete json is much easier.
Do you mean this means that the Pi4 is indeed sending out a complete json?
I will need to study this some more!
Greetz,
Job

Not the Pi4, but the dump1090-fa instance on it. It stores the information in several JSON files. one is the aircraft.json mentioned by wiedehopf.

I am using the file to have a long term storage database of all aircraft covered by my receiver

Cool.
After having had fun playing around with the individual message blocks, I shall now give this .json a try.
Should be much simpler of course.
Will let everyone know of the result!
Greetz,
Job

Just discovered I have a number of ‘aircraft.json’ files on my Pi4:

./run/skyaware978/aircraft.json
./run/dump1090-fa/aircraft.json
./run/adsbexchange-feed/aircraft.json

LOL

the first two are the ones of your local sticks. You obviously have both frequencies covered.
The last one is the data you share with ADSBExchange. It’s content should be similar to the one of dump1090 (i don’t know if the 978 feed is uploaded as well).

I am using a script which grabs the file every minute, collect the aircraft information, verify if it was there the last 60 minutes. If not it writes the record to a SQLite database, so i do have at the end of the day not only the unique aircraft over the day but also the flights if it was done more than once but on a different flight.

i am using this script with some few modifications:
Logging dump1090-fa to local database – Cactus Projects

An now found out that I need to read from this:

url=“http://192.168.1.168:8080/data/aircraft.json

and I am getting full dumps of json data.
What joy. Saved me a complete evening (but fooling around was worth it)

i am using this script with some few modifications:
Logging dump1090-fa to local database – Cactus Projects Blockquote

Supercool man

That should be the one you see locally in your /run/ directory, not a different one

Blockquote

Please explain.
I am accessing /run/dump1090-fa/aircraft.json.
This is the directory of the server for Flightaware I think

Edit: actually I am not so sure about that now…

Yes, that s the data created by dump1090-fa and uploaded to Flightaware (and maybe other sources using dump1090-fa as helper).
The one you see on your raspberry using http://192.x.x.x is the same data accessible via network browser