SDR, eller ”software defined radio” är en radio där mycket av det som byggs med komponenter i en klassisk radio, i stället byggs med mjukvara i en dator. I detta inlägg använder jag en billig SDR för att hämta positioner för passagerarflygplan över i princip södra Sverige.
När jag säger billig så menar jag verkligen det. Det finns dyrare SDR men de jag använder kostar 299kr styck via elektrokit.com.
Med denna USB dongel, rätt anpassad antenn och lämplig mjukvara, så kan man ta emot alla typer av signaler från 24 MHz till 1’766 MHz, vilket inkluderar vanlig radio, TV, GSM, med mera.
Jag är här intresserad av ADS-B signalerna på 1’090 MHz som används för att signalera var flygplan befinner sig, vilken kurs och fart de har, med mera nyttig information. Detta är okrypterade paket som (om alla använder dem) i princip kan ersätta många funktioner som ett betydligt dyrare radarsystem kan tillhandahålla.
För att kunna ta emot signaler på 1’090 MHz behöver man en lämplig antenn. Jag bygger en enkel kvartsvågsantenn med fyra jordplansspröt, vilket duger för mig. De som är bättre på att bygga antenner kan säkert göra en som är bättre, men i princip räcker det att avisolera en koaxialkabel så att änden är ca 6.9 mm lång, och sedan stoppar man in ytterligare trådar mot ”strumpan” på kabeln och vinklar dessa nedåt 45 grader. Dessa skall också vara ca 6.9 mm långa.
Jag har här provat med lite tjockare koppartråd där jag hjälpligt lödat ihop dessa med koaxialkabeln, men det jag beskrev tidigare räcker långt. Det man bör tänka på är att då det är ganska höga frekvenser så är signalerna känsliga för hinder, så det bästa är att ha antennen utomhus med fri sikt mot så mycket himmel som möjligt. För att prova så duger det oftast att sitta nära ett fönster.
Det mesta jag behöver i mjukvaruväg har jag hämtat från ett pdf-dokument på nätet: https://ranous.files.wordpress.com/2018/02/rtl-sdr4linux_quickstartv2-18.pdf
Med hjälp av detta installeras drivrutiner och mjukvara för olika ändamål, samt dump1090 som man kan använda för just ADS-B.
Jag använder ett anpassat startkommando för att dels se paketen bearbetade i realtid, men även skriva data till en JSON-fil.
./dump1090 --interactive --enable-agc --write-json ~/logs
I katalogen ~/logs skapas och uppdateras flera filer, men den jag är intresserad av är aircraft.json.
Denna fil är sedan en enkel sak att läsa med Python och göra om till punkter på en karta i QGIS. Tyvärr så har jag inte hittat ett sätt att automatiskt uppdatera punkterna successivt och uppdatera punkterna på kartan, så det blir att köra skriptet manuellt för att uppdatera. Med QGIS 3 så kommer lager att kunna uppdateras automatiskt med bestämda tidsintervall, men jag tror inte att detta helt kommer att lösa mitt problem här.
Skriptet körs genom Pythonkonsolen i QGIS och skapar ett nytt minneslager med punkter för de poster som är korrekta i JSON-filen. Just nu så skapar jag ett nytt lager varje gång skriptet körs, men det bör inte vara några problem att ”uppdatera” ett och samma lager i stället.
import json from PyQt4.QtCore import QVariant air_count = 0 vl = QgsVectorLayer("Point?crs=epsg:4326", "ADS-B", "memory") pr = vl.dataProvider() # vl.startEditing() pr.addAttributes([QgsField("flight", QVariant.String), QgsField("category", QVariant.String), QgsField("altitude", QVariant.Int), QgsField("vert_rate", QVariant.Int), QgsField("track", QVariant.Int), QgsField("speed", QVariant.Int)]) vl.updateFields() json_data = json.load(open('/home/fm-geo-linux/logs/aircraft.json')) for aircraft in json_data["aircraft"]: try: a_flight = aircraft[u"flight"] except: a_flight = "UNK" try: a_vert_rate = aircraft[u"vert_rate"] except: a_vert_rate = 0 try: a_track = aircraft[u"track"] except: a_track = 0 try: a_speed = aircraft[u"speed"] except: a_speed = 0 try: a_category = aircraft[u"category"] except: a_category = "UNK" try: a_altitude = aircraft[u"altitude"] except: a_altitude = 0 try: a_lat = float(aircraft[u"lat"]) a_lon = aircraft[u"lon"] print("%s %s (%s/%s) at %s/%s feet heading %s at %s knots" % (a_category, a_flight, a_lat, a_lon, a_altitude, a_vert_rate, a_track, a_speed)) fet = QgsFeature() fet.setGeometry( QgsGeometry.fromPoint( QgsPoint( a_lon, a_lat)) ) fet.setAttributes( [a_flight, a_category, a_altitude, a_vert_rate, a_track, a_speed] ) pr.addFeatures( [ fet ] ) air_count += 1 except: print("UNK") #vl.commitChanges() vl.updateExtents() QgsMapLayerRegistry.instance().addMapLayers([vl]) print("%s positioner hittade." % air_count)
Sedan är det bara att skapa lämpliga symboler som beskriver informationen i luften där man befinner sig.
Jag återkommer nog i morgon med hur jag skapat symbolerna i bilden ovan. Förutom flygplan, så kan man göra motsvarande för fartyg till sjöss. För dessa finns det ett system kallat AIS. Det är andra meddelanden och andra frekvenser, men i princip samma sak.
Med två SDR donglar så skulle man därmed i en och samma dator kunna ha realtidsuppföljning på all trafik i luften och till sjöss.
Priset på radion och enkelheten att bygga antenner, samt förhållandevis enkel skriptprogrammering gör att detta är ett utmärkt projekt att ge sig på för att laborera själv eller i olika utbildningar.
vill man bli betydligt mer avancerad så installerar man Gnu Radio Companion där man visuellt kan bygga en mottagare i mjukvara. Det går faktiskt att skapa väldigt avancerade ”radioapparater” på detta sätt, för i princip alla förekommande signaler i frekvensspektrumet. GRC kommer jag dock inte att gå in på närmare den här gången.
Det finns ett program för just AIS, där man kan använda radion för att fånga AIS på båda frekvenserna samtidgt. Vill man dessutom fördjupa sig i momentet flygplansuppföljning så skickar flygplanen ACARS – Aircraft Communications Addressing and Reporting System. Denna data får man koda av då den är digital, men för den händiga så finns det verktyg för sådant.