Jump to content
The simFlight Network Forums

Recommended Posts

Posted

Introduction

Version 3.3.0 of the FSUIPCClientDLL has significant changes to the Airports Database module. This post explains why this was needed, the main differences and quick exmples of how to use this feature from V3.3.0 onwards.

More detailed examples can be found in the Example Code Applications (C# / VB.NET) available on the website:

http://fsuipc.paulhenty.com/#downloads

Full details of all changes in V3.3.0 can be found here:

http://fsuipc.paulhenty.com/#revisionHistory


Why change it?

The feature was first introduced around the time of FSX and early P3D versions. These products shared the same airports database and was small enough that everything could be comfortably stored in RAM (roughly 300mb). This included all airports, gates, helipads, runways and taxiways.

The information was read directly from the MakeRunways text files (.csv/.xml) when the application started and stored in RAM for the lifetime of the application.

With modern flight simulators and scenery (especially MSFS) this method of dealing with the Airports Database has become unworkable. 

The default scenery from a standard install of MSFS takes up over 3GB of RAM. That's a lot for an application to take up, especially one running on the Flight Sim machine. Processing this amount of information makes the application run slowly (e.g. setting the Reference Position on all airports). Also, the time taken to read and parse the MakeRunways text files is now quite slow. It's not good to have to wait for this process to complete every time your application starts.

The Airports Database has been partially redesigned and rewritten to work with the large amount of data from the latest Flight Simulators.

Instead of holding the data in memory, it is instead held in binary files on the hard disk in a way that it can be accessed very quickly.

The importing of the MakeRunways files only needs to be done when they have changed (or if it's the first time you or your users have used your application). After that the data is read from the binary files, so your application's start up can be much faster.

There is also more control over what gets loaded into RAM and what data gets processed. Whereas before, all airports, runways, gates etc were loaded into RAM and processed, the new Airports Database lets you control this so you only load and process the data your application needs.

For example, if you need to know which taxiway the player is on, you can now do so by only loading taxiways for that airport and only testing that airport.

The new ways of using the Airports Database require a little more thought and care than the old way, but the old way is just too inefficient to work on large datasets.


Things that haven't changed:

The database objects (FsAirport, FsRunway, FsGate etc) have not changed. Your current code that uses these objects will not need to be changed.


The differences:

Data Stored in Binary Files

The data is not read from the MakeRunways output files every time your application starts. The MakeRunways data is parsed and then stored in binary files in a way that the data can be quickly accessed. The data is read from these binary files. The MakeRunways data only needs to be imported (parsed) again if they change.


Control of loading of Components (Runways, Gates, Taxiways etc)

When you load the database initially, the only data that's loaded is the list of all airports. No component data (Runways, Gates, Taxiways etc) is loaded. If you want that information you can request that it's loaded. This can be done for a single airport or a collection of airports. 

This keeps the memory footprint down.


Collections of Airports

When you load the database you get a collection containing all airports. You're free to use that collection if your application requires it (e.g. flight planning). However, if you're application only needs to work with a subset of airports (e.g. airports in a 100nm range of the player, or a specific list of airports used by a Virtual Airline) you can create a new collection of airports that is more relevant to your application. You can do this manually or by filtering the main airports collection.

This means you are only processing airports and loading data that is relevant to your application. This improves memory usage and processing times.


Managing the Database as your Application Runs

Throughout the lifetime of your application, you may use combinations of the above techniques to keep the memory use and processing times to a minimum. 

Here's an example: You might use the full airports list to get the airports in 60nm of the player. Then you might load runways for those airports to find those with ILS facilities. Then after the user picks an airport you might load Gate information for that single airport so the player can choose a gate. Your application might then keep checking that FsGate object to known when the player has arrived there.


Integration with AITrafficServices

Integration with AITrafficServices is no longer automatic. If you want the integrated features you need to pass a collection of airports (or a single airport) and the components you wish to process to AITrafficServices.RefreshAITrafficInformation(). 

Note that this method automatically loads component information on demand as it's required. There's no way for you to know what needs to be loaded in advance.

 

(Re)Building the Database:

The database needs to be built before you can use the database and also whenever the MakeRunways output files change. This is typically when the user has updated their scenery.

The rebuild method runs in the background so it doesn't block the User Interface.

The easiest way to call this method is with the Async-Await pattern. This will wait until the rebuild in complete and then continue executing your code. E.g.

C#

private async void btnRebuild_Click(object sender, EventArgs e)
{
     AirportsDatabase db = FSUIPCConnection.AirportsDatabase;
     await db.RebuildDatabaseAsync();
     MessageBox.Show("Rebuild Complete");
}

VB.NET

Private Async Sub btnRebuild_Click(ByVal sender As Object, ByVal e As EventArgs)
     Dim db = FSUIPCConnection.AirportsDatabase
     Await db.RebuildDatabaseAsync()
     MessageBox.Show("Rebuild Complete")
End Sub

You can also pass a Progress object to RebuildDatabaseAsync to receive progress reports during the rebuild. See the Example Code application for this. 


Usage:

1. Get a reference to the Airports Database:

C#

AirportsDatabase db = FSUIPCConnection.AirportsDatabase;

VB.NET

Dim db = FSUIPCConnection.AirportsDatabase


2. Set the Make Runways Folder (Optional)

You can optionally set a path to the MakeRunways output files. If you are using the database with an open FSUIPC Connection this path will be set automatically to the flight simulator main folder. This is where the MakeRunways files are by default.

If you're using the database without an FSUIPC Connection, or want to point to a different folder than the default you can set the MakeRunwaysFolder property.

C#

db.MakeRunwaysFolder = @"C:\Path\To\MakeRunways\Output\Files";

VB.NET

db.MakeRunwaysFolder = "C:\Path\To\MakeRunways\Output\Files"


3. Load the Database:

Call Load() to load in the main collection of airports.

C#

if (db.DatabaseFilesExist)
{
    db.Load();
}

VB.NET

If db.DatabaseFilesExist Then
   db.Load()
End If

4. Get a specific airport using the ICAO indexer:

C#

FsAirport heathrow = db.Airports["EGLL"];

VB.NET

Dim heathrow = db.Airports("EGLL")


5a. Get a cut-down collection of airports by filtering the main collection 

C#

FsAirportCollection localAirports = db.Airports.InRangeOfKilometres(80);
FsAirportCollection londonAirports = db.Airports.FindAll(ap => ap.City == "London" && ap.Country == "United Kingdom");

VB.NET

Dim localAirports = db.Airports.InRangeOfKilometres(80)
Dim londonAirports = db.Airports.FindAll(Function(ap) Equals(ap.City, "London") AndAlso Equals(ap.Country, "United Kingdom"))


5b. Or make your own custom collection of airports:

C#

string[] virtualAirlineAirportCodes = new string[] { "EGLL", "LFPG", "EDDF", "EIDW", "EGPF", "EGJJ" };
FsAirportCollection virtualAirlineAiports = new FsAirportCollection();
foreach(string icao in virtualAirlineAirportCodes)
{
    virtualAirlineAiports.Add(db.Airports[icao]);
}

VB.NET

Dim virtualAirlineAirportCodes = New String() {"EGLL", "LFPG", "EDDF", "EIDW", "EGPF", "EGJJ"}
Dim virtualAirlineAiports As FsAirportCollection = New FsAirportCollection()
For Each icao In virtualAirlineAirportCodes
    virtualAirlineAiports.Add(db.Airports(icao))
Next

7. Load components for an individual airport or a collection 

C#

heathrow.LoadComponents(AirportComponents.Runways | AirportComponents.Gates);
virtualAirlineAiports.LoadComponents(AirportComponents.All);

VB.NET

heathrow.LoadComponents(AirportComponents.Runways Or AirportComponents.Gates)
virtualAirlineAiports.LoadComponents(AirportComponents.All)


8. Use the component information after loading:

C#

foreach(FsRunway rw in heathrow.Runways)
{
    this.cbxRunways.Items.Add(rw.ID + " (" + rw.LengthFeet.ToString("N0") + " ft)");
}

VB.NET

For Each rw In heathrow.Runways
    cbxRunways.Items.Add(rw.ID & " (" & rw.LengthFeet.ToString("N0") & " ft)")
Next

9. Set the Reference Location for an individual airport or a collection:

This will calculate the distance, bearing etc to the airport or each airport in the collection.

You can choose which loaded components are processed.

Setting reference location for all airports in the collection (No components processed - distance, bearings and boundary checks for airports only).

C#

localAirports.SetReferenceLocation(AirportComponents.None);

VB.NET

localAirports.SetReferenceLocation(AirportComponents.None)

Setting reference location for one airport. Also calculate distance, bearings, boundary checks for runways and gates:

C#

heathrow.SetReferenceLocation(AirportComponents.Runways | AirportComponents.Gates);

VB.NET

heathrow.SetReferenceLocation(AirportComponents.Runways Or AirportComponents.Gates)

10. Fill in the AITraffic Properties by passing a collection to the AITrafficServices.

This example will populate the airport, runway and gate information for AITraffic for all virtual airline airports. 

C#

AITrafficServices traffic = FSUIPCConnection.AITrafficServices;
traffic.RefreshAITrafficInformation(virtualAirlineAiports, AirportComponents.Runways | AirportComponents.Gates);

VB.NET

Dim traffic = FSUIPCConnection.AITrafficServices
traffic.RefreshAITrafficInformation(virtualAirlineAiports, AirportComponents.Runways Or AirportComponents.Gates)

Paul

 

  • Thanks 1
  • 5 weeks later...
Posted

Hi Paul,
I have several applications that use the Airport Database of your FSUIPC Client dll. For this I only want to rebuild the database at a central application and save the result on a network drive. All clients should then have access to this. Would this work or will there be access problems if multiple clients access the db at the same time?

Kind regards,

Ruediger

Posted

Hi Ruediger,

I'm almost certain there won't be any problem with this. Except for the Rebuild(), all the airports database functions open the files as read-only with shared access.

However, at the moment the path to the internal database files is fixed and can't be changed (you'll find the DatabaseFolder property is read-only).

You'll need this to be writable so you can set it to the folder on your network. I'll make this change and upload a new version in the next few days.

Paul

 

Posted

Version 3.3.4 is now on Nuget.

FSUIPCConnection.AirportsDatabase.DatabaseFolder is now read/write. Set this property if you want to use a specific path for the internal database files, If you don't set a path it will use the default folder (%localappadata%\FSUIPCClientDLL). 

Paul 

  • 2 weeks later...
Posted (edited)

Hi Paul,

I am still in the process of migrating my applications to the new version of FSUIPCClient.dll. So far it works fine, except that I always get 'Nothing' back when reading the airlines assigned to a gate.

In the g5.csv file these are contained. For example Gate 203, Payware LIME:

LIME,,203,45.666995,9.697427,23.0,194.4,9,,RYR

Basically my code is as follows:

Dim MyGates As FsGate

Dim db = FSUIPCConnection.AirportsDatabase
Dim airport = db.Airports(ICAOOrigin)
airport.LoadComponents(AirportComponents.Runways Or AirportComponents.Gates)

For Each MyGates In airport.Gates
     For Each item In MyGates.Airlines
       If item = ICAO_Airline Then
         GateList.Add(s)
       End if
    Next
Next

I'm probably doing something wrong, but I can't find the mistake.

Ruediger

 

Edited by Delphi

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use. Guidelines Privacy Policy We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.