Skip to content

Commit b1d1544

Browse files
committed
chore: add rfc1 back
1 parent 446fe88 commit b1d1544

File tree

1 file changed

+208
-0
lines changed

1 file changed

+208
-0
lines changed

docs/RFC001.md

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
# Developer-Oriented In-Sim Navigation Data API Specification
2+
3+
To be Reviewed By: Markus Hamburger, Malte Hallström, Jack Lavigne
4+
5+
Authors: Alex Cutforth
6+
7+
Status: Outdated
8+
9+
Date: Feb 1, 2024
10+
11+
## Problem
12+
13+
Accessing Navigraph's navigation data in Microsoft Flight Simulator has always been challenging due to the limitations of the JavaScript and Webassembly APIs. However, with the recent addition of the Communications API, allowing different WASM modules and Coherent pages to interact with each other, this has become possible.
14+
15+
Navigraph has decided to use an architecture consisting of a wasm module whose job it is to download navigation data databases from the internet, and to query them. This means an API must be designed and implemented to best cater to the needs of aircraft developers.
16+
17+
This RFC will outline the following:
18+
19+
- Naming, typing, and other standards to use throughout the API
20+
- Example data structures for the returned data which are comprehensive and ergonomic to use
21+
- Example functions the API will implement to provide the necessary data.
22+
23+
## Anti-Goals
24+
25+
This interface will not be designed for use in parallel with in sim data, it is meant to provide the best experience possible with Navigraph's navigation data capabilities. This interface will only be providing data from Navigraph's databases.
26+
27+
This interface is also not designed for use outside of Microsoft Flight Simulator and is not designed (as of now) with anything other than the Flight Management System in mind.
28+
29+
# Solution
30+
31+
## Standards
32+
33+
---
34+
35+
- All functions and fields and variables involved in this interface should use `snake_case`, and all names of objects and types should use `PascalCase`. This is the code style which rust uses, and it should be used JS side as well for consistency and so objects dont need to be re assigned.
36+
- Data fields which act as an identifier should always use the shorthand term: `ident` and should not name the type they are part of.
37+
- Example: Runways may contain the fields:
38+
- `ident: "RW23L"`
39+
- `airport_ident: "NZAA"`
40+
- Example: Airports may contain the field:
41+
- `ident: "NZAA"`
42+
- Using the term `icao` to refer to an identifier is an anti-pattern as it may be confused with the `icao_code` which contains a two-letter code such as `ES` which represents the area of the world where this piece of data lies.
43+
- Example: Airports may contain the fields:
44+
- `icao_code: "NZ"`
45+
- `ident: "NZAA"`
46+
- Fields should represent the unit that the data will be using as a type alias, not by a suffix or prefix to the name of the field.
47+
- Do: `runway_length: Feet`
48+
- Don't: `runway_length_ft: number`
49+
- Radio navigation aid data type names should consist of the acronym of the type, followed by the suffix `Navaid`
50+
- Examples: `VhfNavaid`, `IlsNavaid`, `NdbNavaid`,
51+
- Acronyms should **_not_** be all capitalised
52+
- Do: `Vhf`
53+
- Dont: `NDB`
54+
- Latitudes should be encoded to as `lat` and Longitudes should be encoded to as `long`, and should wherever they are used in conjunction with each other, be part of a `Coordinates` data structure
55+
56+
---
57+
58+
- Items which are linked to other data should **_not_** have the linked data queried automatically and added to the returned data.
59+
- This is because increasing the size of data this much will result in slower queries due to the performance issues with Coherent's JSON parser.
60+
- While it is useful to have linked data such as Navaid information on airway or procedures, this would not be viable when using the API in a language other than JS or Rust
61+
- For items such as Procedures and Airways, which are represented in the database as a large number of rows with the same `ident` and possibly `icao_code`. They should be grouped into an object, containing list(s) which stores the individual elements. Fields which are known to be the same throughout the grouping should be on the group object, not the individual elements.
62+
- If the individual elements are split into sections such as transitions in a procedure, these should be encoded as subgroups.
63+
64+
---
65+
66+
- Data should be provided in the same units that the Database provides for consistency with aviation standards
67+
- Enums should be used where possible and should have values which match the database encoding.
68+
- Except for when an enum is to be used as a filter, where its values should support bitwise flags.
69+
- The data provided by this API should be able to be encoded purely in JSON, meaning:
70+
71+
- No functions
72+
- No classes
73+
- This is to support JSON serialization as a form of copying or sending between instruments
74+
75+
- Data fields should never be empty strings, they should be undefined
76+
- Data fields which are linked to each other will either both be undefined or both be defined
77+
- Data being encoded as possibly undefined should be based on database sweeps to find whether there are any null fields, not the database schema.
78+
79+
- Datastructures which are expected to have certain fields be defined based on the value of another field should have the type-system enforce this where possible, for example:
80+
81+
- Procedure legs will have their fields filtered based upon the `path_termination` field. Specs for this can be found [here](https://developers.navigraph.com/docs/navigation-data/dfd-data-format#procedure-leg-data-fields-minimum-requirements) or in `ARINC SPECIFICATION 424 Attachment 5 Data fields table 3`
82+
- Altitude constraints
83+
84+
- Values which are not defined should be undefined as opposed to null. This means in the rust implementation, all structs used for serialization which have Option fields should have `#[serde_with::skip_serializing_none]` as an attribute about the struct
85+
86+
---
87+
88+
- Functions which fetch items by the identifier should be named as `get_{type}s`
89+
- Functions which fetch a list of items by a grouping should be named `get_{type}_at_{group}` and should take in the identifier of the item used as the grouping
90+
- Functions which fetch a list of items by location and range should use the naming: `get_{type}s_in_range`, and should take in:
91+
- The center coordinates of the query
92+
- The range in nautical miles to search around the center
93+
- Any filters necessary for the type being fetched
94+
95+
---
96+
97+
- In the rust implementation, Mapping one row to one output struct should use a From<> implementation, but any other mapping should be done with a descriptively named function
98+
99+
---
100+
101+
## Example Datastructures
102+
103+
These datastructures are for use in JS/TS, however, they should be encoded as close to this as they can be on the WASM side, so minimal computation needs to happen in Coherent.
104+
105+
```ts
106+
export interface Coordinates {
107+
lat: Degrees
108+
long: Degrees
109+
}
110+
```
111+
112+
For data which links to a Fix such as Departures, Arrivals, Airways etc should use the Fix interface as the type for those fields. The data in Fix should be obtainable purely from id fields and location field.
113+
114+
The Fix data will be enough information for computing and rendering procedures and airways on most aircraft. After reading the fixType field, full data for the Fix can be fetched using the respective queries.
115+
116+
```ts
117+
export enum FixType {
118+
Airport,
119+
NdbNavaid,
120+
RunwayThreshold,
121+
GlsNavaid,
122+
IlsNavaid,
123+
VhfNavaid,
124+
Waypoint,
125+
}
126+
127+
interface Fix {
128+
fix_type: FixType
129+
ident: string
130+
icao_code: string
131+
location: Coordinates
132+
airport_ident?: string
133+
}
134+
```
135+
136+
```ts
137+
interface Transition {
138+
ident: string
139+
legs: ProcedureLeg[]
140+
}
141+
142+
interface Departure {
143+
ident: string
144+
runway_transitions: Transition[]
145+
common_legs: ProcedureLeg[]
146+
enroute_transitions: Transition[]
147+
engine_out_legs: ProcedureLeg[]
148+
}
149+
```
150+
151+
```ts
152+
export interface Airport {
153+
area_code: string
154+
ident_3_letter?: string
155+
name: string
156+
ifr_capability: IfrCapability
157+
elevation: Feet
158+
transition_altitude?: Feet
159+
transition_level?: Feet
160+
speed_limit?: Knots
161+
speed_limit_altitude?: Feet
162+
iata_ident?: string
163+
}
164+
```
165+
166+
```ts
167+
export interface Airway {
168+
ident: string
169+
fixes: Fix[]
170+
route_type: RouteType
171+
level: AirwayLevel
172+
direction?: AirwayDirection
173+
}
174+
```
175+
176+
## Full description of functions to be implemented
177+
178+
```ts
179+
get_database_info(ident: string): Promise<Airport>
180+
181+
get_airport(ident: string): Promise<Airport>
182+
get_waypoints(ident: string): Promise<Waypoint[]>
183+
get_vhf_navaids(ident: string): Promise<VhfNavaid[]>
184+
get_ndb_navaids(ident: string): Promise<NdbNavaid[]>
185+
get_airways(ident: string): Promise<Airway[]>
186+
187+
get_airways_at_fix(fix_ident: string, fix_icao_code: string): Promise<Airway[]>
188+
get_holds_at_fix(fix_ident: string, fix_icao_code: string): Promise<Hold[]>
189+
190+
get_waypoints_in_range(center: Coordinates, range: NauticalMiles): Promise<Waypoint[]>
191+
get_vhf_navaids_in_range(center: Coordinates, range: NauticalMiles): Promise<VhfNavaid[]>
192+
get_ndb_navaids_in_range(center: Coordinates, range: NauticalMiles): Promise<NdbNavaid[]>
193+
get_airways_in_range(center: Coordinates, range: NauticalMiles): Promise<Airway[]>
194+
get_controlled_airspaces_in_range(center: Coordinates, range: NauticalMiles): Promise<ControlledAirspace[]>
195+
get_restrictive_airspaces_in_range(center: Coordinates, range: NauticalMiles): Promise<RestrictiveAirspace[]>
196+
get_communications_in_range(center: Coordinates, range: NauticalMiles): Promise<Communication[]>
197+
198+
get_runways_at_airport(airport_ident: string): Promise<Runway[]>
199+
get_departures_at_airport(airport_ident: string): Promise<Departure[]>
200+
get_arrivals_at_airport(airport_ident: string): Promise<Arrival[]>
201+
get_approaches_at_airport(airport_ident: string): Promise<Approach[]>
202+
get_ndb_navaids_at_airport(airport_ident: string): Promise<NdbNavaid[]>
203+
get_ils_navaids_at_airport(airport_ident: string): Promise<IlsNavaid[]>
204+
get_gls_navaids_at_airport(airport_ident: string): Promise<GlsNavaid[]>
205+
get_path_points_at_airport(airport_ident: string): Promise<GlsNavaid[]>
206+
get_communications_at_airport(airport_ident: string): Promise<Communication[]>
207+
get_gates_at_airport(airport_ident: string): Promise<Gate[]>
208+
```

0 commit comments

Comments
 (0)