From 30a23711626c5afe7f86ca34fbc489d7979b71d9 Mon Sep 17 00:00:00 2001 From: Arturs Artamonovs Date: Thu, 8 Aug 2024 12:25:55 +0100 Subject: Live data works --- LearnMapKit/ADSBDataQueue.swift | 122 ++++++++++++++++++ LearnMapKit/ADSBFileRunner.swift | 149 ++++++++++++++++++++++ LearnMapKit/ADSBNetRunner.swift | 111 +++++++++++++++++ LearnMapKit/ADSBRunner.swift | 262 --------------------------------------- LearnMapKit/FlighState.swift | 126 ++++++++++++++----- 5 files changed, 476 insertions(+), 294 deletions(-) create mode 100644 LearnMapKit/ADSBDataQueue.swift create mode 100644 LearnMapKit/ADSBFileRunner.swift create mode 100644 LearnMapKit/ADSBNetRunner.swift delete mode 100644 LearnMapKit/ADSBRunner.swift (limited to 'LearnMapKit') diff --git a/LearnMapKit/ADSBDataQueue.swift b/LearnMapKit/ADSBDataQueue.swift new file mode 100644 index 0000000..ada0ab5 --- /dev/null +++ b/LearnMapKit/ADSBDataQueue.swift @@ -0,0 +1,122 @@ +// +// ADSBDataQueue.swift +// LearnMapKit +// +// Created by Jacky Jack on 05/08/2024. +// + +import Foundation +import Collections + +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 +} + +enum DataStreamType { + case EMPTY + case ADSB_ICAO + case ADSB_LOCATION + case ADSB_ALTITUDE +} + +//get stream of decoded data, to tagged stream so all can be processed in sequence +class ADSBDataQueue { + //var icaoQueue: Deque = [] + var icaoArray: Array = [] + var altQueue: Deque = [] + var locQueue: Deque = [] + //var tagQueue: Deque<> = [] + var tagArray: Array = [] + + func getNextTag() -> DataStreamType { + if tagArray.count < 0 { + return DataStreamType.EMPTY + } + return tagArray[tagArray.count-1] + } + + func addIcaoName(_ address: Int, _ icaoname: String) { + tagArray.append(DataStreamType.ADSB_ICAO) + icaoArray.append(ADSBICAOname(address: address, ICAOname: icaoname)) + } + + func addAltitude(_ address: Int, _ altitude: Int) { + tagArray.append(DataStreamType.ADSB_ALTITUDE) + altQueue.append(ADSBAltitude(address: address, altitude: altitude)) + } + + func addLocation(_ address: Int, _ lat: Double, _ long: Double) { + tagArray.append(DataStreamType.ADSB_LOCATION) + locQueue.append(ADSBLocation(address: address, lat: lat, long: long)) + } + + func getIcaoName() -> ADSBICAOname { + if tagArray.count < 1 { + print("ADSB tag Queue is empty") + return ADSBICAOname(address:0,ICAOname: "TEmpty") + } + let tag = tagArray[tagArray.count-1] + if tag != DataStreamType.ADSB_ICAO { + print("ADSB Queue empty") + return ADSBICAOname(address:0,ICAOname: "QEmpty") + } + tagArray.removeLast() + var ret_icao_name = ADSBICAOname(address:0, ICAOname: "Default") + if let last_icao_name = icaoArray.popLast() { + ret_icao_name = last_icao_name + } + return ret_icao_name + } + + func getAltitude() -> ADSBAltitude { + if tagArray.count < 1 { + print("ADSB tag Queue is empty") + return ADSBAltitude(address:0,altitude:0) + } + let tag = tagArray[tagArray.count-1] + if tag != DataStreamType.ADSB_ALTITUDE { + print("ADSB Queue empty") + return ADSBAltitude(address:0,altitude:0) + } + tagArray.removeLast() + return altQueue.popLast()! + } + + func getLocation() -> ADSBLocation { + if tagArray.count < 1 { + print("ADSB tag Queue is empry") + return ADSBLocation(address:0,lat:0.0,long:0.0) + } + let tag = tagArray[tagArray.count-1] + if tag != DataStreamType.ADSB_LOCATION { + print("ADSB Queue empty") + return ADSBLocation(address:0,lat:0.0,long:0.0) + } + tagArray.removeLast() + return locQueue.popLast()! + } + + func haveNum(_ num: Int) -> Bool { + if (tagArray.count > num) { + return true + } + return false + } + + func getCount() -> Int { + return tagArray.count + } +} diff --git a/LearnMapKit/ADSBFileRunner.swift b/LearnMapKit/ADSBFileRunner.swift new file mode 100644 index 0000000..d61b91b --- /dev/null +++ b/LearnMapKit/ADSBFileRunner.swift @@ -0,0 +1,149 @@ +// +// ADSBRunner.swift +// LearnMapKit +// +// Created by Jacky Jack on 28/06/2024. +// + +import Foundation +import Collections + +class ADSBFileRunner { + var filename: URL + //track all airplanes + var tracker = AirPlaneTracker() + var adsb_source: String = "" + //should make it outside and use here? + var adsb_tag_stream = ADSBDataQueue() + private var decoded_status: Bool = false + + init(filename:String) { + self.filename = URL(fileURLWithPath:filename) + } + + init() { + self.filename = URL(fileURLWithPath:"") + } + + func setFileName(_ filename:String) { + self.filename = URL(fileURLWithPath: filename) + } + + func openFile() { + if self.filename == URL(fileURLWithPath:"") { + print("File name for ADSBRunner not specified") + return + } + 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) \(error)") + exit(1) + } + print("If there anything new in file") + } + + func decodeFromFile() { + 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) + adsb_tag_stream.addIcaoName(d17.AddressAnnounced, tracker.getICAOname(d17.AddressAnnounced)!) + } + } 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)") + adsb_tag_stream.addAltitude(d17.AddressAnnounced, tracker.getAltitude(d17.AddressAnnounced)!) + let location = tracker.getPosition(d17.AddressAnnounced)! + adsb_tag_stream.addLocation(d17.AddressAnnounced, location.0, location.1) + } + } + } + } + } + }; + } catch { + print("Error") + } + + if (found == false) { + print("Unknown adsb data line \(line)") + } + } + self.decoded_status = true + //try to free the string after decoded + //adsb_source = "" + for i in 0.. Bool { + return self.decoded_status + } + + func getPlainData(_ num_queries: Int) -> ADSBDataQueue { + var ret = ADSBDataQueue() + if adsb_tag_stream.haveNum(num_queries) { + + for _ in 0.. Int { + return self.adsb_tag_stream.getCount() + } +} + + diff --git a/LearnMapKit/ADSBNetRunner.swift b/LearnMapKit/ADSBNetRunner.swift new file mode 100644 index 0000000..7125615 --- /dev/null +++ b/LearnMapKit/ADSBNetRunner.swift @@ -0,0 +1,111 @@ +// +// ADSBNetRunner.swift +// LearnMapKit +// +// Created by Jacky Jack on 05/08/2024. +// + +import Foundation + +class ADSBNetRunner { + var address = "" + var port = 0 + var tracker = AirPlaneTracker() + var adsb_tag_stream = ADSBDataQueue() + var ADSBClient:NetADSBDecoder! + var timer: Timer? + + init(address:String, port:Int) { + self.address = address + self.port = port + } + + func start() { + var found: Bool = false + let adsb_net_decoder = NetADSBDecoder(host: self.address, port: self.port) + //var _adsb_tag_stream = ADSBDataQueue() + //var _tracker = AirPlaneTracker() + print("_start ADSBNetRunner") + timer = Timer.scheduledTimer( + withTimeInterval: 1, + repeats: true + ) { _ in + print("Timer drain queue") + print("\(adsb_net_decoder.msgarray.message_array.count)") + if adsb_net_decoder.msgarray.message_array.count > 0 { + print(adsb_net_decoder.msgarray.message_array.count) + for _ in 0..= 9 && d17.TypeCode <= 18) { + if let airbornposition = d17.messageAirbornPositon { + self.tracker.addDF17AirBornPosition( + d17.AddressAnnounced, + airbornposition.Latitude, + airbornposition.Longitude, + airbornposition.Altitude, + airbornposition.CPRFormat == 0 + ) + if let position = self.tracker.getPosition(d17.AddressAnnounced) { + print("position: \(position)") + self.adsb_tag_stream.addAltitude(d17.AddressAnnounced, self.tracker.getAltitude(d17.AddressAnnounced)!) + let location = self.tracker.getPosition(d17.AddressAnnounced)! + self.adsb_tag_stream.addLocation(d17.AddressAnnounced, location.0, location.1) + } + } + } + } + } + }; + } catch { + print("Error") + } + + if (found == false) { + print("Unknown adsb data line [\(msg)]") + } + } + } + } + + } + + DispatchQueue.global(qos: .background).async { + do { + try adsb_net_decoder.start() + } catch let error { + print("Error: \(error.localizedDescription)") + adsb_net_decoder.stop() + } + } + } + + func getDataOut() { + + } + + func stop() { + + } + + func getCount() -> Int { + return self.adsb_tag_stream.getCount() + } +} diff --git a/LearnMapKit/ADSBRunner.swift b/LearnMapKit/ADSBRunner.swift deleted file mode 100644 index e05978c..0000000 --- a/LearnMapKit/ADSBRunner.swift +++ /dev/null @@ -1,262 +0,0 @@ -// -// ADSBRunner.swift -// LearnMapKit -// -// Created by Jacky Jack on 28/06/2024. -// - -import Foundation -import Collections - -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 -} - -enum DataStreamType { - case EMPTY - case ADSB_ICAO - case ADSB_LOCATION - case ADSB_ALTITUDE -} - -//get stream of decoded data, to tagged stream so all can be processed in sequence -class ADSBDataQueue { - //var icaoQueue: Deque = [] - var icaoArray: Array = [] - var altQueue: Deque = [] - var locQueue: Deque = [] - //var tagQueue: Deque<> = [] - var tagArray: Array = [] - - func getNextTag() -> DataStreamType { - if tagArray.count < 0 { - return DataStreamType.EMPTY - } - return tagArray[tagArray.count-1] - } - - func addIcaoName(_ address: Int, _ icaoname: String) { - tagArray.append(DataStreamType.ADSB_ICAO) - icaoArray.append(ADSBICAOname(address: address, ICAOname: icaoname)) - } - - func addAltitude(_ address: Int, _ altitude: Int) { - tagArray.append(DataStreamType.ADSB_ALTITUDE) - altQueue.append(ADSBAltitude(address: address, altitude: altitude)) - } - - func addLocation(_ address: Int, _ lat: Double, _ long: Double) { - tagArray.append(DataStreamType.ADSB_LOCATION) - locQueue.append(ADSBLocation(address: address, lat: lat, long: long)) - } - - func getIcaoName() -> ADSBICAOname { - if tagArray.count < 1 { - print("ADSB tag Queue is empty") - return ADSBICAOname(address:0,ICAOname: "TEmpty") - } - let tag = tagArray[tagArray.count-1] - if tag != DataStreamType.ADSB_ICAO { - print("ADSB Queue empty") - return ADSBICAOname(address:0,ICAOname: "QEmpty") - } - tagArray.removeLast() - var ret_icao_name = ADSBICAOname(address:0, ICAOname: "Default") - if let last_icao_name = icaoArray.popLast() { - ret_icao_name = last_icao_name - } - return ret_icao_name - } - - func getAltitude() -> ADSBAltitude { - if tagArray.count < 1 { - print("ADSB tag Queue is empry") - return ADSBAltitude(address:0,altitude:0) - } - let tag = tagArray[tagArray.count-1] - if tag != DataStreamType.ADSB_ALTITUDE { - print("ADSB Queue empty") - return ADSBAltitude(address:0,altitude:0) - } - tagArray.removeLast() - return altQueue.popLast()! - } - - func getLocation() -> ADSBLocation { - if tagArray.count < 1 { - print("ADSB tag Queue is empry") - return ADSBLocation(address:0,lat:0.0,long:0.0) - } - let tag = tagArray[tagArray.count-1] - if tag != DataStreamType.ADSB_LOCATION { - print("ADSB Queue empty") - return ADSBLocation(address:0,lat:0.0,long:0.0) - } - tagArray.removeLast() - return locQueue.popLast()! - } - - func haveNum(_ num: Int) -> Bool { - if (tagArray.count > num) { - return true - } - return false - } - - func getCount() -> Int { - return tagArray.count - } -} - -class ADSBFileRunner { - - var filename: URL - //track all airplanes - var tracker = AirPlaneTracker() - var adsb_source: String = "" - //should make it outside and use here? - var adsb_tag_stream = ADSBDataQueue() - private var decoded_status: Bool = false - - init(filename:String) { - self.filename = URL(fileURLWithPath:filename) - } - - init() { - self.filename = URL(fileURLWithPath:"") - } - - func setFileName(_ filename:String) { - self.filename = URL(fileURLWithPath: filename) - } - - func openFile() { - if self.filename == URL(fileURLWithPath:"") { - print("File name for ADSBRunner not specified") - return - } - 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) \(error)") - 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) - adsb_tag_stream.addIcaoName(d17.AddressAnnounced, tracker.getICAOname(d17.AddressAnnounced)!) - } - } 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)") - adsb_tag_stream.addAltitude(d17.AddressAnnounced, tracker.getAltitude(d17.AddressAnnounced)!) - let location = tracker.getPosition(d17.AddressAnnounced)! - adsb_tag_stream.addLocation(d17.AddressAnnounced, location.0, location.1) - - } - } - } - } - } - }; - } catch { - print("Error") - } - - if (found == false) { - print("Unknown adsb data line \(line)") - } - } - self.decoded_status = true - //try to free the string after decoded - //adsb_source = "" - for i in 0.. Bool { - return self.decoded_status - } - - func getPlainData(_ num_queries: Int) -> ADSBDataQueue { - var ret = ADSBDataQueue() - if adsb_tag_stream.haveNum(num_queries) { - - for _ in 0.. Int { - return self.adsb_tag_stream.getCount() - } -} diff --git a/LearnMapKit/FlighState.swift b/LearnMapKit/FlighState.swift index cfb34f1..446b491 100644 --- a/LearnMapKit/FlighState.swift +++ b/LearnMapKit/FlighState.swift @@ -8,6 +8,7 @@ import Foundation import Collections + class FlightTracker { var last_time_seen: Int = 0 var ICAOName_avaliable = false @@ -27,60 +28,121 @@ class FlightState: ObservableObject { @Published var flight:[Int:FlightTracker] = [:] //configuration options + let sourceFile = false let default_file_path = "/Users/jackyjack/Downloads/2024_05_27_raw_adsb.txt" let process_per_second = 120 + let sourceDump1090Server = true + let dump1090address = "192.168.4.201" + let dump1090port = 30002 + init() { var count = 0 //let ADSBtask = ADSBFileRunner(filename: "") - let adsb_file = ADSBFileRunner(filename: self.default_file_path) + //let adsb_net = ADSBNetRunner(address: dump1090address, port: dump1090port) - DispatchQueue.global(qos: .background).sync { - print("Open file") - adsb_file.openFile() - adsb_file.readFile() - } - - DispatchQueue.global(qos: .background).async { - print("Start decoding data") - adsb_file.decode() - print("Stop decoding data") + if sourceFile { + let adsb_file = ADSBFileRunner(filename: self.default_file_path) + DispatchQueue.global(qos: .background).sync { + print("Open file") + adsb_file.openFile() + adsb_file.readFile() + } + + DispatchQueue.global(qos: .background).async { + print("Start decoding data") + adsb_file.decodeFromFile() + print("Stop decoding data") + } + + //once a second read some data from decoded queue + timer = Timer.scheduledTimer( + withTimeInterval: 1, + repeats: true + ) { _ in + //get the 10 entries if there is + if adsb_file.jobDone() { + print("Decoding done let get some data \(adsb_file.getCount())") + //if adsb_file + if adsb_file.getCount() > self.process_per_second { + let data = adsb_file.getPlainData(self.process_per_second) + //print(data.getCount()) + for idx in 0.. self.process_per_second { - let data = adsb_file.getPlainData(self.process_per_second) - //print(data.getCount()) - for idx in 0.. 0 { + print(ADSBClient.msgarray.message_array.count) + for i in 0.. 0 { + print("Process onse a second") + for idx in 0..