Skip to main content

Querying Navdata

What Are Facilities?

Facilities are the heart of MSFS navigational data, and encompass all of the different types of navigational data that are available to query. The Javascript facility loading system can access 5 different types of facilities from the simulator: airports, intersections, VORs, NDBs, and airspace boundaries.

Airport Facilities

Airport facilities records hold a large amount of data about a given airport:

  • Metadata about the airport, such as the name, ICAO, location
  • COM radio frequencies available related to the airport
  • Runway definitions, including available runway ILS frequencies
  • Departure, arrival, and approach procedures including:
    • All procedure legs
    • Transitions and transition names
    • Approach details, such as type, associated runways, RNAV information

Intersection Facilities

Intersection facilities are one of the more basic facility types. They indicate some metadata regarding the intersection, such as ICAO, the type (low, high), what airway they might be on, and a location.

VOR Facilities

VOR facilities are similar to intersection facilities, except that they indicate some more relevant details about the VOR radio, such as the magnetic variance, tuning frequency, and class (high power, low power, etc). VOR facilities do not include airway information; for VORs that are part of an airway, there is a separate intersection facility record.

NDB Facilities

Similar to VOR facilities, these instead give the NDB/ADF tuning frequency.

Boundary Facilities

These facility records contain the name, ID, bounding box, type, and vector shape of a given airspace boundary.

MSFS Facility ICAO Format

Most navigational facilities in MSFS are uniquely identified using a 12 character formatted string, called an ICAO. The ICAO format is:

TypeRegionAirportIdent
AK5KORDGOOZY
info

The ICAO must always be 12 characters. Any omitted fields must be replaced by empty spaces.

Type

The first character of a MSFS ICAO represents the type of facility. The available types are:

  • A - Airport
  • W - Intersection
  • V - VOR
  • N - NDB

Region

The second two characters represent the MSFS region code, which correspond to the ICAO Airport Region Codes, with some large areas being subdivided. For example, the K area for the US is divided into regions K1 through K7 (generally from east to west incrementing), and the Y area for Australia is similarly divided (YB and YM).

Airport facilities are not required to have a region code, since each airport ident is unique throughout the world.

Airport

Some facilities also include this optional field, which is the owning airport. This is used to disambiguate facilities which might otherwise have the same 12 character ICAO, such as airport RNAV approach fixes that share an ident with an intersection.

Airports themselves do not include this field.

Ident

This is the name of the facility, which is almost always what a user or pilot is interacting with. Idents are not unique around the world, while the full 12 digit ICAO will be.

Loading Individual Facilities

This avionics framework includes a system by which you can query facility data, called FacilityLoader:

const eventBus = new EventBus();
const facilityLoader = new FacilityLoader(FacilityRepository.getRepository(eventBus));

const ord = await facilityLoader.getFacility(FacilityType.Airport, 'A KORD ');
console.log(`This airport is called ${ord.name}`);

Finding An ICAO

Sometimes, you may not have the full 12 character ICAO available (such as when a user is inputting a facility ident). In these cases, you can get a collection of ICAOs whose ident starts with the given string:

const matches = await facilityLoader.searchByIdent(FacilitySearchType.None, 'JOT');

Or if you would like to limit your search to a specific facility type and a maximum of a certain number of facilities:

const matches = await facilityLoader.searchByIdent(FacilitySearchType.NDB, 'AB', 10);

Searching Nearest Facilities

Sometimes, it is helpful to get a collection of facilities that are within a certain geographic distance. For this, the framework provides nearest facilities search sessions.

By starting a search session, you can get a list of the facilities that are within a specfied distance of a lat/lon point. Once started, this search session keeps track, within the sim, of the ICAOs of facilities that have been either added or removed since the last time you searched using the given session.

This means that for the first search performed in a given session, all facilities within range will return in the data as added facilities. If no parameters change (the search radius or the search point), then the next search will return no facilities added or removed: in other words, the facilities that were returned last time are still the valid set of facilities in the search area. If you change the search area parameters, such as by moving the search point or changing the radius, the data returned will include only the diff: everything added to the set of valid facilities in range, and everything removed from the set of valid facilities in range.

This type of search is especially useful for things like map facility icons or pages that show nearest facilities: since only the diffs since the last search are returned, that's all that needs to be processed and the map or list can add or remove the few items in the diff.

You can perform a nearest facility search by starting a new search session using the facility loader, and then searching using the returned session:

const session = await facilityLoader.startNearestSearchSession(FacilitySearchType.Airport);

const nearestAirports = new Map<string, AirportFacility>();
setInterval(async () => {
const lat = SimVar.GetSimVarValue('PLANE LATITUDE', 'degrees');
const lon = SimVar.GetSimVarValue('PLANE LONGITUDE', 'degrees');

const distanceMeters = UnitType.NMILE.convertTo(100, UnitType.METER);
const diff = await session.performNearestSearch(lat, lon, distanceMeters, 25);

for (let i = 0; i < diff.removed.length; i++) {
nearestAirports.remove(diff.removed[i]);
}

await Promise.all(diff.added.map(async (icao) => {
const airport = await facilityLoader.getFacility(FacilityType.Airport, icao);
nearestAirports.add(icao, airport);
}));
}, 1000);

This code starts a new session, then searches for all airports within 100NM of the current plane position every second, adding and removing from the collection of currently found airports as necessary.

caution

Each search session started during a flight uses memory within the sim to track your session state. This is only cleared after the end of the flight. It is highly recommended to limit the number of search sessions started per instrument and reuse sessions where possible.

Starting a new session for every individual search performed will cause an unnecessary memory load in the simulator and should be avoided.