SwiftNASR

3.0.1

Parser for FAA aeronautical data (NASR)
RISCfuture/SwiftNASR

What's New

3.0.1

2022-09-16T17:31:46Z
  • Apparently the README files in FAA distributions have a new name; now supports the new FAA naming format.

SwiftNASR: FAA aeronautical data library for Swift

SwiftNASR is a Swift library that downloads and parses National Airspace System Resource (NASR) distributions from the FAA's Facility Aerodrome Data Distribution System (FADDS). These distributions contain comprehensive aeronautical data for the United States, covering the airports, navaids, airspace, routes, ATC facilities, and more, that make up the National Airspace System.

SwiftNASR can download NASR distributions directly from the FAA website, or load prior-downloaded distributions from disk or memory. It parses this data into classes and structs that are easy to use and take advantage of common Swift paradigms. These classes are all Codable and can be exported to file, and imported using the Coder of your choice.

The design goal of SwiftNASR is domain-restricted data as much as possible. Wherever possible, SwiftNASR avoids representing data as open-ended types such as strings. Instead, enums and other types with small domains are preferred. This obviously has maintainability implications -- namely, as the upstream data changes, SwiftNASR is more likely to generate parsing errors, and require more developer work to maintain future compatibility -- but it also results in a library that's more in harmony with the design goals of the Swift language itself (type safety, compile-time checks, etc.).

What records can I parse with this?

SwiftNASR is a work in progress. Here's what's currently ready:

  • Airports
  • ARTCCs
  • FSSes
  • ARTCC boundary segments
  • Airways
  • AWOSes
  • Coded departure routes
  • FSS comm facilities
    • The FSS data includes comm facilities, but there is also a separate file for FSS comm facilities; haven't checked yet if they contain the same data
  • High altitude route fixes
  • Published holds
  • ILSes
  • Location identifiers
  • Miscellaneous activity areas
  • Military training routes
  • Enroute fixes
  • Navaids
  • Preferred routes
  • Parachute jump activity areas
  • DPs and STARs
  • ATCTs and TRACONs
  • Weather reporting locations

Installation

SwiftNASR is a Swift Package Manager project. To use SwiftNASR, simply add this project to your Package.swift file. Example:

// [...]
dependencies: [
    .package(url: "https://github.com/RISCfuture/SwiftNASR.git", .branch("master")),
]
// [...]

Usage

The NASR class is used to load NASR distributions. If you have not already downloaded a NASR distribution, you can do so using the fromInternetToFile method, which will download the distribution to a file, so you can avoid having to re-download it later:

import SwiftNASR

let workingURL = URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
let distributionURL = workingURL.appendingPathComponent("distribution.zip")
let distribution = NASR.fromInternetToFile(distributionURL)!

If you have already downloaded the distribution, you can load it using fromLocalArchive:

let distribution = NASR.fromLocalArchive(distributionURL)

Once you have your distribution, use the NASR class to asynchronously load the data and parse it:

distribution.load { result in
    switch result {
        case .success:
            try! distribution.parse(.airports, errorHandler: { error in
                // [...]
            })

        case .failure(let error):
            // [...]
    }
}

Note that larger datasets, such as airports, can take several moments to parse. It's recommended to serialize this data once parsed using an encoder (see below).

Once you've completed parsing the data you're interested in, you can access it from NASR.data:

let sanCarlos = distribution.data.airports!.first { $0.LID == "SQL" }!
print(sanCarlos.runways[0].length)

data is an object of type NASRData. Its fields, such as airports will only not be nil once parse has been called for that data type (as in the example above).

To avoid parsing a large dataset each time your application loads, I recommend encoding the NASRData object. Choose the encoder you wish to use; for example, JSONEncoder uses a straightforward and portable format. This class also provides JSONZipEncoder to cut down on space when needed.

You can encode the whole object, containing all the data you've loaded:

let encoder = JSONZipEncoder()
let data = try encoder.encode(distribution.data)
try data.write(to: workingURL.appendingPathComponent("distribution.json.zip"))

or you can encode just the data you need; for example, filtering in only the airports that you care about, to improve space and time efficiency when loading and working with the data:

let validAirports = distribution.data.airports!.filter { airport in
    return airport.publicUse &&
        airport.runways.filter { $0.isPaved && $0.length > 3000 }.count > 0
}
let data = try encoder.encode(validAirports)

For more information on the data you have available to work with, see the class documentation for each of the record classes, such as Airport.

Use as a Publisher

SwiftNASR can also be used as a Publisher for reactive apps written using Combine. The load method has a variation that returns a publisher that emits when loading is complete:

let distribution = NASR.fromLocalArchive(distributionURL)
let cancelable = distribution.load().sink { distribution in
    // [...]
}

There are also variations of the parse method for each parseable type that return Publishers that emit when parsing is complete:

``` swift
let distribution = NASR.fromLocalArchive(distributionURL)
let cancelable = distribution.load().map { $0.parseAirports() }
    .switchToLatest().sink { event in _
        switch event {
            case let .error(error): // parse error for one row only
                // [...] (decide if you want to keep parsing or cancel)
            case let .complete(airports):
                // [...]
        }
    }

}


### Customizing loader behavior

If you need to customize loader behavior (e.g., using your own
`URLSessionConfiguration`), instantiate a loader yourself and pass it to the `NASR`
initializer. The different `NASR` class constructors are simply syntactic sugar for different
loader implementations. See the documentation for each `Loader` implementation for
more information.

## Tests

Testing is done using Nimble and Quick. Simply run the `SwiftNASRTests` target to run
tests.

A `SwiftNASR_E2E` target is also available to do an end-to-end test. This will download a
distribution (or load one from file, if already downloaded) and load all data from the
distribution, then write it out to a `.json.zip` file. The whole process takes some time, but
if it completes successfully without error, that's a pretty good sign the code hasn't broken.

Description

  • Swift Tools 5.5.0
View More Packages from this Author

Dependencies

Last updated: Fri Mar 01 2024 09:36:20 GMT-1000 (Hawaii-Aleutian Standard Time)