diff options
| author | Arturs Artamonovs <arturs.artamonovs@protonmail.com> | 2026-09-26 21:53:06 +0100 |
|---|---|---|
| committer | Arturs Artamonovs <arturs.artamonovs@protonmail.com> | 2026-09-26 21:53:06 +0100 |
| commit | 40038b02ce651958ae703c8ecfe5f5578e1f7f09 (patch) | |
| tree | f6bc782c1b1d1a21073e5d40e4136d887f6fa4cd /ADSBDecoder | |
| parent | 505b23afc68ecbb63b8f0a7d44c0b0ad063d5cfd (diff) | |
| download | ADSBDecoder-40038b02ce651958ae703c8ecfe5f5578e1f7f09.tar.gz ADSBDecoder-40038b02ce651958ae703c8ecfe5f5578e1f7f09.zip | |
create adsbdecoder as UI, and renmae adsbdecoder to adsbdecodercli for terminal version
Diffstat (limited to 'ADSBDecoder')
| -rw-r--r-- | ADSBDecoder/ADSBDecoderApp.swift | 32 | ||||
| -rw-r--r-- | ADSBDecoder/AirplaneTracker.swift | 134 | ||||
| -rw-r--r-- | ADSBDecoder/Assets.xcassets/AccentColor.colorset/Contents.json | 11 | ||||
| -rw-r--r-- | ADSBDecoder/Assets.xcassets/AppIcon.appiconset/Contents.json | 58 | ||||
| -rw-r--r-- | ADSBDecoder/Assets.xcassets/Contents.json | 6 | ||||
| -rw-r--r-- | ADSBDecoder/ContentView.swift | 59 | ||||
| -rw-r--r-- | ADSBDecoder/Item.swift | 18 | ||||
| -rw-r--r-- | ADSBDecoder/main.swift | 130 |
8 files changed, 184 insertions, 264 deletions
diff --git a/ADSBDecoder/ADSBDecoderApp.swift b/ADSBDecoder/ADSBDecoderApp.swift new file mode 100644 index 0000000..491dbc5 --- /dev/null +++ b/ADSBDecoder/ADSBDecoderApp.swift @@ -0,0 +1,32 @@ +// +// ADSBDecoderApp.swift +// ADSBDecoder +// +// Created by Jacky Jack on 26/09/2026. +// + +import SwiftUI +import SwiftData + +@main +struct ADSBDecoderApp: App { + var sharedModelContainer: ModelContainer = { + let schema = Schema([ + Item.self, + ]) + let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) + + do { + return try ModelContainer(for: schema, configurations: [modelConfiguration]) + } catch { + fatalError("Could not create ModelContainer: \(error)") + } + }() + + var body: some Scene { + WindowGroup { + ContentView() + } + .modelContainer(sharedModelContainer) + } +} diff --git a/ADSBDecoder/AirplaneTracker.swift b/ADSBDecoder/AirplaneTracker.swift deleted file mode 100644 index 3c1edcf..0000000 --- a/ADSBDecoder/AirplaneTracker.swift +++ /dev/null @@ -1,134 +0,0 @@ -// -// AirplaneTracker.swift -// ADSBDecoder -// -// Created by Jacky Jack on 20/06/2024. -// - -import Foundation - -struct Airplane { - var addressReady:Bool = false - var Address:Int - var ICAOready:Bool = false - var ICAOname:String = "" - var locationReady:Bool = false - var lat:Double = 0.0 - var long:Double = 0.0 - var altitudeReady:Bool = false - var altitude:Int = 0 - var altitudeCount:Int = 0 - var positionDecoder:PositionDecoder = PositionDecoder() -} - -class AirPlaneTracker { - - var airplanes:[Int:Airplane] = [:] - - init () { - - } - - func addDF17Indentification(_ address: Int, _ ICAOname: String) { - if (airplanes[address] == nil) { - airplanes[address] = Airplane(addressReady: true, Address: address,ICAOready: true, ICAOname: ICAOname) - - } else { - if (airplanes[address]?.ICAOname == "") { - airplanes[address]?.ICAOname = ICAOname - airplanes[address]?.ICAOready = true - } - } - } - - func addDF17AirBornPosition(_ address: Int, _ cpr_lat: Int, _ cpr_long: Int, _ alt: Int, _ even: Bool) { - - if airplanes[address] == nil { - return - } - - //deal with altitude - //if airplanes[address] != nil { - if (airplanes[address]?.altitudeReady != true) { - airplanes[address]?.altitudeReady = true - airplanes[address]?.altitude = alt - airplanes[address]?.altitudeCount += 1 - } else { - airplanes[address]?.altitude = alt - airplanes[address]?.altitudeCount += 1 - } - //} - //do the airborn position - if (even) { - airplanes[address]?.positionDecoder.addEvenPosition(UInt32(cpr_lat), UInt32(cpr_long), mstime()) - } else { - - airplanes[address]?.positionDecoder.addOddPosition(UInt32(cpr_lat), UInt32(cpr_long), mstime()) - } - - } - - func getPosition(_ address: Int) -> (Double,Double)? { - if (airplanes[address] == nil) { - return nil - } - - if let airplane = airplanes[address] { - if (airplane.positionDecoder.calcPosition()) { - return airplane.positionDecoder.getPosition() - } - } - - return nil - } - - func getAltitude(_ address: Int) -> Int? { - if (airplanes[address] == nil) { - return nil - } - if let airplane = airplanes[address] { - if airplane.altitudeReady { - return airplane.altitude - } else { - return nil - } - } else { - return nil - } - } - - func getICAOname(_ address: Int) -> String? { - if (airplanes[address] == nil) { - return nil - } - if let airplane = airplanes[address] { - if airplane.ICAOready { - return airplane.ICAOname - } else { - return nil - } - } else { - return nil - } - } - - func printAllICAOnames() { - let extra = false - var once=false - for (address,plane) in airplanes { - if plane.ICAOready { - print(String("\(plane.ICAOname) "), terminator: "") - } - if (extra) { - print("Alitude \(plane.altitudeCount) Positions \(plane.positionDecoder.queue.count)") - } - //if (!once) { - // for i in plane.positionDecoder.queue { - // print("\(i.cpr_lat) \(i.cpr_long) \(i.even)") - // } - // once = true - //} - } - } - -} diff --git a/ADSBDecoder/Assets.xcassets/AccentColor.colorset/Contents.json b/ADSBDecoder/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/ADSBDecoder/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ADSBDecoder/Assets.xcassets/AppIcon.appiconset/Contents.json b/ADSBDecoder/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..3f00db4 --- /dev/null +++ b/ADSBDecoder/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ADSBDecoder/Assets.xcassets/Contents.json b/ADSBDecoder/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/ADSBDecoder/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ADSBDecoder/ContentView.swift b/ADSBDecoder/ContentView.swift new file mode 100644 index 0000000..b1f9a9e --- /dev/null +++ b/ADSBDecoder/ContentView.swift @@ -0,0 +1,59 @@ +// +// ContentView.swift +// ADSBDecoder +// +// Created by Jacky Jack on 26/09/2026. +// + +import SwiftUI +import SwiftData + +struct ContentView: View { + @Environment(\.modelContext) private var modelContext + @Query private var items: [Item] + + var body: some View { + NavigationSplitView { + List { + ForEach(items) { item in + NavigationLink { + Text("Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))") + } label: { + Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard)) + } + } + .onDelete(perform: deleteItems) + } + .navigationSplitViewColumnWidth(min: 180, ideal: 200) + .toolbar { + ToolbarItem { + Button(action: addItem) { + Label("Add Item", systemImage: "plus") + } + } + } + } detail: { + Text("Select an item") + } + } + + private func addItem() { + withAnimation { + let newItem = Item(timestamp: Date()) + modelContext.insert(newItem) + } + } + + private func deleteItems(offsets: IndexSet) { + withAnimation { + for index in offsets { + modelContext.delete(items[index]) + } + } + } +} + +#Preview { + ContentView() + .modelContainer(for: Item.self, inMemory: true) +} diff --git a/ADSBDecoder/Item.swift b/ADSBDecoder/Item.swift new file mode 100644 index 0000000..17b2529 --- /dev/null +++ b/ADSBDecoder/Item.swift @@ -0,0 +1,18 @@ +// +// Item.swift +// ADSBDecoder +// +// Created by Jacky Jack on 26/09/2026. +// + +import Foundation +import SwiftData + +@Model +final class Item { + var timestamp: Date + + init(timestamp: Date) { + self.timestamp = timestamp + } +} diff --git a/ADSBDecoder/main.swift b/ADSBDecoder/main.swift deleted file mode 100644 index ace377f..0000000 --- a/ADSBDecoder/main.swift +++ /dev/null @@ -1,130 +0,0 @@ -// -// main.swift -// ADSBDecoder -// -// Created by Jacky Jack on 28/05/2024. -// - -import Foundation -import ArgumentParser -import RegexBuilder -import SQLite3 - - -struct CommandLineArgs: ParsableCommand { - @Option(name: .shortAndLong) var inputfile: String - @Flag(name: .shortAndLong) var debug:Bool = false - @Flag(name: .shortAndLong) var version:Bool = false - @Flag(name: .shortAndLong) var show_stats:Bool = false -} - -let args = CommandLineArgs.parseOrExit() - -let fileUrl = URL(fileURLWithPath:args.inputfile) -print("File location [\(fileUrl.absoluteString)]") - -//check if file excists -if (checkIfFileExists(fileUrl.path) == false) { - print("Supplied path \(fileUrl.path) doesnt exists") - exit(1) -} - -//load the file with adsb data -var adsb_source = "" -do { - adsb_source = try String(contentsOfFile: fileUrl.path) - print("Loaded \(adsb_source.count) bytes") -} catch { - print("Couldn't load text from a file \(fileUrl.path)") - exit(1) -} - -//gather stats -var q_df = QueryDF() -var q_dftc = QueryDF17TC() -var q_decoded = QueryDecodedMessages() -var q_df17_decoded = QueryDF17TC_decoded() - -//track all airplanes -var tracker = AirPlaneTracker() - -//parse line by line -var count_messages=0 -for line in adsb_source.components(separatedBy: .newlines) { - var found=false - //print("\(cnt) \(line)") - count_messages += 1 - let matchADSBLong = MatchADSBLong() - //if let tokenMatch = try matchADSBLong.prefixMatch(in: line) { - if let tokenMatch = matchADSBLong.prefixMatch(line) { - print("ADSB Long match \(String(tokenMatch.output))") - found = true - let str = String(tokenMatch.output) - let startIndex = str.index(str.startIndex, offsetBy: 1) - let endIndex = str.index(str.endIndex, offsetBy: -2) - let decoder = Decoder(String(str[startIndex...endIndex])) - if decoder.DataFormat == 17 { - if let d17 = decoder.getDataFormat17() { - //print(d17) - q_dftc.addTC(d17.TypeCode) - q_decoded.addDecoded() - if (d17.TypeCode == 4) { - if let indentification = d17.messageIdentification { - tracker.addDF17Indentification(d17.AddressAnnounced, indentification.ICAOName) - } - q_df17_decoded.addDecoded(4) - } else if (d17.TypeCode >= 9 && d17.TypeCode <= 18) { - if let airbornposition = d17.messageAirbornPositon { - tracker.addDF17AirBornPosition( - d17.AddressAnnounced, - airbornposition.Latitude, - airbornposition.Longitude, - airbornposition.Altitude, - airbornposition.CPRFormat == 0 - ) - } - q_df17_decoded.addDecoded(d17.TypeCode) - } else { - q_df17_decoded.addUndecode(d17.TypeCode) - } - } - } else { - q_decoded.addUndecoded() - } - q_df.addDF(decoder.DataFormat) - }; - - /* - if let tokenMatch = try matchADSBShort.prefixMatch(in: line) { - print("\(tokenMatch.output)") - found = true - - q_decoded.addUndecoded() - };*/ - let matchADSBShort = MatchADSBShort() - if let tokenMatch = matchADSBShort.prefixMatch(line) { - print("ADSBShort Match\(tokenMatch.output)") - found = true - - q_decoded.addUndecoded() - } - - if (found == false) { - print("Unknown adsb data line \(line)") - } - - -} - - -if args.show_stats { - print("----STAT----") - //q_df.showStat() - print(q_df) - print(q_dftc) - print(q_decoded) - print(q_df17_decoded) - tracker.printAllICAOnames() - - print("Total message:\(count_messages)") -} |
