From 40038b02ce651958ae703c8ecfe5f5578e1f7f09 Mon Sep 17 00:00:00 2001 From: Arturs Artamonovs Date: Sat, 26 Sep 2026 21:53:06 +0100 Subject: create adsbdecoder as UI, and renmae adsbdecoder to adsbdecodercli for terminal version --- ADSBDecoder.xcodeproj/project.pbxproj | 568 +++++++++++++++------ .../xcschemes/xcschememanagement.plist | 59 ++- ADSBDecoder/ADSBDecoderApp.swift | 32 ++ ADSBDecoder/AirplaneTracker.swift | 134 ----- .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 58 +++ ADSBDecoder/Assets.xcassets/Contents.json | 6 + ADSBDecoder/ContentView.swift | 59 +++ ADSBDecoder/Item.swift | 18 + ADSBDecoder/main.swift | 130 ----- ADSBDecoderCLI/main.swift | 131 +++++ ADSBDecoderFramework/ADSBRegEx.swift | 12 +- ADSBDecoderFramework/AirplaneTracker.swift | 120 +++++ ADSBDecoderFramework/Decoder.swift | 52 +- ADSBDecoderFramework/PositionDecoder.swift | 52 +- ADSBDecoderFramework/Query.swift | 68 +-- ADSBDecoderTests/ADSBDecoderTests.swift | 19 + ADSBDecoderUITests/ADSBDecoderUITests.swift | 43 ++ ADSBStats/main.swift | 3 +- LearnMapKit/ADSBFileRunner.swift | 1 + LearnMapKit/ADSBNetRunner.swift | 5 +- LearnMapKit/FlighState.swift | 10 +- Test/main.swift | 3 + 23 files changed, 1066 insertions(+), 528 deletions(-) create mode 100644 ADSBDecoder/ADSBDecoderApp.swift delete mode 100644 ADSBDecoder/AirplaneTracker.swift create mode 100644 ADSBDecoder/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 ADSBDecoder/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ADSBDecoder/Assets.xcassets/Contents.json create mode 100644 ADSBDecoder/ContentView.swift create mode 100644 ADSBDecoder/Item.swift delete mode 100644 ADSBDecoder/main.swift create mode 100644 ADSBDecoderCLI/main.swift create mode 100644 ADSBDecoderFramework/AirplaneTracker.swift create mode 100644 ADSBDecoderTests/ADSBDecoderTests.swift create mode 100644 ADSBDecoderUITests/ADSBDecoderUITests.swift diff --git a/ADSBDecoder.xcodeproj/project.pbxproj b/ADSBDecoder.xcodeproj/project.pbxproj index fbca833..ee775e0 100644 --- a/ADSBDecoder.xcodeproj/project.pbxproj +++ b/ADSBDecoder.xcodeproj/project.pbxproj @@ -10,9 +10,7 @@ 8D4F383A3065267F00EA3890 /* ADSBDecoderFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D4F382F3065267E00EA3890 /* ADSBDecoderFramework.framework */; }; 8D4F38443065267F00EA3890 /* ADSBDecoderFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D4F382F3065267E00EA3890 /* ADSBDecoderFramework.framework */; }; 8D4F38453065267F00EA3890 /* ADSBDecoderFramework.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8D4F382F3065267E00EA3890 /* ADSBDecoderFramework.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 8D4F3852306528DE00EA3890 /* ADSBDecoderFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D4F382F3065267E00EA3890 /* ADSBDecoderFramework.framework */; }; 8D4F385F30652A9200EA3890 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = 8D4F385E30652A9200EA3890 /* Collections */; }; - 8D4F386030652B4A00EA3890 /* AirplaneTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DB347C42C242BAC00F3C020 /* AirplaneTracker.swift */; }; 8D8480EF2C56344B007ACD95 /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = 8D8480EE2C56344B007ACD95 /* ArgumentParser */; }; 8D8480F12C60C79E007ACD95 /* ADSBDataQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8480F02C60C79E007ACD95 /* ADSBDataQueue.swift */; }; 8D8480F32C60C7E6007ACD95 /* ADSBNetRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D8480F22C60C7E6007ACD95 /* ADSBNetRunner.swift */; }; @@ -20,21 +18,20 @@ 8D93B67F2C3FEA0000C91865 /* NIO in Frameworks */ = {isa = PBXBuildFile; productRef = 8D93B67E2C3FEA0000C91865 /* NIO */; }; 8D93B6812C3FEA5600C91865 /* NIO in Frameworks */ = {isa = PBXBuildFile; productRef = 8D93B6802C3FEA5600C91865 /* NIO */; }; 8D93B68A2C45986700C91865 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B6892C45986700C91865 /* main.swift */; }; - 8D93B6942C4598E300C91865 /* AirplaneTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DB347C42C242BAC00F3C020 /* AirplaneTracker.swift */; }; 8D93B6962C45992F00C91865 /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = 8D93B6952C45992F00C91865 /* ArgumentParser */; }; 8D93B6982C45993600C91865 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = 8D93B6972C45993600C91865 /* Collections */; }; 8D93B69A2C4A665B00C91865 /* NetConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B6992C4A665B00C91865 /* NetConfigView.swift */; }; 8D93B69C2C4A727300C91865 /* NetworkConfigure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B69B2C4A727300C91865 /* NetworkConfigure.swift */; }; 8D93B69E2C4A788F00C91865 /* NetADSBDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B69D2C4A788F00C91865 /* NetADSBDecoder.swift */; }; 8D93B69F2C4A7A0700C91865 /* NetADSBDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B69D2C4A788F00C91865 /* NetADSBDecoder.swift */; }; - 8DB347C32C1C53ED00F3C020 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = 8DB347C22C1C53ED00F3C020 /* Collections */; }; - 8DB347C52C242BAC00F3C020 /* AirplaneTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DB347C42C242BAC00F3C020 /* AirplaneTracker.swift */; }; + 8DCF557A3068652B00C724BA /* ADSBDecoderFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D4F382F3065267E00EA3890 /* ADSBDecoderFramework.framework */; }; + 8DCF557B306865A300C724BA /* ADSBDecoderFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D4F382F3065267E00EA3890 /* ADSBDecoderFramework.framework */; }; + 8DCF557F3068673400C724BA /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = 8DCF557E3068673400C724BA /* ArgumentParser */; }; + 8DCF55813068678500C724BA /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = 8DCF55803068678500C724BA /* ArgumentParser */; }; + 8DCF55833068678900C724BA /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = 8DCF55823068678900C724BA /* Collections */; }; 8DEC6F2E2C2E9C3000AC6209 /* ADSBFileRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEC6F2D2C2E9C3000AC6209 /* ADSBFileRunner.swift */; }; 8DEC6F302C2E9F0E00AC6209 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = 8DEC6F2F2C2E9F0E00AC6209 /* Collections */; }; 8DEC6F322C31530C00AC6209 /* FlighState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEC6F312C31530C00AC6209 /* FlighState.swift */; }; - 8DF756632C0595AA008E8DFF /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DF756622C0595AA008E8DFF /* main.swift */; }; - 8DF7566C2C0595F6008E8DFF /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = 8DF7566B2C0595F6008E8DFF /* ArgumentParser */; }; - 8DF756742C059969008E8DFF /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DF756732C059969008E8DFF /* main.swift */; }; 8DF756852C10556A008E8DFF /* LearnMapKitApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DF756842C10556A008E8DFF /* LearnMapKitApp.swift */; }; 8DF756872C10556A008E8DFF /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DF756862C10556A008E8DFF /* ContentView.swift */; }; 8DF756892C10556C008E8DFF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8DF756882C10556C008E8DFF /* Assets.xcassets */; }; @@ -66,6 +63,20 @@ remoteGlobalIDString = 8D4F382E3065267E00EA3890; remoteInfo = ADSBDecoderFramework; }; + 8DCF5562306864B800C724BA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8DF756572C0595AA008E8DFF /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DCF5552306864B700C724BA; + remoteInfo = ADSBDecoder; + }; + 8DCF556C306864B800C724BA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8DF756572C0595AA008E8DFF /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DCF5552306864B700C724BA; + remoteInfo = ADSBDecoder; + }; 8DF756932C10556C008E8DFF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 8DF756572C0595AA008E8DFF /* Project object */; @@ -112,16 +123,7 @@ ); runOnlyForDeploymentPostprocessing = 1; }; - 8DF7565D2C0595AA008E8DFF /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 8DF7566F2C059969008E8DFF /* CopyFiles */ = { + 8DCF5546306863F500C724BA /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/share/man/man1/; @@ -144,12 +146,12 @@ 8D93B6992C4A665B00C91865 /* NetConfigView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetConfigView.swift; sourceTree = ""; }; 8D93B69B2C4A727300C91865 /* NetworkConfigure.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkConfigure.swift; sourceTree = ""; }; 8D93B69D2C4A788F00C91865 /* NetADSBDecoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetADSBDecoder.swift; sourceTree = ""; }; - 8DB347C42C242BAC00F3C020 /* AirplaneTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AirplaneTracker.swift; sourceTree = ""; }; + 8DCF5548306863F500C724BA /* ADSBDecoderCLI */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ADSBDecoderCLI; sourceTree = BUILT_PRODUCTS_DIR; }; + 8DCF5553306864B700C724BA /* ADSBDecoder.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ADSBDecoder.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 8DCF5561306864B800C724BA /* ADSBDecoderTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ADSBDecoderTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 8DCF556B306864B800C724BA /* ADSBDecoderUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ADSBDecoderUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 8DEC6F2D2C2E9C3000AC6209 /* ADSBFileRunner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ADSBFileRunner.swift; sourceTree = ""; }; 8DEC6F312C31530C00AC6209 /* FlighState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlighState.swift; sourceTree = ""; }; - 8DF7565F2C0595AA008E8DFF /* ADSBDecoder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ADSBDecoder; sourceTree = BUILT_PRODUCTS_DIR; }; - 8DF756622C0595AA008E8DFF /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; - 8DF756712C059969008E8DFF /* Test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Test; sourceTree = BUILT_PRODUCTS_DIR; }; 8DF756732C059969008E8DFF /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 8DF756822C10556A008E8DFF /* LearnMapKit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LearnMapKit.app; sourceTree = BUILT_PRODUCTS_DIR; }; 8DF756842C10556A008E8DFF /* LearnMapKitApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LearnMapKitApp.swift; sourceTree = ""; }; @@ -165,13 +167,6 @@ /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ - 8D4F384E306528A200EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { - isa = PBXFileSystemSynchronizedBuildFileExceptionSet; - membershipExceptions = ( - FileUtils.swift, - ); - target = 8DF7565E2C0595AA008E8DFF /* ADSBDecoder */; - }; 8D4F384F306528A200EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { isa = PBXFileSystemSynchronizedBuildFileExceptionSet; membershipExceptions = ( @@ -193,52 +188,23 @@ ); target = 8D4F382E3065267E00EA3890 /* ADSBDecoderFramework */; }; - 8D4F38533065291400EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + 8DCF557D306866C000C724BA /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { isa = PBXFileSystemSynchronizedBuildFileExceptionSet; membershipExceptions = ( - ADSBRegEx.swift, - Configs.swift, - Decoder.swift, - PositionDecoder.swift, - Query.swift, - ); - target = 8DF7565E2C0595AA008E8DFF /* ADSBDecoder */; - }; - 8D4F38543065291400EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { - isa = PBXFileSystemSynchronizedBuildFileExceptionSet; - membershipExceptions = ( - Configs.swift, - Decoder.swift, - ); - target = 8DF756702C059969008E8DFF /* Test */; - }; - 8D4F38553065291400EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { - isa = PBXFileSystemSynchronizedBuildFileExceptionSet; - membershipExceptions = ( - ADSBRegEx.swift, - Configs.swift, - Decoder.swift, - PositionDecoder.swift, - ); - target = 8DF756812C10556A008E8DFF /* LearnMapKit */; - }; - 8D4F38563065291400EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { - isa = PBXFileSystemSynchronizedBuildFileExceptionSet; - membershipExceptions = ( - ADSBRegEx.swift, - Configs.swift, - Decoder.swift, - PositionDecoder.swift, - Query.swift, + FileUtils.swift, ); - target = 8D93B6862C45986700C91865 /* ADSBStats */; + target = 8DCF5547306863F500C724BA /* ADSBDecoderCLI */; }; /* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ - 8D4F38303065267E00EA3890 /* ADSBDecoderFramework */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (8D4F38533065291400EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 8D4F38543065291400EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 8D4F38553065291400EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 8D4F38563065291400EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = ADSBDecoderFramework; sourceTree = ""; }; + 8D4F38303065267E00EA3890 /* ADSBDecoderFramework */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = ADSBDecoderFramework; sourceTree = ""; }; 8D4F383F3065267F00EA3890 /* ADSBDecoderFrameworkTests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = ADSBDecoderFrameworkTests; sourceTree = ""; }; - 8D4F384D3065289B00EA3890 /* Utils */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (8D4F384E306528A200EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 8D4F384F306528A200EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 8D4F3850306528A200EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 8D4F3851306528A200EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = Utils; sourceTree = ""; }; + 8D4F384D3065289B00EA3890 /* Utils */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (8D4F384F306528A200EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 8D4F3850306528A200EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 8D4F3851306528A200EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 8DCF557D306866C000C724BA /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = Utils; sourceTree = ""; }; + 8DCF5549306863F500C724BA /* ADSBDecoderCLI */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = ADSBDecoderCLI; sourceTree = ""; }; + 8DCF5554306864B700C724BA /* ADSBDecoder */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = ADSBDecoder; sourceTree = ""; }; + 8DCF5564306864B800C724BA /* ADSBDecoderTests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = ADSBDecoderTests; sourceTree = ""; }; + 8DCF556E306864B800C724BA /* ADSBDecoderUITests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = ADSBDecoderUITests; sourceTree = ""; }; /* End PBXFileSystemSynchronizedRootGroup section */ /* Begin PBXFrameworksBuildPhase section */ @@ -275,17 +241,33 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 8DF7565C2C0595AA008E8DFF /* Frameworks */ = { + 8DCF5545306863F500C724BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8DCF557F3068673400C724BA /* ArgumentParser in Frameworks */, + 8DCF557A3068652B00C724BA /* ADSBDecoderFramework.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8DCF5550306864B700C724BA /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 8D4F3852306528DE00EA3890 /* ADSBDecoderFramework.framework in Frameworks */, - 8DB347C32C1C53ED00F3C020 /* Collections in Frameworks */, - 8DF7566C2C0595F6008E8DFF /* ArgumentParser in Frameworks */, + 8DCF55833068678900C724BA /* Collections in Frameworks */, + 8DCF55813068678500C724BA /* ArgumentParser in Frameworks */, + 8DCF557B306865A300C724BA /* ADSBDecoderFramework.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 8DF7566E2C059969008E8DFF /* Frameworks */ = { + 8DCF555E306864B800C724BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8DCF5568306864B800C724BA /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -349,7 +331,6 @@ children = ( 8D4F384D3065289B00EA3890 /* Utils */, 8DF756692C0595BB008E8DFF /* Data */, - 8DF756612C0595AA008E8DFF /* ADSBDecoder */, 8DF756722C059969008E8DFF /* Test */, 8DF756832C10556A008E8DFF /* LearnMapKit */, 8DF756952C10556C008E8DFF /* LearnMapKitTests */, @@ -358,6 +339,10 @@ 8D93B6882C45986700C91865 /* ADSBStats */, 8D4F38303065267E00EA3890 /* ADSBDecoderFramework */, 8D4F383F3065267F00EA3890 /* ADSBDecoderFrameworkTests */, + 8DCF5549306863F500C724BA /* ADSBDecoderCLI */, + 8DCF5554306864B700C724BA /* ADSBDecoder */, + 8DCF5564306864B800C724BA /* ADSBDecoderTests */, + 8DCF556E306864B800C724BA /* ADSBDecoderUITests */, 8DF756602C0595AA008E8DFF /* Products */, 8DB347C12C1C53ED00F3C020 /* Frameworks */, ); @@ -366,8 +351,6 @@ 8DF756602C0595AA008E8DFF /* Products */ = { isa = PBXGroup; children = ( - 8DF7565F2C0595AA008E8DFF /* ADSBDecoder */, - 8DF756712C059969008E8DFF /* Test */, 8DF756822C10556A008E8DFF /* LearnMapKit.app */, 8DF756922C10556C008E8DFF /* LearnMapKitTests.xctest */, 8DF7569C2C10556C008E8DFF /* LearnMapKitUITests.xctest */, @@ -375,19 +358,14 @@ 8D93B6872C45986700C91865 /* ADSBStats */, 8D4F382F3065267E00EA3890 /* ADSBDecoderFramework.framework */, 8D4F38393065267F00EA3890 /* ADSBDecoderFrameworkTests.xctest */, + 8DCF5548306863F500C724BA /* ADSBDecoderCLI */, + 8DCF5553306864B700C724BA /* ADSBDecoder.app */, + 8DCF5561306864B800C724BA /* ADSBDecoderTests.xctest */, + 8DCF556B306864B800C724BA /* ADSBDecoderUITests.xctest */, ); name = Products; sourceTree = ""; }; - 8DF756612C0595AA008E8DFF /* ADSBDecoder */ = { - isa = PBXGroup; - children = ( - 8DF756622C0595AA008E8DFF /* main.swift */, - 8DB347C42C242BAC00F3C020 /* AirplaneTracker.swift */, - ); - path = ADSBDecoder; - sourceTree = ""; - }; 8DF756692C0595BB008E8DFF /* Data */ = { isa = PBXGroup; children = ( @@ -549,43 +527,98 @@ productReference = 8D93B6872C45986700C91865 /* ADSBStats */; productType = "com.apple.product-type.tool"; }; - 8DF7565E2C0595AA008E8DFF /* ADSBDecoder */ = { + 8DCF5547306863F500C724BA /* ADSBDecoderCLI */ = { isa = PBXNativeTarget; - buildConfigurationList = 8DF756662C0595AA008E8DFF /* Build configuration list for PBXNativeTarget "ADSBDecoder" */; + buildConfigurationList = 8DCF554C306863F500C724BA /* Build configuration list for PBXNativeTarget "ADSBDecoderCLI" */; buildPhases = ( - 8DF7565B2C0595AA008E8DFF /* Sources */, - 8DF7565C2C0595AA008E8DFF /* Frameworks */, - 8DF7565D2C0595AA008E8DFF /* CopyFiles */, + 8DCF5544306863F500C724BA /* Sources */, + 8DCF5545306863F500C724BA /* Frameworks */, + 8DCF5546306863F500C724BA /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); + fileSystemSynchronizedGroups = ( + 8DCF5549306863F500C724BA /* ADSBDecoderCLI */, + ); + name = ADSBDecoderCLI; + packageProductDependencies = ( + 8DCF557E3068673400C724BA /* ArgumentParser */, + ); + productName = ADSBDecoderCLI; + productReference = 8DCF5548306863F500C724BA /* ADSBDecoderCLI */; + productType = "com.apple.product-type.tool"; + }; + 8DCF5552306864B700C724BA /* ADSBDecoder */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8DCF5571306864B800C724BA /* Build configuration list for PBXNativeTarget "ADSBDecoder" */; + buildPhases = ( + 8DCF554F306864B700C724BA /* Sources */, + 8DCF5550306864B700C724BA /* Frameworks */, + 8DCF5551306864B700C724BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 8DCF5554306864B700C724BA /* ADSBDecoder */, + ); name = ADSBDecoder; packageProductDependencies = ( - 8DF7566B2C0595F6008E8DFF /* ArgumentParser */, - 8DB347C22C1C53ED00F3C020 /* Collections */, + 8DCF55803068678500C724BA /* ArgumentParser */, + 8DCF55823068678900C724BA /* Collections */, ); productName = ADSBDecoder; - productReference = 8DF7565F2C0595AA008E8DFF /* ADSBDecoder */; - productType = "com.apple.product-type.tool"; + productReference = 8DCF5553306864B700C724BA /* ADSBDecoder.app */; + productType = "com.apple.product-type.application"; }; - 8DF756702C059969008E8DFF /* Test */ = { + 8DCF5560306864B800C724BA /* ADSBDecoderTests */ = { isa = PBXNativeTarget; - buildConfigurationList = 8DF756752C059969008E8DFF /* Build configuration list for PBXNativeTarget "Test" */; + buildConfigurationList = 8DCF5574306864B800C724BA /* Build configuration list for PBXNativeTarget "ADSBDecoderTests" */; buildPhases = ( - 8DF7566D2C059969008E8DFF /* Sources */, - 8DF7566E2C059969008E8DFF /* Frameworks */, - 8DF7566F2C059969008E8DFF /* CopyFiles */, + 8DCF555D306864B800C724BA /* Sources */, + 8DCF555E306864B800C724BA /* Frameworks */, + 8DCF555F306864B800C724BA /* Resources */, ); buildRules = ( ); dependencies = ( + 8DCF5563306864B800C724BA /* PBXTargetDependency */, ); - name = Test; - productName = Test; - productReference = 8DF756712C059969008E8DFF /* Test */; - productType = "com.apple.product-type.tool"; + fileSystemSynchronizedGroups = ( + 8DCF5564306864B800C724BA /* ADSBDecoderTests */, + ); + name = ADSBDecoderTests; + packageProductDependencies = ( + ); + productName = ADSBDecoderTests; + productReference = 8DCF5561306864B800C724BA /* ADSBDecoderTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 8DCF556A306864B800C724BA /* ADSBDecoderUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8DCF5577306864B800C724BA /* Build configuration list for PBXNativeTarget "ADSBDecoderUITests" */; + buildPhases = ( + 8DCF5567306864B800C724BA /* Sources */, + 8DCF5568306864B800C724BA /* Frameworks */, + 8DCF5569306864B800C724BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 8DCF556D306864B800C724BA /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + 8DCF556E306864B800C724BA /* ADSBDecoderUITests */, + ); + name = ADSBDecoderUITests; + packageProductDependencies = ( + ); + productName = ADSBDecoderUITests; + productReference = 8DCF556B306864B800C724BA /* ADSBDecoderUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; }; 8DF756812C10556A008E8DFF /* LearnMapKit */ = { isa = PBXNativeTarget; @@ -670,11 +703,19 @@ 8D93B6862C45986700C91865 = { CreatedOnToolsVersion = 15.4; }; - 8DF7565E2C0595AA008E8DFF = { - CreatedOnToolsVersion = 15.3; + 8DCF5547306863F500C724BA = { + CreatedOnToolsVersion = 27.0; }; - 8DF756702C059969008E8DFF = { - CreatedOnToolsVersion = 15.3; + 8DCF5552306864B700C724BA = { + CreatedOnToolsVersion = 27.0; + }; + 8DCF5560306864B800C724BA = { + CreatedOnToolsVersion = 27.0; + TestTargetID = 8DCF5552306864B700C724BA; + }; + 8DCF556A306864B800C724BA = { + CreatedOnToolsVersion = 27.0; + TestTargetID = 8DCF5552306864B700C724BA; }; 8DF756812C10556A008E8DFF = { CreatedOnToolsVersion = 15.3; @@ -707,8 +748,6 @@ projectDirPath = ""; projectRoot = ""; targets = ( - 8DF7565E2C0595AA008E8DFF /* ADSBDecoder */, - 8DF756702C059969008E8DFF /* Test */, 8DF756812C10556A008E8DFF /* LearnMapKit */, 8DF756912C10556C008E8DFF /* LearnMapKitTests */, 8DF7569B2C10556C008E8DFF /* LearnMapKitUITests */, @@ -716,6 +755,10 @@ 8D93B6862C45986700C91865 /* ADSBStats */, 8D4F382E3065267E00EA3890 /* ADSBDecoderFramework */, 8D4F38383065267F00EA3890 /* ADSBDecoderFrameworkTests */, + 8DCF5547306863F500C724BA /* ADSBDecoderCLI */, + 8DCF5552306864B700C724BA /* ADSBDecoder */, + 8DCF5560306864B800C724BA /* ADSBDecoderTests */, + 8DCF556A306864B800C724BA /* ADSBDecoderUITests */, ); }; /* End PBXProject section */ @@ -735,6 +778,27 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 8DCF5551306864B700C724BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8DCF555F306864B800C724BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8DCF5569306864B800C724BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8DF756802C10556A008E8DFF /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -788,25 +852,35 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8D93B6942C4598E300C91865 /* AirplaneTracker.swift in Sources */, 8D93B68A2C45986700C91865 /* main.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 8DF7565B2C0595AA008E8DFF /* Sources */ = { + 8DCF5544306863F500C724BA /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8DB347C52C242BAC00F3C020 /* AirplaneTracker.swift in Sources */, - 8DF756632C0595AA008E8DFF /* main.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 8DF7566D2C059969008E8DFF /* Sources */ = { + 8DCF554F306864B700C724BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8DCF555D306864B800C724BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8DCF5567306864B800C724BA /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8DF756742C059969008E8DFF /* main.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -820,7 +894,6 @@ 8D93B69F2C4A7A0700C91865 /* NetADSBDecoder.swift in Sources */, 8D8480F32C60C7E6007ACD95 /* ADSBNetRunner.swift in Sources */, 8DEC6F322C31530C00AC6209 /* FlighState.swift in Sources */, - 8D4F386030652B4A00EA3890 /* AirplaneTracker.swift in Sources */, 8DF756852C10556A008E8DFF /* LearnMapKitApp.swift in Sources */, 8D8480F12C60C79E007ACD95 /* ADSBDataQueue.swift in Sources */, 8D93B69A2C4A665B00C91865 /* NetConfigView.swift in Sources */, @@ -862,6 +935,16 @@ target = 8D4F382E3065267E00EA3890 /* ADSBDecoderFramework */; targetProxy = 8D4F38423065267F00EA3890 /* PBXContainerItemProxy */; }; + 8DCF5563306864B800C724BA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DCF5552306864B700C724BA /* ADSBDecoder */; + targetProxy = 8DCF5562306864B800C724BA /* PBXContainerItemProxy */; + }; + 8DCF556D306864B800C724BA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DCF5552306864B700C724BA /* ADSBDecoder */; + targetProxy = 8DCF556C306864B800C724BA /* PBXContainerItemProxy */; + }; 8DF756942C10556C008E8DFF /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 8DF756812C10556A008E8DFF /* LearnMapKit */; @@ -1041,6 +1124,170 @@ }; name = Release; }; + 8DCF554D306863F500C724BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + MACOSX_DEPLOYMENT_TARGET = 26.6; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 8DCF554E306863F500C724BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + MACOSX_DEPLOYMENT_TARGET = 26.6; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 8DCF5572306864B800C724BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_APP_SANDBOX = YES; + ENABLE_PREVIEWS = YES; + ENABLE_USER_SELECTED_FILES = readonly; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 26.6; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = RadioTeam.ADSBDecoder; + PRODUCT_NAME = "$(TARGET_NAME)"; + REGISTER_APP_GROUPS = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 8DCF5573306864B800C724BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_APP_SANDBOX = YES; + ENABLE_PREVIEWS = YES; + ENABLE_USER_SELECTED_FILES = readonly; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 26.6; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = RadioTeam.ADSBDecoder; + PRODUCT_NAME = "$(TARGET_NAME)"; + REGISTER_APP_GROUPS = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 8DCF5575306864B800C724BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 26.6; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = RadioTeam.ADSBDecoderTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRING_CATALOG_GENERATE_SYMBOLS = NO; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ADSBDecoder.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/ADSBDecoder"; + }; + name = Debug; + }; + 8DCF5576306864B800C724BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 26.6; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = RadioTeam.ADSBDecoderTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRING_CATALOG_GENERATE_SYMBOLS = NO; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ADSBDecoder.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/ADSBDecoder"; + }; + name = Release; + }; + 8DCF5578306864B800C724BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 26.6; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = RadioTeam.ADSBDecoderUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRING_CATALOG_GENERATE_SYMBOLS = NO; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TEST_TARGET_NAME = ADSBDecoder; + }; + name = Debug; + }; + 8DCF5579306864B800C724BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 26.6; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = RadioTeam.ADSBDecoderUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRING_CATALOG_GENERATE_SYMBOLS = NO; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TEST_TARGET_NAME = ADSBDecoder; + }; + name = Release; + }; 8DF756642C0595AA008E8DFF /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1159,44 +1406,6 @@ }; name = Release; }; - 8DF756672C0595AA008E8DFF /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - PRODUCT_NAME = "$(TARGET_NAME)"; - RUN_DOCUMENTATION_COMPILER = YES; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 8DF756682C0595AA008E8DFF /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - PRODUCT_NAME = "$(TARGET_NAME)"; - RUN_DOCUMENTATION_COMPILER = YES; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 8DF756762C059969008E8DFF /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 8DF756772C059969008E8DFF /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; 8DF756A52C10556C008E8DFF /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1354,29 +1563,47 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 8DF7565A2C0595AA008E8DFF /* Build configuration list for PBXProject "ADSBDecoder" */ = { + 8DCF554C306863F500C724BA /* Build configuration list for PBXNativeTarget "ADSBDecoderCLI" */ = { isa = XCConfigurationList; buildConfigurations = ( - 8DF756642C0595AA008E8DFF /* Debug */, - 8DF756652C0595AA008E8DFF /* Release */, + 8DCF554D306863F500C724BA /* Debug */, + 8DCF554E306863F500C724BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8DCF5571306864B800C724BA /* Build configuration list for PBXNativeTarget "ADSBDecoder" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8DCF5572306864B800C724BA /* Debug */, + 8DCF5573306864B800C724BA /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 8DF756662C0595AA008E8DFF /* Build configuration list for PBXNativeTarget "ADSBDecoder" */ = { + 8DCF5574306864B800C724BA /* Build configuration list for PBXNativeTarget "ADSBDecoderTests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 8DF756672C0595AA008E8DFF /* Debug */, - 8DF756682C0595AA008E8DFF /* Release */, + 8DCF5575306864B800C724BA /* Debug */, + 8DCF5576306864B800C724BA /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 8DF756752C059969008E8DFF /* Build configuration list for PBXNativeTarget "Test" */ = { + 8DCF5577306864B800C724BA /* Build configuration list for PBXNativeTarget "ADSBDecoderUITests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 8DF756762C059969008E8DFF /* Debug */, - 8DF756772C059969008E8DFF /* Release */, + 8DCF5578306864B800C724BA /* Debug */, + 8DCF5579306864B800C724BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8DF7565A2C0595AA008E8DFF /* Build configuration list for PBXProject "ADSBDecoder" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8DF756642C0595AA008E8DFF /* Debug */, + 8DF756652C0595AA008E8DFF /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -1468,7 +1695,17 @@ package = 8DB347C02C1C53CB00F3C020 /* XCRemoteSwiftPackageReference "swift-collections" */; productName = Collections; }; - 8DB347C22C1C53ED00F3C020 /* Collections */ = { + 8DCF557E3068673400C724BA /* ArgumentParser */ = { + isa = XCSwiftPackageProductDependency; + package = 8DF7566A2C0595F6008E8DFF /* XCRemoteSwiftPackageReference "swift-argument-parser" */; + productName = ArgumentParser; + }; + 8DCF55803068678500C724BA /* ArgumentParser */ = { + isa = XCSwiftPackageProductDependency; + package = 8DF7566A2C0595F6008E8DFF /* XCRemoteSwiftPackageReference "swift-argument-parser" */; + productName = ArgumentParser; + }; + 8DCF55823068678900C724BA /* Collections */ = { isa = XCSwiftPackageProductDependency; package = 8DB347C02C1C53CB00F3C020 /* XCRemoteSwiftPackageReference "swift-collections" */; productName = Collections; @@ -1478,11 +1715,6 @@ package = 8DB347C02C1C53CB00F3C020 /* XCRemoteSwiftPackageReference "swift-collections" */; productName = Collections; }; - 8DF7566B2C0595F6008E8DFF /* ArgumentParser */ = { - isa = XCSwiftPackageProductDependency; - package = 8DF7566A2C0595F6008E8DFF /* XCRemoteSwiftPackageReference "swift-argument-parser" */; - productName = ArgumentParser; - }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 8DF756572C0595AA008E8DFF /* Project object */; diff --git a/ADSBDecoder.xcodeproj/xcuserdata/jackyjack.xcuserdatad/xcschemes/xcschememanagement.plist b/ADSBDecoder.xcodeproj/xcuserdata/jackyjack.xcuserdatad/xcschemes/xcschememanagement.plist index 2b937de..7605dca 100644 --- a/ADSBDecoder.xcodeproj/xcuserdata/jackyjack.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/ADSBDecoder.xcodeproj/xcuserdata/jackyjack.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,29 +7,39 @@ ADSBDecoder.xcscheme_^#shared#^_ orderHint - 0 + 6 + + ADSBDecoderCLI.xcscheme_^#shared#^_ + + orderHint + 7 ADSBDecoderFramework.xcscheme_^#shared#^_ + + orderHint + 1 + + ADSBDecoderTests.xcscheme_^#shared#^_ orderHint 4 - ADSBStats.xcscheme_^#shared#^_ + ADSBDecoderUITests.xcscheme_^#shared#^_ orderHint 5 - LearnMapKit.xcscheme_^#shared#^_ + ADSBStats.xcscheme_^#shared#^_ orderHint - 1 + 2 - Net1090.xcscheme_^#shared#^_ + LearnMapKit.xcscheme_^#shared#^_ orderHint - 2 + 0 - Test.xcscheme_^#shared#^_ + Net1090.xcscheme_^#shared#^_ orderHint 3 @@ -42,11 +52,46 @@ primary + 8D93B6752C3FE6F400C91865 + + primary + + + 8D93B6862C45986700C91865 + + primary + + + 8DCF551C306863B200C724BA + + primary + + + 8DCF552A306863B500C724BA + + primary + + + 8DCF5534306863B500C724BA + + primary + + + 8DCF5547306863F500C724BA + + primary + + 8DF7565E2C0595AA008E8DFF primary + 8DF756702C059969008E8DFF + + primary + + 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)") -} diff --git a/ADSBDecoderCLI/main.swift b/ADSBDecoderCLI/main.swift new file mode 100644 index 0000000..3dc1f85 --- /dev/null +++ b/ADSBDecoderCLI/main.swift @@ -0,0 +1,131 @@ +// +// main.swift +// ADSBDecoder +// +// Created by Jacky Jack on 28/05/2024. +// + +import Foundation +import ArgumentParser +import RegexBuilder +import SQLite3 +import ADSBDecoderFramework + + +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)") +} diff --git a/ADSBDecoderFramework/ADSBRegEx.swift b/ADSBDecoderFramework/ADSBRegEx.swift index 2841467..4e554c0 100644 --- a/ADSBDecoderFramework/ADSBRegEx.swift +++ b/ADSBDecoderFramework/ADSBRegEx.swift @@ -21,7 +21,9 @@ let matchADSBLong = Regex { ";" }*/ -class MatchADSBLong { +public class MatchADSBLong { + public init() {} + let matchADSBLong = Regex { Anchor.startOfLine "*" @@ -36,7 +38,7 @@ class MatchADSBLong { ";" } - func prefixMatch(_ line: String) -> Regex.RegexOutput>.Match? { + public func prefixMatch(_ line: String) -> Regex.RegexOutput>.Match? { do { if let match = try matchADSBLong.prefixMatch(in: line) { return match @@ -61,7 +63,9 @@ let matchADSBShort = Regex { ";" }*/ -class MatchADSBShort { +public class MatchADSBShort { + public init() {} + let matchADSBShort = Regex { Anchor.startOfLine "*" @@ -74,7 +78,7 @@ class MatchADSBShort { ";" } - func prefixMatch(_ line: String) -> Regex.RegexOutput>.Match? { + public func prefixMatch(_ line: String) -> Regex.RegexOutput>.Match? { do { if let match = try matchADSBShort.prefixMatch(in: line) { return match diff --git a/ADSBDecoderFramework/AirplaneTracker.swift b/ADSBDecoderFramework/AirplaneTracker.swift new file mode 100644 index 0000000..6c09953 --- /dev/null +++ b/ADSBDecoderFramework/AirplaneTracker.swift @@ -0,0 +1,120 @@ +// +// 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() +} + +public class AirPlaneTracker { + + var airplanes:[Int:Airplane] = [:] + + public init () { + + } + + public 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 + } + } + } + + public func addDF17AirBornPosition(_ address: Int, _ cpr_lat: Int, _ cpr_long: Int, _ alt: Int, _ even: Bool) { + + if airplanes[address] == nil { + return + } + + //deal with altitude + airplanes[address]?.altitude = alt + airplanes[address]?.altitudeCount += 1 + airplanes[address]?.altitudeReady = true + //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()) + } + + } + + public 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 + } + + public 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 + } + } + + public 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 + } + } + + public func printAllICAOnames() { + let extra = false + for (address,plane) in airplanes { + if plane.ICAOready { + print(String("\(plane.ICAOname) "), terminator: "") + } + if (extra) { + print("Alitude \(plane.altitudeCount)") + } + } + } + +} diff --git a/ADSBDecoderFramework/Decoder.swift b/ADSBDecoderFramework/Decoder.swift index a9724b6..17fce52 100644 --- a/ADSBDecoderFramework/Decoder.swift +++ b/ADSBDecoderFramework/Decoder.swift @@ -20,11 +20,11 @@ func BarometricAltitudeFeat(_ altitude: UInt16) -> Int { return Int(altitude)*100-1000 } -class Decoder { +public class Decoder { var adsb_data: String = "" - var DataFormat: UInt32 = 0; - - init (_ adsb_data: String) { + public var DataFormat: UInt32 = 0; + + public init (_ adsb_data: String) { //print(adsb_data) self.adsb_data = adsb_data //get the first 8 bits as integer @@ -41,7 +41,7 @@ class Decoder { //print("Data Format \(DataFormat)") } - func getDataFormat17() -> DataFormat17? { + public func getDataFormat17() -> DataFormat17? { if (DataFormat != 17) { return nil @@ -77,12 +77,12 @@ func ICAO2String(_ b1: UInt8, _ b2: UInt8, _ b3: UInt8, _ b4: UInt8, _ b5: UInt8 return ICAOAlphabet(b1)+ICAOAlphabet(b2)+ICAOAlphabet(b3)+ICAOAlphabet(b4)+ICAOAlphabet(b5)+ICAOAlphabet(b6)+ICAOAlphabet(b7)+ICAOAlphabet(b8) } -class DataFormat17 { - +public class DataFormat17 { + let DataFormat=17 //0:5 var Capability=0 //5:7 - var AddressAnnounced=0 //8:31 - var TypeCode=0 //32:36 + public var AddressAnnounced=0 //8:31 + public var TypeCode=0 //32:36 var MovementField=0//37:43 var HeadingBit=0//44 var HeadingField=0//45:51 @@ -92,10 +92,10 @@ class DataFormat17 { var ParityIntegrity=0//88-111 //all avaliable message types - var messageIdentification:ADSBTypeCodeIndentification? = nil - var messageAirbornPositon:ADSBTypeCodeAirbonePositon? = nil - - init(_ adsb_data: String) { + public var messageIdentification:ADSBTypeCodeIndentification? = nil + public var messageAirbornPositon:ADSBTypeCodeAirbonePositon? = nil + + public init(_ adsb_data: String) { //print("Dataformat: 17!") //print(adsb_data) @@ -167,12 +167,12 @@ class DataFormat17 { } } -class ADSBTypeCodeIndentification: CustomStringConvertible { +public class ADSBTypeCodeIndentification: CustomStringConvertible { var TypeCode:Int = 4 var Category:Int = 0 - var ICAOName:String - - init(_ bindata:ArraySlice) { + public var ICAOName:String + + public init(_ bindata:ArraySlice) { let cat = bindata[4]&0x7 Category = Int(cat) let char_0 = bindata[5]>>2 @@ -189,24 +189,24 @@ class ADSBTypeCodeIndentification: CustomStringConvertible { //print("ICAO name \(ICAOName)") } - var description: String { + public var description: String { let description = "TypeCode \(TypeCode) Cat \(Category) Flight name \(ICAOName)" return description } } //DF17 message types codes 8 to 18 -class ADSBTypeCodeAirbonePositon:CustomStringConvertible { +public class ADSBTypeCodeAirbonePositon:CustomStringConvertible { var TypeCode:Int = 11 var SurveillanceStatus: Int = 0 var SingleAntennaFlag: Int = 0 - var Altitude: Int = 0 + public var Altitude: Int = 0 var Time: Int = 0 - var CPRFormat: Int = 0 - var Latitude: Int = 0 - var Longitude: Int = 0 - - init(_ bindata:ArraySlice) { + public var CPRFormat: Int = 0 + public var Latitude: Int = 0 + public var Longitude: Int = 0 + + public init(_ bindata:ArraySlice) { let ss = (bindata[4]>>1)&(0x3) SurveillanceStatus = Int(ss) let saf = bindata[5]&0x1 @@ -224,7 +224,7 @@ class ADSBTypeCodeAirbonePositon:CustomStringConvertible { Longitude = Int(lon) } - var description: String { + public var description: String { var description = "SS \(SurveillanceStatus) SAF \(SingleAntennaFlag) Altitude \(Altitude)ft \n" description += "Time \(Time) CPR \(CPRFormat)" if (CPRFormat == 0) { diff --git a/ADSBDecoderFramework/PositionDecoder.swift b/ADSBDecoderFramework/PositionDecoder.swift index 85b9d49..a8d03de 100644 --- a/ADSBDecoderFramework/PositionDecoder.swift +++ b/ADSBDecoderFramework/PositionDecoder.swift @@ -112,7 +112,7 @@ func mstime() -> Int64 { return mst; } -class PositionDecoder { +public class PositionDecoder { var long: Double = 0.0 var lat: Double = 0.0 @@ -120,18 +120,22 @@ class PositionDecoder { var newposition: Bool = false //initialise first values so this values is nonsence - var queue: Deque = [] + //var queue: Deque = [] + var position_even: PositionData? = nil + var position_odd: PositionData? = nil init() { } func addEvenPosition(_ cpr_lat: UInt32,_ cpr_long: UInt32, _ cprtime: Int64) { - queue.append(PositionData(cpr_lat:cpr_lat, cpr_long:cpr_long, even:true, cprtime: cprtime)) + //queue.append(PositionData(cpr_lat:cpr_lat, cpr_long:cpr_long, even:true, cprtime: cprtime)) + self.position_even = PositionData(cpr_lat:cpr_lat, cpr_long:cpr_long, even:true, cprtime: cprtime) } func addOddPosition(_ cpr_lat: UInt32,_ cpr_long: UInt32, _ cprtime: Int64) { - queue.append(PositionData(cpr_lat:cpr_lat,cpr_long:cpr_long,even:false, cprtime: cprtime)) + //queue.append(PositionData(cpr_lat:cpr_lat,cpr_long:cpr_long,even:false, cprtime: cprtime)) + self.position_odd = PositionData(cpr_lat:cpr_lat,cpr_long:cpr_long,even:false, cprtime: cprtime) } func getPosition() -> (Double, Double)? { @@ -143,24 +147,36 @@ class PositionDecoder { //TODO: allways adds to queue newer frees the queue func calcPosition() -> Bool { - if (queue.count > 2) { - let el1 = queue[queue.count-1] - let el2 = queue[queue.count-2] - if (el1.even == el2.even) { - //ready = false - return false - } - } else { - ready = false - print("Position queue to short to calculate values") + //if (queue.count > 2) { + //let el1 = queue[queue.count-1] + //let el2 = queue[queue.count-2] + //if (el1.even == el2.even) { + // //ready = false + // return false + //} + //} else { + // ready = false + // print("Position queue to short to calculate values") + // return false + //} + if position_odd == nil { + return false + } + if position_even == nil { return false } //last to elements are evan and odd - let el1 = queue[queue.count-1] - let el2 = queue[queue.count-2] - let cpr_even = el1.even ? el1 : el2 - let cpr_odd = (!el1.even) ? el1 : el2 + //let el1 = queue[queue.count-1] + //let el2 = queue[queue.count-2] + guard let cpr_even = self.position_even else { + print("Cant unwrap even position") + return false + } + guard let cpr_odd = self.position_odd else { + print("Cant unwrap odd position") + return false + } //print("Position queue is ready to calculate location \(cpr_even) \(cpr_odd)") // from here https://github.com/antirez/dump1090/blob/master/dump1090.c#L1718 diff --git a/ADSBDecoderFramework/Query.swift b/ADSBDecoderFramework/Query.swift index a92d919..0ae6212 100644 --- a/ADSBDecoderFramework/Query.swift +++ b/ADSBDecoderFramework/Query.swift @@ -7,20 +7,20 @@ import Foundation -class QueryDF: CustomStringConvertible { - +public class QueryDF: CustomStringConvertible { + //max I see is 24 var DFlist:[Int] = Array(repeating: 0, count: 30) - - init() { + + public init() { } - func addDF(_ dataformat: UInt32) { + public func addDF(_ dataformat: UInt32) { DFlist[Int(dataformat)] += 1 } - - func showStat() { + + public func showStat() { print("DataFormat Count") for i in 0...(DFlist.count)-1 { if DFlist[i] != 0 { @@ -29,7 +29,7 @@ class QueryDF: CustomStringConvertible { } } - var description: String { + public var description: String { var description = "DataFormat Count\n" for i in 0...(DFlist.count)-1 { if DFlist[i] != 0 { @@ -40,18 +40,18 @@ class QueryDF: CustomStringConvertible { } } -class QueryDF17TC: CustomStringConvertible { +public class QueryDF17TC: CustomStringConvertible { var TClist:[Int] = Array(repeating: 0, count: 32) - - init() { - + + public init() { + } - - func addTC(_ typecode: Int) { + + public func addTC(_ typecode: Int) { TClist[typecode] += 1 } - var description: String { + public var description: String { var description = "DF17 TypeCode Count\n" for i in 0...(TClist.count-1) { if TClist[i] != 0 { @@ -62,25 +62,25 @@ class QueryDF17TC: CustomStringConvertible { } } -class QueryDecodedMessages: CustomStringConvertible { - +public class QueryDecodedMessages: CustomStringConvertible { + var decoded:Int = 0 var total:Int = 0 - - init() { - + + public init() { + } - - func addDecoded() { + + public func addDecoded() { decoded += 1 total += 1 } - - func addUndecoded() { + + public func addUndecoded() { total = total + 1 } - var description: String { + public var description: String { var description = "Total messages:\n" description += "Decoded:\(decoded)\n" description += "Total :\(total) \(String(format:"%02.01f",Float(Float(decoded)/Float(total)*100.0)))%\n" @@ -90,24 +90,24 @@ class QueryDecodedMessages: CustomStringConvertible { } -class QueryDF17TC_decoded: CustomStringConvertible { +public class QueryDF17TC_decoded: CustomStringConvertible { var TClist_decoded:[Int] = Array(repeating: 0, count: 32) var TClist_total:[Int] = Array(repeating: 0, count: 32) - - init() { - + + public init() { + } - - func addDecoded(_ typecode: Int) { + + public func addDecoded(_ typecode: Int) { TClist_decoded[typecode] += 1 TClist_total[typecode] += 1 } - - func addUndecode(_ typecode: Int) { + + public func addUndecode(_ typecode: Int) { TClist_total[typecode] += 1 } - var description: String { + public var description: String { var description = "" var decoded:Int = 0 var total:Int = 0 diff --git a/ADSBDecoderTests/ADSBDecoderTests.swift b/ADSBDecoderTests/ADSBDecoderTests.swift new file mode 100644 index 0000000..48b599d --- /dev/null +++ b/ADSBDecoderTests/ADSBDecoderTests.swift @@ -0,0 +1,19 @@ +// +// ADSBDecoderTests.swift +// ADSBDecoderTests +// +// Created by Jacky Jack on 26/09/2026. +// + +import Testing +@testable import ADSBDecoder + +struct ADSBDecoderTests { + + @Test func example() async throws { + // Write your test here and use APIs like `#expect(...)` to check expected conditions. + // Swift Testing Documentation + // https://developer.apple.com/documentation/testing + } + +} diff --git a/ADSBDecoderUITests/ADSBDecoderUITests.swift b/ADSBDecoderUITests/ADSBDecoderUITests.swift new file mode 100644 index 0000000..9e32700 --- /dev/null +++ b/ADSBDecoderUITests/ADSBDecoderUITests.swift @@ -0,0 +1,43 @@ +// +// ADSBDecoderUITests.swift +// ADSBDecoderUITests +// +// Created by Jacky Jack on 26/09/2026. +// + +import XCTest + +final class ADSBDecoderUITests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + @MainActor + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use XCTAssert and related functions to verify your tests produce the correct results. + // XCUIAutomation Documentation + // https://developer.apple.com/documentation/xcuiautomation + } + + @MainActor + func testLaunchPerformance() throws { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } +} diff --git a/ADSBStats/main.swift b/ADSBStats/main.swift index d340e16..f541aa5 100644 --- a/ADSBStats/main.swift +++ b/ADSBStats/main.swift @@ -10,6 +10,7 @@ import ArgumentParser import RegexBuilder import SQLite3 import SwiftData +import ADSBDecoderFramework //decoder_debug_mode = false @@ -18,7 +19,7 @@ struct CommandLineArgs: ParsableCommand { @Flag(name: .shortAndLong) var debug:Bool = false @Flag(name: .shortAndLong) var version:Bool = false @Flag(name: .shortAndLong) var showstats:Bool = false - @Flag(name: .shortAndLong) var dbadd:Bool = false + @Flag(name: .long) var dbadd:Bool = false } let args = CommandLineArgs.parseOrExit() diff --git a/LearnMapKit/ADSBFileRunner.swift b/LearnMapKit/ADSBFileRunner.swift index 796892c..4c4e154 100644 --- a/LearnMapKit/ADSBFileRunner.swift +++ b/LearnMapKit/ADSBFileRunner.swift @@ -7,6 +7,7 @@ import Foundation import Collections +import ADSBDecoderFramework class ADSBFileRunner { var filename: URL diff --git a/LearnMapKit/ADSBNetRunner.swift b/LearnMapKit/ADSBNetRunner.swift index 8634a72..b5fdd60 100644 --- a/LearnMapKit/ADSBNetRunner.swift +++ b/LearnMapKit/ADSBNetRunner.swift @@ -6,6 +6,7 @@ // import Foundation +import ADSBDecoderFramework class ADSBNetRunner { var address = "" @@ -67,8 +68,8 @@ class ADSBNetRunner { 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) + //let location = self.tracker.getPosition(d17.AddressAnnounced)! + self.adsb_tag_stream.addLocation(d17.AddressAnnounced, position.0, position.1) } } } diff --git a/LearnMapKit/FlighState.swift b/LearnMapKit/FlighState.swift index 9f26578..3da94e0 100644 --- a/LearnMapKit/FlighState.swift +++ b/LearnMapKit/FlighState.swift @@ -15,8 +15,8 @@ class FlightTracker: Identifiable { var ICAOName_avaliable = false var ICAOName = "" var Position_avaliable = false - @Published var long:Double = 0.0 - @Published var lat:Double = 0.0 + @Published var long:Double = 0.0 //? remove published + @Published var lat:Double = 0.0 //?remove published var FromTo_avaliable = false var flightFrom:String = "" var flightTo:String = "" @@ -263,7 +263,8 @@ class FlightState: ObservableObject { } else { print("Update location addr: \(address) lat:\(f.lat) long:\(f.long)") } - flight.append(f) + //flight.append(f) + flight[idx] = f //self.objectWillChange.send() return } @@ -314,9 +315,10 @@ class FlightState: ObservableObject { } else { if let idx = idx_flight[address] { print("Flights \(flight.count)") + } } - print("icao name") + //print("icao name") } func addNewFlight() { diff --git a/Test/main.swift b/Test/main.swift index 8a8e001..a73aef3 100644 --- a/Test/main.swift +++ b/Test/main.swift @@ -6,9 +6,12 @@ // import Foundation +import ADSBDecoderFramework print("Decoder test") +//ADSBDecoderFramework.Decoder() + let decoder = Decoder("8d3c664c580d014ae16024650e6c") if decoder.DataFormat == 17 { if let d17 = decoder.getDataFormat17() { -- cgit v1.2.3