// // 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 altQueue: Deque = [] var locQueue: Deque = [] var tagQueue: Deque = [] func getNextTag() -> DataStreamType { if tagQueue.count < 0 { return DataStreamType.EMPTY } return tagQueue[tagQueue.count-1] } func addIcaoName(_ address: Int, _ icaoname: String) { tagQueue.append(DataStreamType.ADSB_ICAO) icaoQueue.append(ADSBICAOname(address: address, ICAOname: icaoname)) } func addAltitude(_ address: Int, _ altitude: Int) { tagQueue.append(DataStreamType.ADSB_ALTITUDE) altQueue.append(ADSBAltitude(address: address, altitude: altitude)) } func addLocation(_ address: Int, _ lat: Double, _ long: Double) { tagQueue.append(DataStreamType.ADSB_LOCATION) locQueue.append(ADSBLocation(address: address, lat: lat, long: long)) } func getIcaoName() -> ADSBICAOname { if tagQueue.count < 1 { print("ADSB tag Queue is empry") return ADSBICAOname(address:0,ICAOname: "") } let tag = tagQueue[tagQueue.count-1] if tag != DataStreamType.ADSB_ICAO { print("ADSB Queue empty") return ADSBICAOname(address:0,ICAOname: "") } tagQueue.removeLast() return icaoQueue.popLast()! } func getAltitude() -> ADSBAltitude { if tagQueue.count < 1 { print("ADSB tag Queue is empry") return ADSBAltitude(address:0,altitude:0) } let tag = tagQueue[tagQueue.count-1] if tag != DataStreamType.ADSB_ALTITUDE { print("ADSB Queue empty") return ADSBAltitude(address:0,altitude:0) } tagQueue.removeLast() return altQueue.popLast()! } func getLocation() -> ADSBLocation { if tagQueue.count < 1 { print("ADSB tag Queue is empry") return ADSBLocation(address:0,lat:0.0,long:0.0) } let tag = tagQueue[tagQueue.count-1] if tag != DataStreamType.ADSB_LOCATION { print("ADSB Queue empty") return ADSBLocation(address:0,lat:0.0,long:0.0) } tagQueue.removeLast() return locQueue.popLast()! } func haveNum(_ num: Int) -> Bool { if (tagQueue.count > num) { return true } return false } } class ADSBFileRunner { var filename: URL //track all airplanes var tracker = AirPlaneTracker() var adsb_source: String = "" var adsb_tag_stream = ADSBDataQueue() 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) 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)") } } //try to free the string after decoded //adsb_source = "" } }