From 505b23afc68ecbb63b8f0a7d44c0b0ad063d5cfd Mon Sep 17 00:00:00 2001 From: Arturs Artamonovs Date: Thu, 24 Sep 2026 11:02:35 +0100 Subject: rearrange source, move common parts to framework --- ADSBDecoder.xcodeproj/project.pbxproj | 467 ++++++++++++++++++--- .../xcschemes/xcschememanagement.plist | 16 +- ADSBDecoder/ADSBRegEx.swift | 87 ---- ADSBDecoder/Configs.swift | 10 - ADSBDecoder/Decoder.swift | 249 ----------- ADSBDecoder/PositionDecoder.swift | 221 ---------- ADSBDecoder/Query.swift | 126 ------ ADSBDecoder/Utils.swift | 23 - ADSBDecoder/main.swift | 1 - .../ADSBDecoderFramework.md | 13 + ADSBDecoderFramework/ADSBDecoderFramework.swift | 9 + ADSBDecoderFramework/ADSBRegEx.swift | 87 ++++ ADSBDecoderFramework/Configs.swift | 10 + ADSBDecoderFramework/Decoder.swift | 249 +++++++++++ ADSBDecoderFramework/PositionDecoder.swift | 221 ++++++++++ ADSBDecoderFramework/Query.swift | 126 ++++++ .../ADSBDecoderFrameworkTests.swift | 21 + LearnMapKit/ADSBNetRunner.swift | 16 +- LearnMapKit/NetworkConfigure.swift | 4 +- Utils/FileUtils.swift | 23 + 20 files changed, 1184 insertions(+), 795 deletions(-) delete mode 100644 ADSBDecoder/ADSBRegEx.swift delete mode 100644 ADSBDecoder/Configs.swift delete mode 100644 ADSBDecoder/Decoder.swift delete mode 100644 ADSBDecoder/PositionDecoder.swift delete mode 100644 ADSBDecoder/Query.swift delete mode 100644 ADSBDecoder/Utils.swift create mode 100644 ADSBDecoderFramework/ADSBDecoderFramework.docc/ADSBDecoderFramework.md create mode 100644 ADSBDecoderFramework/ADSBDecoderFramework.swift create mode 100644 ADSBDecoderFramework/ADSBRegEx.swift create mode 100644 ADSBDecoderFramework/Configs.swift create mode 100644 ADSBDecoderFramework/Decoder.swift create mode 100644 ADSBDecoderFramework/PositionDecoder.swift create mode 100644 ADSBDecoderFramework/Query.swift create mode 100644 ADSBDecoderFrameworkTests/ADSBDecoderFrameworkTests.swift create mode 100644 Utils/FileUtils.swift diff --git a/ADSBDecoder.xcodeproj/project.pbxproj b/ADSBDecoder.xcodeproj/project.pbxproj index 06c5a00..fbca833 100644 --- a/ADSBDecoder.xcodeproj/project.pbxproj +++ b/ADSBDecoder.xcodeproj/project.pbxproj @@ -3,33 +3,23 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 70; objects = { /* Begin PBXBuildFile section */ + 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 */; }; - 8D93B64C2C32030B00C91865 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B64B2C32030B00C91865 /* Utils.swift */; }; - 8D93B64F2C3206DD00C91865 /* AirplaneTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DB347C42C242BAC00F3C020 /* AirplaneTracker.swift */; }; - 8D93B6502C3206E700C91865 /* PositionDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DB347BE2C1C501200F3C020 /* PositionDecoder.swift */; }; - 8D93B6512C3206EB00C91865 /* Decoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DF756782C05A3D7008E8DFF /* Decoder.swift */; }; - 8D93B6532C32095300C91865 /* ADSBRegEx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B6522C32095300C91865 /* ADSBRegEx.swift */; }; - 8D93B6542C32095800C91865 /* ADSBRegEx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B6522C32095300C91865 /* ADSBRegEx.swift */; }; - 8D93B6552C32099B00C91865 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B64B2C32030B00C91865 /* Utils.swift */; }; - 8D93B6572C3D27A000C91865 /* Configs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B6562C3D27A000C91865 /* Configs.swift */; }; - 8D93B6582C3D290C00C91865 /* Configs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B6562C3D27A000C91865 /* Configs.swift */; }; 8D93B6792C3FE6F400C91865 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B6782C3FE6F400C91865 /* main.swift */; }; 8D93B67F2C3FEA0000C91865 /* NIO in Frameworks */ = {isa = PBXBuildFile; productRef = 8D93B67E2C3FEA0000C91865 /* NIO */; }; 8D93B6812C3FEA5600C91865 /* NIO in Frameworks */ = {isa = PBXBuildFile; productRef = 8D93B6802C3FEA5600C91865 /* NIO */; }; - 8D93B6822C412C0A00C91865 /* Configs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B6562C3D27A000C91865 /* Configs.swift */; }; 8D93B68A2C45986700C91865 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B6892C45986700C91865 /* main.swift */; }; - 8D93B68E2C4598A500C91865 /* Configs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B6562C3D27A000C91865 /* Configs.swift */; }; - 8D93B68F2C4598A900C91865 /* ADSBRegEx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B6522C32095300C91865 /* ADSBRegEx.swift */; }; - 8D93B6902C4598AC00C91865 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D93B64B2C32030B00C91865 /* Utils.swift */; }; - 8D93B6912C4598B300C91865 /* PositionDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DB347BE2C1C501200F3C020 /* PositionDecoder.swift */; }; - 8D93B6922C4598B800C91865 /* Decoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DF756782C05A3D7008E8DFF /* Decoder.swift */; }; - 8D93B6932C4598D900C91865 /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DF7567B2C09B7F7008E8DFF /* Query.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 */; }; @@ -37,7 +27,6 @@ 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 */; }; - 8DB347BF2C1C501200F3C020 /* PositionDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DB347BE2C1C501200F3C020 /* PositionDecoder.swift */; }; 8DB347C32C1C53ED00F3C020 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = 8DB347C22C1C53ED00F3C020 /* Collections */; }; 8DB347C52C242BAC00F3C020 /* AirplaneTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DB347C42C242BAC00F3C020 /* AirplaneTracker.swift */; }; 8DEC6F2E2C2E9C3000AC6209 /* ADSBFileRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEC6F2D2C2E9C3000AC6209 /* ADSBFileRunner.swift */; }; @@ -46,9 +35,6 @@ 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 */; }; - 8DF756792C05A3D7008E8DFF /* Decoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DF756782C05A3D7008E8DFF /* Decoder.swift */; }; - 8DF7567A2C06F550008E8DFF /* Decoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DF756782C05A3D7008E8DFF /* Decoder.swift */; }; - 8DF7567C2C09B7F7008E8DFF /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DF7567B2C09B7F7008E8DFF /* Query.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 */; }; @@ -59,6 +45,27 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 8D4F383B3065267F00EA3890 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8DF756572C0595AA008E8DFF /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D4F382E3065267E00EA3890; + remoteInfo = ADSBDecoderFramework; + }; + 8D4F383D3065267F00EA3890 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8DF756572C0595AA008E8DFF /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8DF756812C10556A008E8DFF; + remoteInfo = LearnMapKit; + }; + 8D4F38423065267F00EA3890 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8DF756572C0595AA008E8DFF /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D4F382E3065267E00EA3890; + remoteInfo = ADSBDecoderFramework; + }; 8DF756932C10556C008E8DFF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 8DF756572C0595AA008E8DFF /* Project object */; @@ -76,6 +83,17 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 8D4F38493065267F00EA3890 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 8D4F38453065267F00EA3890 /* ADSBDecoderFramework.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; 8D93B6742C3FE6F400C91865 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -115,11 +133,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 8D4F382F3065267E00EA3890 /* ADSBDecoderFramework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ADSBDecoderFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8D4F38393065267F00EA3890 /* ADSBDecoderFrameworkTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ADSBDecoderFrameworkTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 8D8480F02C60C79E007ACD95 /* ADSBDataQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ADSBDataQueue.swift; sourceTree = ""; }; 8D8480F22C60C7E6007ACD95 /* ADSBNetRunner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ADSBNetRunner.swift; sourceTree = ""; }; - 8D93B64B2C32030B00C91865 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; - 8D93B6522C32095300C91865 /* ADSBRegEx.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ADSBRegEx.swift; sourceTree = ""; }; - 8D93B6562C3D27A000C91865 /* Configs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configs.swift; sourceTree = ""; }; 8D93B6762C3FE6F400C91865 /* Net1090 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Net1090; sourceTree = BUILT_PRODUCTS_DIR; }; 8D93B6782C3FE6F400C91865 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 8D93B6872C45986700C91865 /* ADSBStats */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ADSBStats; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -127,7 +144,6 @@ 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 = ""; }; - 8DB347BE2C1C501200F3C020 /* PositionDecoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionDecoder.swift; sourceTree = ""; }; 8DB347C42C242BAC00F3C020 /* AirplaneTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AirplaneTracker.swift; sourceTree = ""; }; 8DEC6F2D2C2E9C3000AC6209 /* ADSBFileRunner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ADSBFileRunner.swift; sourceTree = ""; }; 8DEC6F312C31530C00AC6209 /* FlighState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlighState.swift; sourceTree = ""; }; @@ -135,8 +151,6 @@ 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 = ""; }; - 8DF756782C05A3D7008E8DFF /* Decoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Decoder.swift; sourceTree = ""; }; - 8DF7567B2C09B7F7008E8DFF /* Query.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Query.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 = ""; }; 8DF756862C10556A008E8DFF /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -150,7 +164,100 @@ 8DF756A22C10556C008E8DFF /* LearnMapKitUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LearnMapKitUITestsLaunchTests.swift; sourceTree = ""; }; /* End PBXFileReference section */ +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + 8D4F384E306528A200EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + FileUtils.swift, + ); + target = 8DF7565E2C0595AA008E8DFF /* ADSBDecoder */; + }; + 8D4F384F306528A200EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + FileUtils.swift, + ); + target = 8DF756812C10556A008E8DFF /* LearnMapKit */; + }; + 8D4F3850306528A200EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + FileUtils.swift, + ); + target = 8D93B6862C45986700C91865 /* ADSBStats */; + }; + 8D4F3851306528A200EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + FileUtils.swift, + ); + target = 8D4F382E3065267E00EA3890 /* ADSBDecoderFramework */; + }; + 8D4F38533065291400EA3890 /* 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, + ); + target = 8D93B6862C45986700C91865 /* ADSBStats */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 8D4F38303065267E00EA3890 /* ADSBDecoderFramework */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (8D4F38533065291400EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 8D4F38543065291400EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 8D4F38553065291400EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, 8D4F38563065291400EA3890 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); 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 = ""; }; +/* End PBXFileSystemSynchronizedRootGroup section */ + /* Begin PBXFrameworksBuildPhase section */ + 8D4F382C3065267E00EA3890 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D4F385F30652A9200EA3890 /* Collections in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8D4F38363065267F00EA3890 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D4F383A3065267F00EA3890 /* ADSBDecoderFramework.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8D93B6732C3FE6F400C91865 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -172,6 +279,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 8D4F3852306528DE00EA3890 /* ADSBDecoderFramework.framework in Frameworks */, 8DB347C32C1C53ED00F3C020 /* Collections in Frameworks */, 8DF7566C2C0595F6008E8DFF /* ArgumentParser in Frameworks */, ); @@ -188,6 +296,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 8D4F38443065267F00EA3890 /* ADSBDecoderFramework.framework in Frameworks */, 8D8480EF2C56344B007ACD95 /* ArgumentParser in Frameworks */, 8DEC6F302C2E9F0E00AC6209 /* Collections in Frameworks */, 8D93B6812C3FEA5600C91865 /* NIO in Frameworks */, @@ -238,6 +347,7 @@ 8DF756562C0595AA008E8DFF = { isa = PBXGroup; children = ( + 8D4F384D3065289B00EA3890 /* Utils */, 8DF756692C0595BB008E8DFF /* Data */, 8DF756612C0595AA008E8DFF /* ADSBDecoder */, 8DF756722C059969008E8DFF /* Test */, @@ -246,6 +356,8 @@ 8DF7569F2C10556C008E8DFF /* LearnMapKitUITests */, 8D93B6772C3FE6F400C91865 /* Net1090 */, 8D93B6882C45986700C91865 /* ADSBStats */, + 8D4F38303065267E00EA3890 /* ADSBDecoderFramework */, + 8D4F383F3065267F00EA3890 /* ADSBDecoderFrameworkTests */, 8DF756602C0595AA008E8DFF /* Products */, 8DB347C12C1C53ED00F3C020 /* Frameworks */, ); @@ -261,6 +373,8 @@ 8DF7569C2C10556C008E8DFF /* LearnMapKitUITests.xctest */, 8D93B6762C3FE6F400C91865 /* Net1090 */, 8D93B6872C45986700C91865 /* ADSBStats */, + 8D4F382F3065267E00EA3890 /* ADSBDecoderFramework.framework */, + 8D4F38393065267F00EA3890 /* ADSBDecoderFrameworkTests.xctest */, ); name = Products; sourceTree = ""; @@ -269,13 +383,7 @@ isa = PBXGroup; children = ( 8DF756622C0595AA008E8DFF /* main.swift */, - 8DF756782C05A3D7008E8DFF /* Decoder.swift */, - 8DF7567B2C09B7F7008E8DFF /* Query.swift */, - 8DB347BE2C1C501200F3C020 /* PositionDecoder.swift */, 8DB347C42C242BAC00F3C020 /* AirplaneTracker.swift */, - 8D93B64B2C32030B00C91865 /* Utils.swift */, - 8D93B6522C32095300C91865 /* ADSBRegEx.swift */, - 8D93B6562C3D27A000C91865 /* Configs.swift */, ); path = ADSBDecoder; sourceTree = ""; @@ -340,7 +448,66 @@ }; /* End PBXGroup section */ +/* Begin PBXHeadersBuildPhase section */ + 8D4F382A3065267E00EA3890 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + /* Begin PBXNativeTarget section */ + 8D4F382E3065267E00EA3890 /* ADSBDecoderFramework */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8D4F38463065267F00EA3890 /* Build configuration list for PBXNativeTarget "ADSBDecoderFramework" */; + buildPhases = ( + 8D4F382A3065267E00EA3890 /* Headers */, + 8D4F382B3065267E00EA3890 /* Sources */, + 8D4F382C3065267E00EA3890 /* Frameworks */, + 8D4F382D3065267E00EA3890 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 8D4F38303065267E00EA3890 /* ADSBDecoderFramework */, + 8D4F384D3065289B00EA3890 /* Utils */, + ); + name = ADSBDecoderFramework; + packageProductDependencies = ( + 8D4F385E30652A9200EA3890 /* Collections */, + ); + productName = ADSBDecoderFramework; + productReference = 8D4F382F3065267E00EA3890 /* ADSBDecoderFramework.framework */; + productType = "com.apple.product-type.framework"; + }; + 8D4F38383065267F00EA3890 /* ADSBDecoderFrameworkTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8D4F384A3065267F00EA3890 /* Build configuration list for PBXNativeTarget "ADSBDecoderFrameworkTests" */; + buildPhases = ( + 8D4F38353065267F00EA3890 /* Sources */, + 8D4F38363065267F00EA3890 /* Frameworks */, + 8D4F38373065267F00EA3890 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 8D4F383C3065267F00EA3890 /* PBXTargetDependency */, + 8D4F383E3065267F00EA3890 /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + 8D4F383F3065267F00EA3890 /* ADSBDecoderFrameworkTests */, + ); + name = ADSBDecoderFrameworkTests; + packageProductDependencies = ( + ); + productName = ADSBDecoderFrameworkTests; + productReference = 8D4F38393065267F00EA3890 /* ADSBDecoderFrameworkTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 8D93B6752C3FE6F400C91865 /* Net1090 */ = { isa = PBXNativeTarget; buildConfigurationList = 8D93B67A2C3FE6F400C91865 /* Build configuration list for PBXNativeTarget "Net1090" */; @@ -427,10 +594,12 @@ 8DF7567E2C10556A008E8DFF /* Sources */, 8DF7567F2C10556A008E8DFF /* Frameworks */, 8DF756802C10556A008E8DFF /* Resources */, + 8D4F38493065267F00EA3890 /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( + 8D4F38433065267F00EA3890 /* PBXTargetDependency */, ); name = LearnMapKit; packageProductDependencies = ( @@ -485,9 +654,16 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1540; + LastSwiftUpdateCheck = 2700; LastUpgradeCheck = 1530; TargetAttributes = { + 8D4F382E3065267E00EA3890 = { + CreatedOnToolsVersion = 27.0; + }; + 8D4F38383065267F00EA3890 = { + CreatedOnToolsVersion = 27.0; + TestTargetID = 8DF756812C10556A008E8DFF; + }; 8D93B6752C3FE6F400C91865 = { CreatedOnToolsVersion = 15.4; }; @@ -538,11 +714,27 @@ 8DF7569B2C10556C008E8DFF /* LearnMapKitUITests */, 8D93B6752C3FE6F400C91865 /* Net1090 */, 8D93B6862C45986700C91865 /* ADSBStats */, + 8D4F382E3065267E00EA3890 /* ADSBDecoderFramework */, + 8D4F38383065267F00EA3890 /* ADSBDecoderFrameworkTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 8D4F382D3065267E00EA3890 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8D4F38373065267F00EA3890 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8DF756802C10556A008E8DFF /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -569,6 +761,20 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 8D4F382B3065267E00EA3890 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8D4F38353065267F00EA3890 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8D93B6722C3FE6F400C91865 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -583,13 +789,7 @@ buildActionMask = 2147483647; files = ( 8D93B6942C4598E300C91865 /* AirplaneTracker.swift in Sources */, - 8D93B6912C4598B300C91865 /* PositionDecoder.swift in Sources */, - 8D93B6932C4598D900C91865 /* Query.swift in Sources */, 8D93B68A2C45986700C91865 /* main.swift in Sources */, - 8D93B68F2C4598A900C91865 /* ADSBRegEx.swift in Sources */, - 8D93B68E2C4598A500C91865 /* Configs.swift in Sources */, - 8D93B6922C4598B800C91865 /* Decoder.swift in Sources */, - 8D93B6902C4598AC00C91865 /* Utils.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -598,13 +798,7 @@ buildActionMask = 2147483647; files = ( 8DB347C52C242BAC00F3C020 /* AirplaneTracker.swift in Sources */, - 8D93B6572C3D27A000C91865 /* Configs.swift in Sources */, - 8DF756792C05A3D7008E8DFF /* Decoder.swift in Sources */, - 8DF7567C2C09B7F7008E8DFF /* Query.swift in Sources */, 8DF756632C0595AA008E8DFF /* main.swift in Sources */, - 8D93B6532C32095300C91865 /* ADSBRegEx.swift in Sources */, - 8DB347BF2C1C501200F3C020 /* PositionDecoder.swift in Sources */, - 8D93B64C2C32030B00C91865 /* Utils.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -612,9 +806,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8DF7567A2C06F550008E8DFF /* Decoder.swift in Sources */, 8DF756742C059969008E8DFF /* main.swift in Sources */, - 8D93B6822C412C0A00C91865 /* Configs.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -622,20 +814,15 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8D93B64F2C3206DD00C91865 /* AirplaneTracker.swift in Sources */, 8D93B69C2C4A727300C91865 /* NetworkConfigure.swift in Sources */, 8DF756872C10556A008E8DFF /* ContentView.swift in Sources */, - 8D93B6552C32099B00C91865 /* Utils.swift in Sources */, 8DEC6F2E2C2E9C3000AC6209 /* ADSBFileRunner.swift in Sources */, 8D93B69F2C4A7A0700C91865 /* NetADSBDecoder.swift in Sources */, 8D8480F32C60C7E6007ACD95 /* ADSBNetRunner.swift in Sources */, - 8D93B6502C3206E700C91865 /* PositionDecoder.swift in Sources */, - 8D93B6582C3D290C00C91865 /* Configs.swift in Sources */, - 8D93B6512C3206EB00C91865 /* Decoder.swift in Sources */, 8DEC6F322C31530C00AC6209 /* FlighState.swift in Sources */, + 8D4F386030652B4A00EA3890 /* AirplaneTracker.swift in Sources */, 8DF756852C10556A008E8DFF /* LearnMapKitApp.swift in Sources */, 8D8480F12C60C79E007ACD95 /* ADSBDataQueue.swift in Sources */, - 8D93B6542C32095800C91865 /* ADSBRegEx.swift in Sources */, 8D93B69A2C4A665B00C91865 /* NetConfigView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -660,6 +847,21 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 8D4F383C3065267F00EA3890 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8D4F382E3065267E00EA3890 /* ADSBDecoderFramework */; + targetProxy = 8D4F383B3065267F00EA3890 /* PBXContainerItemProxy */; + }; + 8D4F383E3065267F00EA3890 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8DF756812C10556A008E8DFF /* LearnMapKit */; + targetProxy = 8D4F383D3065267F00EA3890 /* PBXContainerItemProxy */; + }; + 8D4F38433065267F00EA3890 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8D4F382E3065267E00EA3890 /* ADSBDecoderFramework */; + targetProxy = 8D4F38423065267F00EA3890 /* PBXContainerItemProxy */; + }; 8DF756942C10556C008E8DFF /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 8DF756812C10556A008E8DFF /* LearnMapKit */; @@ -673,11 +875,127 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ + 8D4F38473065267F00EA3890 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 26.6; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = RadioTeam.ADSBDecoderFramework; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 8D4F38483065267F00EA3890 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 26.6; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = RadioTeam.ADSBDecoderFramework; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 8D4F384B3065267F00EA3890 /* 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.ADSBDecoderFrameworkTests; + 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)/LearnMapKit.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/LearnMapKit"; + }; + name = Debug; + }; + 8D4F384C3065267F00EA3890 /* 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.ADSBDecoderFrameworkTests; + 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)/LearnMapKit.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/LearnMapKit"; + }; + name = Release; + }; 8D93B67B2C3FE6F400C91865 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 53B26AJZ4Z; + DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; MACOSX_DEPLOYMENT_TARGET = 14.5; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -689,7 +1007,7 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 53B26AJZ4Z; + DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; MACOSX_DEPLOYMENT_TARGET = 14.5; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -700,8 +1018,9 @@ 8D93B68C2C45986700C91865 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 53B26AJZ4Z; + DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; MACOSX_DEPLOYMENT_TARGET = 14.5; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -712,8 +1031,9 @@ 8D93B68D2C45986700C91865 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 53B26AJZ4Z; + DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; MACOSX_DEPLOYMENT_TARGET = 14.5; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -887,7 +1207,7 @@ COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"LearnMapKit/Preview Content\""; - DEVELOPMENT_TEAM = 53B26AJZ4Z; + DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; @@ -914,7 +1234,7 @@ COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"LearnMapKit/Preview Content\""; - DEVELOPMENT_TEAM = 53B26AJZ4Z; + DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; @@ -934,7 +1254,6 @@ 8DF756A82C10556C008E8DFF /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; @@ -952,7 +1271,6 @@ 8DF756A92C10556C008E8DFF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; @@ -970,7 +1288,6 @@ 8DF756AB2C10556C008E8DFF /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; @@ -986,7 +1303,6 @@ 8DF756AC2C10556C008E8DFF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; @@ -1002,6 +1318,24 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 8D4F38463065267F00EA3890 /* Build configuration list for PBXNativeTarget "ADSBDecoderFramework" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8D4F38473065267F00EA3890 /* Debug */, + 8D4F38483065267F00EA3890 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8D4F384A3065267F00EA3890 /* Build configuration list for PBXNativeTarget "ADSBDecoderFrameworkTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8D4F384B3065267F00EA3890 /* Debug */, + 8D4F384C3065267F00EA3890 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 8D93B67A2C3FE6F400C91865 /* Build configuration list for PBXNativeTarget "Net1090" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -1104,6 +1438,11 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 8D4F385E30652A9200EA3890 /* Collections */ = { + isa = XCSwiftPackageProductDependency; + package = 8DB347C02C1C53CB00F3C020 /* XCRemoteSwiftPackageReference "swift-collections" */; + productName = Collections; + }; 8D8480EE2C56344B007ACD95 /* ArgumentParser */ = { isa = XCSwiftPackageProductDependency; package = 8DF7566A2C0595F6008E8DFF /* XCRemoteSwiftPackageReference "swift-argument-parser" */; diff --git a/ADSBDecoder.xcodeproj/xcuserdata/jackyjack.xcuserdatad/xcschemes/xcschememanagement.plist b/ADSBDecoder.xcodeproj/xcuserdata/jackyjack.xcuserdatad/xcschemes/xcschememanagement.plist index 70a9ecd..2b937de 100644 --- a/ADSBDecoder.xcodeproj/xcuserdata/jackyjack.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/ADSBDecoder.xcodeproj/xcuserdata/jackyjack.xcuserdatad/xcschemes/xcschememanagement.plist @@ -9,10 +9,15 @@ orderHint 0 + ADSBDecoderFramework.xcscheme_^#shared#^_ + + orderHint + 4 + ADSBStats.xcscheme_^#shared#^_ orderHint - 3 + 5 LearnMapKit.xcscheme_^#shared#^_ @@ -22,16 +27,21 @@ Net1090.xcscheme_^#shared#^_ orderHint - 4 + 2 Test.xcscheme_^#shared#^_ orderHint - 2 + 3 SuppressBuildableAutocreation + 8D4F382E3065267E00EA3890 + + primary + + 8DF7565E2C0595AA008E8DFF primary diff --git a/ADSBDecoder/ADSBRegEx.swift b/ADSBDecoder/ADSBRegEx.swift deleted file mode 100644 index 2841467..0000000 --- a/ADSBDecoder/ADSBRegEx.swift +++ /dev/null @@ -1,87 +0,0 @@ -// -// ADSBRegEx.swift -// ADSBDecoder -// -// Created by Jacky Jack on 30/06/2024. -// - -import Foundation -import RegexBuilder -/* -let matchADSBLong = Regex { - Anchor.startOfLine - "*" - - Repeat( - CharacterClass( - ("a"..."f"), - ("0"..."9") - ) - ,count:28) - - ";" -}*/ -class MatchADSBLong { - let matchADSBLong = Regex { - Anchor.startOfLine - "*" - - Repeat( - CharacterClass( - ("a"..."f"), - ("0"..."9") - ) - ,count:28) - - ";" - } - - func prefixMatch(_ line: String) -> Regex.RegexOutput>.Match? { - do { - if let match = try matchADSBLong.prefixMatch(in: line) { - return match - } - } catch { - return nil - } - return nil - } -} - -/* -let matchADSBShort = Regex { - Anchor.startOfLine - "*" - Repeat( - CharacterClass( - ("a"..."f"), - ("0"..."9") - ) - ,count:14) - ";" -}*/ - -class MatchADSBShort { - let matchADSBShort = Regex { - Anchor.startOfLine - "*" - Repeat( - CharacterClass( - ("a"..."f"), - ("0"..."9") - ) - ,count:14) - ";" - } - - func prefixMatch(_ line: String) -> Regex.RegexOutput>.Match? { - do { - if let match = try matchADSBShort.prefixMatch(in: line) { - return match - } - } catch { - return nil - } - return nil - } -} diff --git a/ADSBDecoder/Configs.swift b/ADSBDecoder/Configs.swift deleted file mode 100644 index a42e745..0000000 --- a/ADSBDecoder/Configs.swift +++ /dev/null @@ -1,10 +0,0 @@ -// -// Configs.swift -// ADSBDecoder -// -// Created by Jacky Jack on 09/07/2024. -// - -import Foundation - -let decoder_debug_mode = false diff --git a/ADSBDecoder/Decoder.swift b/ADSBDecoder/Decoder.swift deleted file mode 100644 index a9724b6..0000000 --- a/ADSBDecoder/Decoder.swift +++ /dev/null @@ -1,249 +0,0 @@ -// -// Decoder.swift -// ADSBDecoder -// -// Created by Jacky Jack on 28/05/2024. -// - -import Foundation - -func BarometricAltitudeFeat(_ altitude: UInt16) -> Int { - let QBit = (altitude>>4)&0x1 - if QBit == 1 { - //remove qbit - let part1:UInt16 = altitude&0xf - let part2:UInt16 = (altitude>>1)&0x7ff0 - let altitude25 = part1 + part2 - //print("altitude2 \(altitude25) ") - return Int(altitude25)*25-1000 - } - return Int(altitude)*100-1000 -} - -class Decoder { - var adsb_data: String = "" - var DataFormat: UInt32 = 0; - - init (_ adsb_data: String) { - //print(adsb_data) - self.adsb_data = adsb_data - //get the first 8 bits as integer - let startI = adsb_data.startIndex - let endI = adsb_data.index(startI, offsetBy: 1) - let firstByteString = adsb_data[startI...endI] - //print("\(firstByteString)") - if let ControlMsg = UInt32(firstByteString, radix: 16) { - //print("ControlMsg = \(ControlMsg)") - let CM_DataFormat = (ControlMsg&0xF8)>>3 - DataFormat = CM_DataFormat - //let CM_TranspoderCapability = ControlMsg&(0x7) - } - //print("Data Format \(DataFormat)") - } - - func getDataFormat17() -> DataFormat17? { - - if (DataFormat != 17) { - return nil - } - //let startI = adsb_data.index(adsb_data.startIndex, offsetBy: 1) - //let endI = adsb_data.index(adsb_data.endIndex, offsetBy: -1) - //let adsbData = adsb_data[startI...endI] - let ret:DataFormat17 = DataFormat17(adsb_data) - - - - return ret; - } - - func getDataFormat18() { - print("Not implemented") - } - -} - -func ICAOAlphabet(_ code: UInt8) -> String { - if ((code>=1) && (code<=26)) { - return String(UnicodeScalar(code+64)) - } else if ((code >= 48)&&(code<=57)) { - return String(UnicodeScalar(code)) - } else if (code==32) { - return " " - } - return "#" -} - -func ICAO2String(_ b1: UInt8, _ b2: UInt8, _ b3: UInt8, _ b4: UInt8, _ b5: UInt8, _ b6: UInt8, _ b7: UInt8, _ b8: UInt8) -> String { - return ICAOAlphabet(b1)+ICAOAlphabet(b2)+ICAOAlphabet(b3)+ICAOAlphabet(b4)+ICAOAlphabet(b5)+ICAOAlphabet(b6)+ICAOAlphabet(b7)+ICAOAlphabet(b8) -} - -class DataFormat17 { - - let DataFormat=17 //0:5 - var Capability=0 //5:7 - var AddressAnnounced=0 //8:31 - var TypeCode=0 //32:36 - var MovementField=0//37:43 - var HeadingBit=0//44 - var HeadingField=0//45:51 - //var CPROddEven=0//53 - //var CPRlat=0//54:70 - //var CPRlon=0//71:87 - var ParityIntegrity=0//88-111 - - //all avaliable message types - var messageIdentification:ADSBTypeCodeIndentification? = nil - var messageAirbornPositon:ADSBTypeCodeAirbonePositon? = nil - - init(_ adsb_data: String) { - //print("Dataformat: 17!") - //print(adsb_data) - - var bindata:[UInt8] = [] - - var startN = adsb_data.startIndex - var endN = adsb_data.index(startN, offsetBy: 1) - var count=0//start index value - while (count>1)&0x7 - //print(String(format: "cap %02x", cap)) - Capability = Int(cap) - - //Decode Address Announcement - let address_ann = UInt32(bindata[1])<<16 + UInt32(bindata[2])<<8 + UInt32(bindata[3]) - //print(String(format: "address %06x", address_ann)) - - AddressAnnounced = Int(address_ann) - - //Decode Type Code - let tc_byte = bindata[4] >> 3 - //print(String(format: "tc %02d", tc_byte)) - - TypeCode = Int(tc_byte) - - //aircraft indentification and category - if (tc_byte == 4) { - let msg = ADSBTypeCodeIndentification(bindata[4...10]) - if decoder_debug_mode { - print("=====ADSB MESSSGE 04 =======") - print(msg) - print("============================") - } - - messageIdentification = msg - //airborn position - } else if ((tc_byte >= 8) && (tc_byte <= 18)) { - let msg = ADSBTypeCodeAirbonePositon(bindata[4...10]) - if decoder_debug_mode { - print(String(format:"=====ADSB MESSSGE %02d ======= AA:%04d", tc_byte, AddressAnnounced)) - print(msg) - print("============================") - } - - messageAirbornPositon = msg - //airborn velocity - } else if (tc_byte == 19) { - if decoder_debug_mode { - print("=====ADSB MESSSGE 19 =======") - print("=====VELOCITY =======") - } - } else { - if decoder_debug_mode { - print("=====ADSB MESSSGE UNKNOWN =======") - } - } - } -} - -class ADSBTypeCodeIndentification: CustomStringConvertible { - var TypeCode:Int = 4 - var Category:Int = 0 - var ICAOName:String - - init(_ bindata:ArraySlice) { - let cat = bindata[4]&0x7 - Category = Int(cat) - let char_0 = bindata[5]>>2 - let char_1 = (bindata[5]&0x3)<<4 + bindata[6]>>4 - let char_2 = (bindata[6]&0xf)<<2 + (bindata[7]>>6)&0x3 - let char_3 = (bindata[7])&0x3f - let char_4 = bindata[8]>>2 - let char_5 = (bindata[8]&0x3)<<4 + bindata[9]>>4 - let char_6 = (bindata[9]&0xf)<<2 + (bindata[10]>>6) - let char_7 = bindata[10]&0x3f - - //print(char_0, char_1, char_2,char_3,char_4,char_5,char_6,char_7) - ICAOName = ICAO2String(char_0, char_1, char_2, char_3, char_4, char_5, char_6, char_7) - //print("ICAO name \(ICAOName)") - } - - var description: String { - let description = "TypeCode \(TypeCode) Cat \(Category) Flight name \(ICAOName)" - return description - } -} - -//DF17 message types codes 8 to 18 -class ADSBTypeCodeAirbonePositon:CustomStringConvertible { - var TypeCode:Int = 11 - var SurveillanceStatus: Int = 0 - var SingleAntennaFlag: Int = 0 - var Altitude: Int = 0 - var Time: Int = 0 - var CPRFormat: Int = 0 - var Latitude: Int = 0 - var Longitude: Int = 0 - - init(_ bindata:ArraySlice) { - let ss = (bindata[4]>>1)&(0x3) - SurveillanceStatus = Int(ss) - let saf = bindata[5]&0x1 - SingleAntennaFlag = Int(saf) - let altitude = UInt16(bindata[5])<<4 + (UInt16(bindata[6])>>4)&0xf - //print(altitude) - Altitude = BarometricAltitudeFeat(altitude) - let time = (bindata[6]>>3)&0x1 - Time = Int(time) - let cpr = (bindata[6]>>2)&0x1 - CPRFormat = Int(cpr) - let lat:UInt32 = UInt32(bindata[6]&0x3)<<15 + UInt32(bindata[7])<<7 + UInt32(bindata[8]>>1) - Latitude = Int(lat) - let lon:UInt32 = UInt32(bindata[8]&0x1)<<16 + UInt32(bindata[9])<<8 + UInt32(bindata[10]) - Longitude = Int(lon) - } - - var description: String { - var description = "SS \(SurveillanceStatus) SAF \(SingleAntennaFlag) Altitude \(Altitude)ft \n" - description += "Time \(Time) CPR \(CPRFormat)" - if (CPRFormat == 0) { - description += "even" - } else { - description += "odd" - } - description += "\n" - description += "Lat \(Latitude) Long \(Longitude)" - return description - } -} - -class DataFormat19:CustomStringConvertible { - init(_ bindata:ArraySlice) { - print("Dataformat: 19") - } - - var description: String { - return "" - } -} diff --git a/ADSBDecoder/PositionDecoder.swift b/ADSBDecoder/PositionDecoder.swift deleted file mode 100644 index 85b9d49..0000000 --- a/ADSBDecoder/PositionDecoder.swift +++ /dev/null @@ -1,221 +0,0 @@ -// -// PositionDecoder.swift -// ADSBDecoder -// -// Created by Jacky Jack on 14/06/2024. -// - -import Foundation -import Collections - -struct PositionData { - var cpr_lat: UInt32 - var cpr_long: UInt32 - var even: Bool - var cprtime: Int64 -} - -func cpr_mod(_ a: Int, _ b: Int) -> Int { - var res:Int = a % b; - if (res < 0) { - res += b - } - return res; -} - -/* The NL function uses the precomputed table from 1090-WP-9-14 */ -func cpr_NLFunction(_ _lat: Double) -> Int { - var lat:Double = _lat - if (lat < 0) { - lat = -lat - } /* Table is simmetric about the equator. */ - if (lat < 10.47047130) {return 59} - if (lat < 14.82817437) {return 58} - if (lat < 18.18626357) {return 57} - if (lat < 21.02939493) {return 56} - if (lat < 23.54504487) {return 55} - if (lat < 25.82924707) {return 54} - if (lat < 27.93898710) {return 53} - if (lat < 29.91135686) {return 52} - if (lat < 31.77209708) {return 51} - if (lat < 33.53993436) {return 50} - if (lat < 35.22899598) {return 49} - if (lat < 36.85025108) {return 48} - if (lat < 38.41241892) {return 47} - if (lat < 39.92256684) {return 46} - if (lat < 41.38651832) {return 45} - if (lat < 42.80914012) {return 44} - if (lat < 44.19454951) {return 43} - if (lat < 45.54626723) {return 42} - if (lat < 46.86733252) {return 41} - if (lat < 48.16039128) {return 40} - if (lat < 49.42776439) {return 39} - if (lat < 50.67150166) {return 38} - if (lat < 51.89342469) {return 37} - if (lat < 53.09516153) {return 36} - if (lat < 54.27817472) {return 35} - if (lat < 55.44378444) {return 34} - if (lat < 56.59318756) {return 33} - if (lat < 57.72747354) {return 32} - if (lat < 58.84763776) {return 31} - if (lat < 59.95459277) {return 30} - if (lat < 61.04917774) {return 29} - if (lat < 62.13216659) {return 28} - if (lat < 63.20427479) {return 27} - if (lat < 64.26616523) {return 26} - if (lat < 65.31845310) {return 25} - if (lat < 66.36171008) {return 24} - if (lat < 67.39646774) {return 23} - if (lat < 68.42322022) {return 22} - if (lat < 69.44242631) {return 21} - if (lat < 70.45451075) {return 20} - if (lat < 71.45986473) {return 19} - if (lat < 72.45884545) {return 18} - if (lat < 73.45177442) {return 17} - if (lat < 74.43893416) {return 16} - if (lat < 75.42056257) {return 15} - if (lat < 76.39684391) {return 14} - if (lat < 77.36789461) {return 13} - if (lat < 78.33374083) {return 12} - if (lat < 79.29428225) {return 11} - if (lat < 80.24923213) {return 10} - if (lat < 81.19801349) {return 9} - if (lat < 82.13956981) {return 8} - if (lat < 83.07199445) {return 7} - if (lat < 83.99173563) {return 6} - if (lat < 84.89166191) {return 5} - if (lat < 85.75541621) {return 4} - if (lat < 86.53536998) {return 3} - if (lat < 87.00000000) {return 2} - else {return 1} -} - -func cpr_NFunction(_ lat: Double, _ isodd: Int) -> Int { - var nl:Int = cpr_NLFunction(lat) - isodd; - if (nl < 1) { - nl = 1 - } - return nl; -} - -func cpr_DlonFunction(_ lat: Double, _ isodd: Int) -> Double { - return 360.0 / Double(cpr_NFunction(lat, isodd)); -} - -func mstime() -> Int64 { - var tv:timeval = timeval(tv_sec: 0, tv_usec: 0) - var mst:Int64=0; - - gettimeofday(&tv, nil); - mst = Int64(tv.tv_sec)*1000; - mst += Int64(tv.tv_usec)/1000; - return mst; -} - -class PositionDecoder { - - var long: Double = 0.0 - var lat: Double = 0.0 - var ready: Bool = false - var newposition: Bool = false - - //initialise first values so this values is nonsence - var queue: Deque = [] - - 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)) - } - - 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)) - } - - func getPosition() -> (Double, Double)? { - if (ready) { - return (lat, long) - } - return nil - } - - //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") - 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 - - //print("Position queue is ready to calculate location \(cpr_even) \(cpr_odd)") - // from here https://github.com/antirez/dump1090/blob/master/dump1090.c#L1718 - let AirDlat0:Double = 360.0/60.0 - let AirDlat1:Double = 360.0/59.0 - - let lat0 = Int(cpr_even.cpr_lat) - let lat1 = Int(cpr_odd.cpr_lat) - let lon0 = Int(cpr_even.cpr_long) - let lon1 = Int(cpr_odd.cpr_long) - - //latitude index - let j:Int = Int(floor(((59.0*Double(lat0) - 60.0*Double(lat1)) / 131072.0) + 0.5)) - - var rlat0:Double = AirDlat0 * (Double(cpr_mod(j,60)) + Double(lat0) / 131072.0) - var rlat1:Double = AirDlat1 * (Double(cpr_mod(j,59)) + Double(lat1) / 131072.0) - - if (rlat0 >= 270.0) { - rlat0 -= 360.0 - } - if (rlat1 >= 270.0) { - rlat1 -= 360.0 - } - - /* Check that both are in the same latitude zone, or abort. */ - if (cpr_NLFunction(rlat0) != cpr_NLFunction(rlat1)) { - print("Not same lat?!") - return false - } - - /* Compute ni and the longitude index m */ - if (cpr_even.cprtime > cpr_odd.cprtime) { - /* Use even packet. */ - let ni:Int = cpr_NFunction(rlat0,0); - let m:Int = Int( - floor((((Double(lon0) * (Double(cpr_NLFunction(rlat0))-1.0)) - - (Double(lon1) * Double(cpr_NLFunction(rlat0)))) / 131072.0) + 0.5) - ); - self.long = Double(cpr_DlonFunction(rlat0,0)) * (Double(cpr_mod(m,ni))+Double(lon0)/131072.0); - self.lat = rlat0; - } else { - /* Use odd packet. */ - let ni:Int = cpr_NFunction(rlat1,1); - let m:Int = Int(floor((((Double(lon0) * (Double(cpr_NLFunction(rlat1))-1.0)) - - (Double(lon1) * Double(cpr_NLFunction(rlat1)))) / 131072.0) + 0.5)); - self.long = cpr_DlonFunction(rlat1,1) * (Double(cpr_mod(m,ni))+Double(lon1)/131072.0); - self.lat = rlat1; - } - if (self.long > 180) { - self.long -= 360 - } - - ready = true - return true - } - - -} diff --git a/ADSBDecoder/Query.swift b/ADSBDecoder/Query.swift deleted file mode 100644 index a92d919..0000000 --- a/ADSBDecoder/Query.swift +++ /dev/null @@ -1,126 +0,0 @@ -// -// Query.swift -// ADSBDecoder -// -// Created by Jacky Jack on 31/05/2024. -// - -import Foundation - -class QueryDF: CustomStringConvertible { - - //max I see is 24 - var DFlist:[Int] = Array(repeating: 0, count: 30) - - init() { - - } - - func addDF(_ dataformat: UInt32) { - DFlist[Int(dataformat)] += 1 - } - - func showStat() { - print("DataFormat Count") - for i in 0...(DFlist.count)-1 { - if DFlist[i] != 0 { - print(String(format:" %02d: %05d", i, DFlist[i])) - } - } - } - - var description: String { - var description = "DataFormat Count\n" - for i in 0...(DFlist.count)-1 { - if DFlist[i] != 0 { - description += String(format:" %02d: %04d\n", i, DFlist[i]) - } - } - return description - } -} - -class QueryDF17TC: CustomStringConvertible { - var TClist:[Int] = Array(repeating: 0, count: 32) - - init() { - - } - - func addTC(_ typecode: Int) { - TClist[typecode] += 1 - } - - var description: String { - var description = "DF17 TypeCode Count\n" - for i in 0...(TClist.count-1) { - if TClist[i] != 0 { - description += String(format: " %02d: %04d\n", i, TClist[i]) - } - } - return description - } -} - -class QueryDecodedMessages: CustomStringConvertible { - - var decoded:Int = 0 - var total:Int = 0 - - init() { - - } - - func addDecoded() { - decoded += 1 - total += 1 - } - - func addUndecoded() { - total = total + 1 - } - - 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" - return description - } - -} - - -class QueryDF17TC_decoded: CustomStringConvertible { - var TClist_decoded:[Int] = Array(repeating: 0, count: 32) - var TClist_total:[Int] = Array(repeating: 0, count: 32) - - init() { - - } - - func addDecoded(_ typecode: Int) { - TClist_decoded[typecode] += 1 - TClist_total[typecode] += 1 - } - - func addUndecode(_ typecode: Int) { - TClist_total[typecode] += 1 - } - - var description: String { - var description = "" - var decoded:Int = 0 - var total:Int = 0 - for i in 0...(TClist_decoded.count-1) { - total += TClist_total[i] - decoded += TClist_decoded[i] - if TClist_total[i] != 0 { - description += String(format: " %02d: %04d\n", i, TClist_decoded[i]) - } - } - description += String(format:"Total %d/%d %.1f",decoded,total,Double(Double(decoded)/Double(total))*100) - description += "%\n" - return description - } -} - diff --git a/ADSBDecoder/Utils.swift b/ADSBDecoder/Utils.swift deleted file mode 100644 index 7a7f177..0000000 --- a/ADSBDecoder/Utils.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// Utils.swift -// ADSBDecoder -// -// Created by Jacky Jack on 30/06/2024. -// - -import Foundation - -//return true if file excists -func checkIfFileExists(_ fname: String) -> Bool { - let fm = FileManager.default - if fm.fileExists(atPath: fname) { - return true - } - return false -} - -//get current run directory -func getCurrentDirPath() -> String { - return Process().currentDirectoryPath -} - diff --git a/ADSBDecoder/main.swift b/ADSBDecoder/main.swift index 91ba97b..ace377f 100644 --- a/ADSBDecoder/main.swift +++ b/ADSBDecoder/main.swift @@ -11,7 +11,6 @@ import RegexBuilder import SQLite3 - struct CommandLineArgs: ParsableCommand { @Option(name: .shortAndLong) var inputfile: String @Flag(name: .shortAndLong) var debug:Bool = false diff --git a/ADSBDecoderFramework/ADSBDecoderFramework.docc/ADSBDecoderFramework.md b/ADSBDecoderFramework/ADSBDecoderFramework.docc/ADSBDecoderFramework.md new file mode 100644 index 0000000..588e73d --- /dev/null +++ b/ADSBDecoderFramework/ADSBDecoderFramework.docc/ADSBDecoderFramework.md @@ -0,0 +1,13 @@ +# ``ADSBDecoderFramework`` + +Summary + +## Overview + +Text + +## Topics + +### Group + +- ``Symbol`` \ No newline at end of file diff --git a/ADSBDecoderFramework/ADSBDecoderFramework.swift b/ADSBDecoderFramework/ADSBDecoderFramework.swift new file mode 100644 index 0000000..c2407a0 --- /dev/null +++ b/ADSBDecoderFramework/ADSBDecoderFramework.swift @@ -0,0 +1,9 @@ +// +// ADSBDecoderFramework.swift +// ADSBDecoderFramework +// +// Created by Jacky Jack on 24/09/2026. +// + +import Foundation + diff --git a/ADSBDecoderFramework/ADSBRegEx.swift b/ADSBDecoderFramework/ADSBRegEx.swift new file mode 100644 index 0000000..2841467 --- /dev/null +++ b/ADSBDecoderFramework/ADSBRegEx.swift @@ -0,0 +1,87 @@ +// +// ADSBRegEx.swift +// ADSBDecoder +// +// Created by Jacky Jack on 30/06/2024. +// + +import Foundation +import RegexBuilder +/* +let matchADSBLong = Regex { + Anchor.startOfLine + "*" + + Repeat( + CharacterClass( + ("a"..."f"), + ("0"..."9") + ) + ,count:28) + + ";" +}*/ +class MatchADSBLong { + let matchADSBLong = Regex { + Anchor.startOfLine + "*" + + Repeat( + CharacterClass( + ("a"..."f"), + ("0"..."9") + ) + ,count:28) + + ";" + } + + func prefixMatch(_ line: String) -> Regex.RegexOutput>.Match? { + do { + if let match = try matchADSBLong.prefixMatch(in: line) { + return match + } + } catch { + return nil + } + return nil + } +} + +/* +let matchADSBShort = Regex { + Anchor.startOfLine + "*" + Repeat( + CharacterClass( + ("a"..."f"), + ("0"..."9") + ) + ,count:14) + ";" +}*/ + +class MatchADSBShort { + let matchADSBShort = Regex { + Anchor.startOfLine + "*" + Repeat( + CharacterClass( + ("a"..."f"), + ("0"..."9") + ) + ,count:14) + ";" + } + + func prefixMatch(_ line: String) -> Regex.RegexOutput>.Match? { + do { + if let match = try matchADSBShort.prefixMatch(in: line) { + return match + } + } catch { + return nil + } + return nil + } +} diff --git a/ADSBDecoderFramework/Configs.swift b/ADSBDecoderFramework/Configs.swift new file mode 100644 index 0000000..a42e745 --- /dev/null +++ b/ADSBDecoderFramework/Configs.swift @@ -0,0 +1,10 @@ +// +// Configs.swift +// ADSBDecoder +// +// Created by Jacky Jack on 09/07/2024. +// + +import Foundation + +let decoder_debug_mode = false diff --git a/ADSBDecoderFramework/Decoder.swift b/ADSBDecoderFramework/Decoder.swift new file mode 100644 index 0000000..a9724b6 --- /dev/null +++ b/ADSBDecoderFramework/Decoder.swift @@ -0,0 +1,249 @@ +// +// Decoder.swift +// ADSBDecoder +// +// Created by Jacky Jack on 28/05/2024. +// + +import Foundation + +func BarometricAltitudeFeat(_ altitude: UInt16) -> Int { + let QBit = (altitude>>4)&0x1 + if QBit == 1 { + //remove qbit + let part1:UInt16 = altitude&0xf + let part2:UInt16 = (altitude>>1)&0x7ff0 + let altitude25 = part1 + part2 + //print("altitude2 \(altitude25) ") + return Int(altitude25)*25-1000 + } + return Int(altitude)*100-1000 +} + +class Decoder { + var adsb_data: String = "" + var DataFormat: UInt32 = 0; + + init (_ adsb_data: String) { + //print(adsb_data) + self.adsb_data = adsb_data + //get the first 8 bits as integer + let startI = adsb_data.startIndex + let endI = adsb_data.index(startI, offsetBy: 1) + let firstByteString = adsb_data[startI...endI] + //print("\(firstByteString)") + if let ControlMsg = UInt32(firstByteString, radix: 16) { + //print("ControlMsg = \(ControlMsg)") + let CM_DataFormat = (ControlMsg&0xF8)>>3 + DataFormat = CM_DataFormat + //let CM_TranspoderCapability = ControlMsg&(0x7) + } + //print("Data Format \(DataFormat)") + } + + func getDataFormat17() -> DataFormat17? { + + if (DataFormat != 17) { + return nil + } + //let startI = adsb_data.index(adsb_data.startIndex, offsetBy: 1) + //let endI = adsb_data.index(adsb_data.endIndex, offsetBy: -1) + //let adsbData = adsb_data[startI...endI] + let ret:DataFormat17 = DataFormat17(adsb_data) + + + + return ret; + } + + func getDataFormat18() { + print("Not implemented") + } + +} + +func ICAOAlphabet(_ code: UInt8) -> String { + if ((code>=1) && (code<=26)) { + return String(UnicodeScalar(code+64)) + } else if ((code >= 48)&&(code<=57)) { + return String(UnicodeScalar(code)) + } else if (code==32) { + return " " + } + return "#" +} + +func ICAO2String(_ b1: UInt8, _ b2: UInt8, _ b3: UInt8, _ b4: UInt8, _ b5: UInt8, _ b6: UInt8, _ b7: UInt8, _ b8: UInt8) -> String { + return ICAOAlphabet(b1)+ICAOAlphabet(b2)+ICAOAlphabet(b3)+ICAOAlphabet(b4)+ICAOAlphabet(b5)+ICAOAlphabet(b6)+ICAOAlphabet(b7)+ICAOAlphabet(b8) +} + +class DataFormat17 { + + let DataFormat=17 //0:5 + var Capability=0 //5:7 + var AddressAnnounced=0 //8:31 + var TypeCode=0 //32:36 + var MovementField=0//37:43 + var HeadingBit=0//44 + var HeadingField=0//45:51 + //var CPROddEven=0//53 + //var CPRlat=0//54:70 + //var CPRlon=0//71:87 + var ParityIntegrity=0//88-111 + + //all avaliable message types + var messageIdentification:ADSBTypeCodeIndentification? = nil + var messageAirbornPositon:ADSBTypeCodeAirbonePositon? = nil + + init(_ adsb_data: String) { + //print("Dataformat: 17!") + //print(adsb_data) + + var bindata:[UInt8] = [] + + var startN = adsb_data.startIndex + var endN = adsb_data.index(startN, offsetBy: 1) + var count=0//start index value + while (count>1)&0x7 + //print(String(format: "cap %02x", cap)) + Capability = Int(cap) + + //Decode Address Announcement + let address_ann = UInt32(bindata[1])<<16 + UInt32(bindata[2])<<8 + UInt32(bindata[3]) + //print(String(format: "address %06x", address_ann)) + + AddressAnnounced = Int(address_ann) + + //Decode Type Code + let tc_byte = bindata[4] >> 3 + //print(String(format: "tc %02d", tc_byte)) + + TypeCode = Int(tc_byte) + + //aircraft indentification and category + if (tc_byte == 4) { + let msg = ADSBTypeCodeIndentification(bindata[4...10]) + if decoder_debug_mode { + print("=====ADSB MESSSGE 04 =======") + print(msg) + print("============================") + } + + messageIdentification = msg + //airborn position + } else if ((tc_byte >= 8) && (tc_byte <= 18)) { + let msg = ADSBTypeCodeAirbonePositon(bindata[4...10]) + if decoder_debug_mode { + print(String(format:"=====ADSB MESSSGE %02d ======= AA:%04d", tc_byte, AddressAnnounced)) + print(msg) + print("============================") + } + + messageAirbornPositon = msg + //airborn velocity + } else if (tc_byte == 19) { + if decoder_debug_mode { + print("=====ADSB MESSSGE 19 =======") + print("=====VELOCITY =======") + } + } else { + if decoder_debug_mode { + print("=====ADSB MESSSGE UNKNOWN =======") + } + } + } +} + +class ADSBTypeCodeIndentification: CustomStringConvertible { + var TypeCode:Int = 4 + var Category:Int = 0 + var ICAOName:String + + init(_ bindata:ArraySlice) { + let cat = bindata[4]&0x7 + Category = Int(cat) + let char_0 = bindata[5]>>2 + let char_1 = (bindata[5]&0x3)<<4 + bindata[6]>>4 + let char_2 = (bindata[6]&0xf)<<2 + (bindata[7]>>6)&0x3 + let char_3 = (bindata[7])&0x3f + let char_4 = bindata[8]>>2 + let char_5 = (bindata[8]&0x3)<<4 + bindata[9]>>4 + let char_6 = (bindata[9]&0xf)<<2 + (bindata[10]>>6) + let char_7 = bindata[10]&0x3f + + //print(char_0, char_1, char_2,char_3,char_4,char_5,char_6,char_7) + ICAOName = ICAO2String(char_0, char_1, char_2, char_3, char_4, char_5, char_6, char_7) + //print("ICAO name \(ICAOName)") + } + + var description: String { + let description = "TypeCode \(TypeCode) Cat \(Category) Flight name \(ICAOName)" + return description + } +} + +//DF17 message types codes 8 to 18 +class ADSBTypeCodeAirbonePositon:CustomStringConvertible { + var TypeCode:Int = 11 + var SurveillanceStatus: Int = 0 + var SingleAntennaFlag: Int = 0 + var Altitude: Int = 0 + var Time: Int = 0 + var CPRFormat: Int = 0 + var Latitude: Int = 0 + var Longitude: Int = 0 + + init(_ bindata:ArraySlice) { + let ss = (bindata[4]>>1)&(0x3) + SurveillanceStatus = Int(ss) + let saf = bindata[5]&0x1 + SingleAntennaFlag = Int(saf) + let altitude = UInt16(bindata[5])<<4 + (UInt16(bindata[6])>>4)&0xf + //print(altitude) + Altitude = BarometricAltitudeFeat(altitude) + let time = (bindata[6]>>3)&0x1 + Time = Int(time) + let cpr = (bindata[6]>>2)&0x1 + CPRFormat = Int(cpr) + let lat:UInt32 = UInt32(bindata[6]&0x3)<<15 + UInt32(bindata[7])<<7 + UInt32(bindata[8]>>1) + Latitude = Int(lat) + let lon:UInt32 = UInt32(bindata[8]&0x1)<<16 + UInt32(bindata[9])<<8 + UInt32(bindata[10]) + Longitude = Int(lon) + } + + var description: String { + var description = "SS \(SurveillanceStatus) SAF \(SingleAntennaFlag) Altitude \(Altitude)ft \n" + description += "Time \(Time) CPR \(CPRFormat)" + if (CPRFormat == 0) { + description += "even" + } else { + description += "odd" + } + description += "\n" + description += "Lat \(Latitude) Long \(Longitude)" + return description + } +} + +class DataFormat19:CustomStringConvertible { + init(_ bindata:ArraySlice) { + print("Dataformat: 19") + } + + var description: String { + return "" + } +} diff --git a/ADSBDecoderFramework/PositionDecoder.swift b/ADSBDecoderFramework/PositionDecoder.swift new file mode 100644 index 0000000..85b9d49 --- /dev/null +++ b/ADSBDecoderFramework/PositionDecoder.swift @@ -0,0 +1,221 @@ +// +// PositionDecoder.swift +// ADSBDecoder +// +// Created by Jacky Jack on 14/06/2024. +// + +import Foundation +import Collections + +struct PositionData { + var cpr_lat: UInt32 + var cpr_long: UInt32 + var even: Bool + var cprtime: Int64 +} + +func cpr_mod(_ a: Int, _ b: Int) -> Int { + var res:Int = a % b; + if (res < 0) { + res += b + } + return res; +} + +/* The NL function uses the precomputed table from 1090-WP-9-14 */ +func cpr_NLFunction(_ _lat: Double) -> Int { + var lat:Double = _lat + if (lat < 0) { + lat = -lat + } /* Table is simmetric about the equator. */ + if (lat < 10.47047130) {return 59} + if (lat < 14.82817437) {return 58} + if (lat < 18.18626357) {return 57} + if (lat < 21.02939493) {return 56} + if (lat < 23.54504487) {return 55} + if (lat < 25.82924707) {return 54} + if (lat < 27.93898710) {return 53} + if (lat < 29.91135686) {return 52} + if (lat < 31.77209708) {return 51} + if (lat < 33.53993436) {return 50} + if (lat < 35.22899598) {return 49} + if (lat < 36.85025108) {return 48} + if (lat < 38.41241892) {return 47} + if (lat < 39.92256684) {return 46} + if (lat < 41.38651832) {return 45} + if (lat < 42.80914012) {return 44} + if (lat < 44.19454951) {return 43} + if (lat < 45.54626723) {return 42} + if (lat < 46.86733252) {return 41} + if (lat < 48.16039128) {return 40} + if (lat < 49.42776439) {return 39} + if (lat < 50.67150166) {return 38} + if (lat < 51.89342469) {return 37} + if (lat < 53.09516153) {return 36} + if (lat < 54.27817472) {return 35} + if (lat < 55.44378444) {return 34} + if (lat < 56.59318756) {return 33} + if (lat < 57.72747354) {return 32} + if (lat < 58.84763776) {return 31} + if (lat < 59.95459277) {return 30} + if (lat < 61.04917774) {return 29} + if (lat < 62.13216659) {return 28} + if (lat < 63.20427479) {return 27} + if (lat < 64.26616523) {return 26} + if (lat < 65.31845310) {return 25} + if (lat < 66.36171008) {return 24} + if (lat < 67.39646774) {return 23} + if (lat < 68.42322022) {return 22} + if (lat < 69.44242631) {return 21} + if (lat < 70.45451075) {return 20} + if (lat < 71.45986473) {return 19} + if (lat < 72.45884545) {return 18} + if (lat < 73.45177442) {return 17} + if (lat < 74.43893416) {return 16} + if (lat < 75.42056257) {return 15} + if (lat < 76.39684391) {return 14} + if (lat < 77.36789461) {return 13} + if (lat < 78.33374083) {return 12} + if (lat < 79.29428225) {return 11} + if (lat < 80.24923213) {return 10} + if (lat < 81.19801349) {return 9} + if (lat < 82.13956981) {return 8} + if (lat < 83.07199445) {return 7} + if (lat < 83.99173563) {return 6} + if (lat < 84.89166191) {return 5} + if (lat < 85.75541621) {return 4} + if (lat < 86.53536998) {return 3} + if (lat < 87.00000000) {return 2} + else {return 1} +} + +func cpr_NFunction(_ lat: Double, _ isodd: Int) -> Int { + var nl:Int = cpr_NLFunction(lat) - isodd; + if (nl < 1) { + nl = 1 + } + return nl; +} + +func cpr_DlonFunction(_ lat: Double, _ isodd: Int) -> Double { + return 360.0 / Double(cpr_NFunction(lat, isodd)); +} + +func mstime() -> Int64 { + var tv:timeval = timeval(tv_sec: 0, tv_usec: 0) + var mst:Int64=0; + + gettimeofday(&tv, nil); + mst = Int64(tv.tv_sec)*1000; + mst += Int64(tv.tv_usec)/1000; + return mst; +} + +class PositionDecoder { + + var long: Double = 0.0 + var lat: Double = 0.0 + var ready: Bool = false + var newposition: Bool = false + + //initialise first values so this values is nonsence + var queue: Deque = [] + + 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)) + } + + 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)) + } + + func getPosition() -> (Double, Double)? { + if (ready) { + return (lat, long) + } + return nil + } + + //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") + 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 + + //print("Position queue is ready to calculate location \(cpr_even) \(cpr_odd)") + // from here https://github.com/antirez/dump1090/blob/master/dump1090.c#L1718 + let AirDlat0:Double = 360.0/60.0 + let AirDlat1:Double = 360.0/59.0 + + let lat0 = Int(cpr_even.cpr_lat) + let lat1 = Int(cpr_odd.cpr_lat) + let lon0 = Int(cpr_even.cpr_long) + let lon1 = Int(cpr_odd.cpr_long) + + //latitude index + let j:Int = Int(floor(((59.0*Double(lat0) - 60.0*Double(lat1)) / 131072.0) + 0.5)) + + var rlat0:Double = AirDlat0 * (Double(cpr_mod(j,60)) + Double(lat0) / 131072.0) + var rlat1:Double = AirDlat1 * (Double(cpr_mod(j,59)) + Double(lat1) / 131072.0) + + if (rlat0 >= 270.0) { + rlat0 -= 360.0 + } + if (rlat1 >= 270.0) { + rlat1 -= 360.0 + } + + /* Check that both are in the same latitude zone, or abort. */ + if (cpr_NLFunction(rlat0) != cpr_NLFunction(rlat1)) { + print("Not same lat?!") + return false + } + + /* Compute ni and the longitude index m */ + if (cpr_even.cprtime > cpr_odd.cprtime) { + /* Use even packet. */ + let ni:Int = cpr_NFunction(rlat0,0); + let m:Int = Int( + floor((((Double(lon0) * (Double(cpr_NLFunction(rlat0))-1.0)) - + (Double(lon1) * Double(cpr_NLFunction(rlat0)))) / 131072.0) + 0.5) + ); + self.long = Double(cpr_DlonFunction(rlat0,0)) * (Double(cpr_mod(m,ni))+Double(lon0)/131072.0); + self.lat = rlat0; + } else { + /* Use odd packet. */ + let ni:Int = cpr_NFunction(rlat1,1); + let m:Int = Int(floor((((Double(lon0) * (Double(cpr_NLFunction(rlat1))-1.0)) - + (Double(lon1) * Double(cpr_NLFunction(rlat1)))) / 131072.0) + 0.5)); + self.long = cpr_DlonFunction(rlat1,1) * (Double(cpr_mod(m,ni))+Double(lon1)/131072.0); + self.lat = rlat1; + } + if (self.long > 180) { + self.long -= 360 + } + + ready = true + return true + } + + +} diff --git a/ADSBDecoderFramework/Query.swift b/ADSBDecoderFramework/Query.swift new file mode 100644 index 0000000..a92d919 --- /dev/null +++ b/ADSBDecoderFramework/Query.swift @@ -0,0 +1,126 @@ +// +// Query.swift +// ADSBDecoder +// +// Created by Jacky Jack on 31/05/2024. +// + +import Foundation + +class QueryDF: CustomStringConvertible { + + //max I see is 24 + var DFlist:[Int] = Array(repeating: 0, count: 30) + + init() { + + } + + func addDF(_ dataformat: UInt32) { + DFlist[Int(dataformat)] += 1 + } + + func showStat() { + print("DataFormat Count") + for i in 0...(DFlist.count)-1 { + if DFlist[i] != 0 { + print(String(format:" %02d: %05d", i, DFlist[i])) + } + } + } + + var description: String { + var description = "DataFormat Count\n" + for i in 0...(DFlist.count)-1 { + if DFlist[i] != 0 { + description += String(format:" %02d: %04d\n", i, DFlist[i]) + } + } + return description + } +} + +class QueryDF17TC: CustomStringConvertible { + var TClist:[Int] = Array(repeating: 0, count: 32) + + init() { + + } + + func addTC(_ typecode: Int) { + TClist[typecode] += 1 + } + + var description: String { + var description = "DF17 TypeCode Count\n" + for i in 0...(TClist.count-1) { + if TClist[i] != 0 { + description += String(format: " %02d: %04d\n", i, TClist[i]) + } + } + return description + } +} + +class QueryDecodedMessages: CustomStringConvertible { + + var decoded:Int = 0 + var total:Int = 0 + + init() { + + } + + func addDecoded() { + decoded += 1 + total += 1 + } + + func addUndecoded() { + total = total + 1 + } + + 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" + return description + } + +} + + +class QueryDF17TC_decoded: CustomStringConvertible { + var TClist_decoded:[Int] = Array(repeating: 0, count: 32) + var TClist_total:[Int] = Array(repeating: 0, count: 32) + + init() { + + } + + func addDecoded(_ typecode: Int) { + TClist_decoded[typecode] += 1 + TClist_total[typecode] += 1 + } + + func addUndecode(_ typecode: Int) { + TClist_total[typecode] += 1 + } + + var description: String { + var description = "" + var decoded:Int = 0 + var total:Int = 0 + for i in 0...(TClist_decoded.count-1) { + total += TClist_total[i] + decoded += TClist_decoded[i] + if TClist_total[i] != 0 { + description += String(format: " %02d: %04d\n", i, TClist_decoded[i]) + } + } + description += String(format:"Total %d/%d %.1f",decoded,total,Double(Double(decoded)/Double(total))*100) + description += "%\n" + return description + } +} + diff --git a/ADSBDecoderFrameworkTests/ADSBDecoderFrameworkTests.swift b/ADSBDecoderFrameworkTests/ADSBDecoderFrameworkTests.swift new file mode 100644 index 0000000..1e0c27b --- /dev/null +++ b/ADSBDecoderFrameworkTests/ADSBDecoderFrameworkTests.swift @@ -0,0 +1,21 @@ +// +// ADSBDecoderFrameworkTests.swift +// ADSBDecoderFrameworkTests +// +// Created by Jacky Jack on 24/09/2026. +// + +import Testing +@testable import ADSBDecoderFramework + +struct ADSBDecoderFrameworkTests { + + @Test("Decoder dataformat 17") 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 + let decoder = Decoder("8d3c664c580d014ae16024650e6c") + #expect(decoder.DataFormat == 17) + } + +} diff --git a/LearnMapKit/ADSBNetRunner.swift b/LearnMapKit/ADSBNetRunner.swift index 21b8fd8..8634a72 100644 --- a/LearnMapKit/ADSBNetRunner.swift +++ b/LearnMapKit/ADSBNetRunner.swift @@ -32,14 +32,14 @@ class ADSBNetRunner { ) { _ in //print("Timer drain queue") //print("\(adsb_net_decoder.msgarray.message_array.count)") - if adsb_net_decoder.msgarray.message_array.count > 0 { + //if adsb_net_decoder.msgarray.message_array.count > 0 { + //print(adsb_net_decoder.msgarray.message_array.count) - for _ in 0.. Bool { + let fm = FileManager.default + if fm.fileExists(atPath: fname) { + return true + } + return false +} + +//get current run directory +func getCurrentDirPath() -> String { + return Process().currentDirectoryPath +} + -- cgit v1.2.3