From cc5272cd4be2ab55fa8411790082be408b586be9 Mon Sep 17 00:00:00 2001 From: Arturs Artamonovs Date: Tue, 2 Jul 2024 10:07:49 +0100 Subject: Make ADSBDecoder more modular. Integrate into LearnMapKit --- ADSBDecoder/ADSBRegEx.swift | 35 +++++++++++++ ADSBDecoder/AirplaneTracker.swift | 31 +++++++++-- ADSBDecoder/Utils.swift | 23 +++++++++ ADSBDecoder/main.swift | 40 --------------- LearnMapKit/ADSBRunner.swift | 105 ++++++++++++++++++++++++++++++++++++++ LearnMapKit/ContentView.swift | 29 +++++++++-- LearnMapKit/FlighState.swift | 45 ++++++++++++++++ LearnMapKit/LearnMapKitApp.swift | 45 +++++++++++++++- 8 files changed, 304 insertions(+), 49 deletions(-) create mode 100644 ADSBDecoder/ADSBRegEx.swift create mode 100644 ADSBDecoder/Utils.swift create mode 100644 LearnMapKit/ADSBRunner.swift create mode 100644 LearnMapKit/FlighState.swift diff --git a/ADSBDecoder/ADSBRegEx.swift b/ADSBDecoder/ADSBRegEx.swift new file mode 100644 index 0000000..e9ebe17 --- /dev/null +++ b/ADSBDecoder/ADSBRegEx.swift @@ -0,0 +1,35 @@ +// +// ADSBRegEx.swift +// ADSBDecoder +// +// Created by Jacky Jack on 30/06/2024. +// + +import Foundation +import RegexBuilder + +let matchADSBLong = Regex { + Anchor.startOfLine + "*" + + Repeat( + CharacterClass( + ("a"..."f"), + ("0"..."9") + ) + ,count:28) + + ";" +} + +let matchADSBShort = Regex { + Anchor.startOfLine + "*" + Repeat( + CharacterClass( + ("a"..."f"), + ("0"..."9") + ) + ,count:14) + ";" +} diff --git a/ADSBDecoder/AirplaneTracker.swift b/ADSBDecoder/AirplaneTracker.swift index 0ac8bfc..f346201 100644 --- a/ADSBDecoder/AirplaneTracker.swift +++ b/ADSBDecoder/AirplaneTracker.swift @@ -83,9 +83,34 @@ class AirPlaneTracker { return nil } - func getAltitude() { - - print("not implemented") + 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() { diff --git a/ADSBDecoder/Utils.swift b/ADSBDecoder/Utils.swift new file mode 100644 index 0000000..7a7f177 --- /dev/null +++ b/ADSBDecoder/Utils.swift @@ -0,0 +1,23 @@ +// +// Utils.swift +// ADSBDecoder +// +// Created by Jacky Jack on 30/06/2024. +// + +import Foundation + +//return true if file excists +func checkIfFileExists(_ fname: String) -> Bool { + let fm = FileManager.default + if fm.fileExists(atPath: fname) { + return true + } + return false +} + +//get current run directory +func getCurrentDirPath() -> String { + return Process().currentDirectoryPath +} + diff --git a/ADSBDecoder/main.swift b/ADSBDecoder/main.swift index a346fbb..3148a9d 100644 --- a/ADSBDecoder/main.swift +++ b/ADSBDecoder/main.swift @@ -10,19 +10,7 @@ import ArgumentParser import RegexBuilder import SQLite3 -//return true if file excists -func checkIfFileExists(_ fname: String) -> Bool { - let fm = FileManager.default - if fm.fileExists(atPath: fname) { - return true - } - return false -} -//get current run directory -func getCurrentDirPath() -> String { - return Process().currentDirectoryPath -} struct CommandLineArgs: ParsableCommand { @Option(name: .shortAndLong) var inputfile: String @@ -52,34 +40,6 @@ do { exit(1) } - - -let matchADSBLong = Regex { - Anchor.startOfLine - "*" - - Repeat( - CharacterClass( - ("a"..."f"), - ("0"..."9") - ) - ,count:28) - - ";" -} - -let matchADSBShort = Regex { - Anchor.startOfLine - "*" - Repeat( - CharacterClass( - ("a"..."f"), - ("0"..."9") - ) - ,count:14) - ";" -} - //gather stats var q_df = QueryDF() var q_dftc = QueryDF17TC() diff --git a/LearnMapKit/ADSBRunner.swift b/LearnMapKit/ADSBRunner.swift new file mode 100644 index 0000000..0f09759 --- /dev/null +++ b/LearnMapKit/ADSBRunner.swift @@ -0,0 +1,105 @@ +// +// ADSBRunner.swift +// LearnMapKit +// +// Created by Jacky Jack on 28/06/2024. +// + +import Foundation + +struct ADSBLocation { + let address: Int + let lat: Double + let long: Double + //let alt: Int +} + +struct ADSBAltitude { + let address: Int + let altitude: Int +} + +struct ADSBICAOname { + let address: Int + let ICAOname: String +} + +class ADSBFileRunner { + + var filename: URL + //track all airplanes + var tracker = AirPlaneTracker() + var adsb_source: String = "" + + init(filename:String) { + self.filename = URL(fileURLWithPath:filename) + } + + func openFile() { + print("File location [\(filename.absoluteString)]") + + //check if file excists + if (checkIfFileExists(filename.path) == false) { + print("Supplied path \(filename.path) doesnt exists") + exit(1) + } + } + + func readFile() { + //load the file with adsb data + do { + adsb_source = try String(contentsOfFile: filename.path) + print("Loaded \(adsb_source.count) bytes") + } catch { + print("Couldn't load text from a file \(filename.path)") + exit(1) + } + print("If there anything new in file") + } + + func decode() { + for line in self.adsb_source.components(separatedBy: .newlines) { + var found=false + do { + if let tokenMatch = try matchADSBLong.prefixMatch(in: line) { + //print("\(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() { + if (d17.TypeCode == 4) { + if let indentification = d17.messageIdentification { + tracker.addDF17Indentification(d17.AddressAnnounced, indentification.ICAOName) + } + } 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 + ) + if let position = tracker.getPosition(d17.AddressAnnounced) { + print("position: \(position)") + } + } + } + } + } + }; + } catch { + print("Error") + } + + if (found == false) { + print("Unknown adsb data line \(line)") + } + } + //try to free the string after decoded + //adsb_source = "" + } +} diff --git a/LearnMapKit/ContentView.swift b/LearnMapKit/ContentView.swift index d9e3377..08f4192 100644 --- a/LearnMapKit/ContentView.swift +++ b/LearnMapKit/ContentView.swift @@ -7,11 +7,15 @@ import SwiftUI import MapKit +import Collections struct ContentView: View { - @State private var region = MKCoordinateRegion() + @State private var isImporting = false + + @Binding var pos_queue: Deque + @EnvironmentObject var evilClass: FlightState let initialPosition: MapCameraPosition = { let center = CLLocationCoordinate2D(latitude: 55.90159, longitude:-3.53154) @@ -49,6 +53,7 @@ struct ContentView: View { } Button("7") { print("Pressed 7") + print(evilClass.update_postions.count) } } .border(.blue) @@ -105,6 +110,22 @@ struct ContentView: View { .border(.green) .layoutPriority(1) .mapStyle(.hybrid(elevation: .realistic)) + .toolbar { + ToolbarItem() { + Button { + isImporting = true + } label: { + Label("Import file", systemImage: "square.and.arrow.down") + } + } + } .fileImporter(isPresented: $isImporting, allowedContentTypes: [.text], allowsMultipleSelection: false) { + result in switch result { + case .success(let files): + print(files) + case .failure(let error): + print(error) + } + } } @@ -114,6 +135,6 @@ struct ContentView: View { } } -#Preview { - ContentView() -} +//#Preview { + //ContentView(pos_queue: pos_queue) +//} diff --git a/LearnMapKit/FlighState.swift b/LearnMapKit/FlighState.swift new file mode 100644 index 0000000..f3895cb --- /dev/null +++ b/LearnMapKit/FlighState.swift @@ -0,0 +1,45 @@ +// +// FlighState.swift +// LearnMapKit +// +// Created by Jacky Jack on 30/06/2024. +// + +import Foundation +import Collections + +class FlightState: ObservableObject { + @Published var name = "Some Name" + @Published var isEnabled = false + var timer: Timer? + var update_postions: Deque = [] + var fromFile: Bool = false + init() { + var count = 0 + + let ADSBtask = ADSBFileRunner(filename: "") + timer = Timer.scheduledTimer( + withTimeInterval: 1, + repeats: true + ) { _ in + + //queue.append(MapADSBData(lat: 0.0, long: 0.0, alt: 1)) + + //let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in + print("Evil object \(count)") + //ADSBtask.runFromFile() + self.update_postions.append(ADSBLocation(address: 0, lat: 0.0, long: 0.0)) + // print(update_postions.count) + count += 1 + //} + } + } + init(filename: String) { + + } + + func loadFromFile() { + + } +} + diff --git a/LearnMapKit/LearnMapKitApp.swift b/LearnMapKit/LearnMapKitApp.swift index eebb4b8..5fa170a 100644 --- a/LearnMapKit/LearnMapKitApp.swift +++ b/LearnMapKit/LearnMapKitApp.swift @@ -6,12 +6,53 @@ // import SwiftUI +import Collections + +//https://www.hackingwithswift.com/quick-start/swiftui/how-to-run-code-when-your-app-launches + + @main struct LearnMapKitApp: App { + + @State var queue: Deque = [] + + @StateObject private var flightState = FlightState() + + init() { + print("Init app") + var update_postions: Deque = [] + DispatchQueue.global(qos: .background).sync { + print("Dispatch") + //var count = 0 + + + //let ADSBtask = ADSBRunner() + //queue.append(MapADSBData(lat: 0.0, long: 0.0, alt: 1)) + /* + let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in + print("Timer fired! \(count)") + ADSBtask.runFromFile() + update_postions.append(MapADSBData(lat: 0.0, long: 0.0, alt: 1)) + print(update_postions.count) + count += 1 + }*/ + print("Exit dispatch") + } + + //push all new data to state queue from a runner + DispatchQueue.global(qos: .background).sync { + // Update the UI on the main thread + let c = queue.count + } + } + + + var body: some Scene { WindowGroup { - ContentView() - } + ContentView(pos_queue: $queue) + }.environmentObject(flightState) } + } -- cgit v1.2.3