MAVA Logger X Developers' Documentation

Introduction

This (partially generated) documentation describes the MAVA Logger X from a developer's perspective. Its purpose is to give enough information, so that a developer could understand how the software works in general, and easily understand the code to be able to make modifications to it.

Note, that to be able to understand the code most effectively, it is important to either use the application actively, or to read its user documentation carefully.

Overview

The application was written in Python 2. The Python wrapper Gtk+ toolkit was used for the graphical user interface. The program is designed to run on both Windows and Linux, though as of this writing only the Windows version can be used practically. However, Linux distributions move towards Gtk+ 3 as the primary toolkit, while it has no reliable port for Windows yet. Therefore it was decided to support both Gtk+ 2 and 3 depending on the platform. For Gtk+ 2 the PyGTK wrapper is used, while for Gtk+ 3 the PyGObject bindings. See the mlx.gui.common module for information on how the differences between these toolkits are handled.

At present only Microsoft Flight Simulator 2004 and X (also, perhaps, Prepar3D) are supported, and are accessed via the FSUIPC interface. The author has created a Python mapping for it, which has been submitted for inclusion into the SDK, so it will hopefully appear in its next version. It is planned to support X-Plane in the near future (hopefully by the end of 2012) on both Linux and Windows.

Development environment

The software is primarily being developed on Linux, but is possible to perform development on Windows as well. You need to have Python 2.7.x installed as well as one of the above mentioned wrappers for Gtk+ and Gtk+ itself. Since Python is an interpreted language, there is no need for any special build system.

Python and Gtk+ are readily available on most Linux distributions, but some links are probably useful for Windows users:

The install package can be created by running the makeinst.bat file. It contains some absolute paths, so check those befure running the batch file. Windows is needed currently to create an install package.

On Linux you can use the makesdist.sh script to create the archive that you can extract on Windows. This archive goes in to the dist subdirectory, and contains everything needed (from the logger) to create the package.

Architecture

The two major parts of the application are the GUI and the rest of it (let's call it the "business logic"). The main interface for the GUI is the mlx.gui.gui.GUI class, which is referenced from the business logic only from the mlx.flight.Flight class. The rest of the business logic uses the actual instance of this class to access values entered into the GUI by the user.

The program uses a few threads. The main thread is reserved for the GUI, which has two implications:

  1. No GUI operations should be executed directly from another thread. Instead, use gobject.idle_add to "inject" the operation into the main thread.
  2. To ensure the responsiveness of the GUI, only operations that take a short time should be executed in the GUI thread.

Business Logic

The business logic part deals with the connection towards the simulator. The mlx.fsuipc module implements this connection using the FSUIPC interface. Its Simulator class creates a Handler object, which starts its own thread, in which the FSUIPC requests are called. In case of reading data from FSUIPC, the data is passed to a callback function, which is called in this thread. This should be considered when the retrieved data is processed on the GUI in same way (e.g. displayed). The main interface towards the simulator is the Simulator class, so if another simulator is to be supported, a class with the same (or at least sufficiently similar) public interface should be implemented.

The most important function of the program is the continuous monitoring of the aircraft's parameters and some other data. The monitoring is started using the startMonitoring function of the simulator object. If started, it calls the handleState function of the mlx.acft.Aircraft instance used. The mlx.acft module contains one child class of Aircraft for each aircraft type in the MAVA fleet. These subclasses contain the type-specific behaviour, but the main handling logic is in the Aircraft class.

Upon calling its handleState function, it calculates the smoothed values of IAS and VS, and then calls each "checker". A checker is an instance of a subclass of mlx.checks.StateChecker, which checks a one or a few parameters that are important from some aspect of the correct execution of a flight. For example, a checker may check if the strobe lights are switched on and off at the right stages of the flight. But some checkers simply log some value whenever it changes in an "interesting" way, or send theACARS" periodically.

There is also a checker which detects the changes in the stage of the flight, and calls the setStage function of the aircraft, if there is a change. It first calls the flight's setStage function, which notifies the GUI and the logger of this change, and records the block and flight times. Then the aircraft's setStage function logs some values in case of certain stages, such as the takeoff weights and speeds when the takeoff stage is entered. After calling the checkers, the handleState function of the aircraft calls the function with the same name of the flight. It again records some statistical data, such as the flown distance and the amount of fuel used, and calls the sound scheduler to check if some backround sound should be played. If the check list hotkey is pressed, the checklist scheduler is notified too.

As mentioned, there is a logger in the application, which contains the textual log lines as well as the faults and their scores.

The business logic part contains many other components, but they are quite simple and are built around the principles mentioned above. Consult the documentation and the code of the relevant modules for more information.

GUI

As mentioned, the GUI is implemented using Gtk+. This toolkit provides the Glade graphical user interface designer, but due to the requirement of supporting both Gtk+ 2 and 3, and due to a so-so experience with Glade in an earlier project, it was decided to not use it. Instead, the GUI elements are created and handled by hand-written code.

The central class of the graphical user interface is mlx.gui.gui.GUI. Upon creation, it creates the rest of the GUI, sets up the menus and shortcuts, etc. It also maintains the connection to the simulator and creates the flight and aircraft objects as needed.

To understand the operation of the GUI, one should be familiar with Gtk+, but otherwise it is pretty straighforward. See the documentation of the relevant modules for more information.

Adding a new aircraft type

While new aircraft types will probably not be added too often, here is a checklist about what should be modified when such a requirement arises.

First, it is worth to know what data you need to add the new type:

  • the aircraft's type name and its ICAO code
  • the following weights: DOW, MZFW, MTOW, MLW
  • the flap settings and their speed limits
  • the speed limit for extending/retracting the gear (VLE)
  • the number and types of the fuel tanks
  • the type code the MAVA website uses to identify the type
  • if the plane has reversers, what is the operating limit speed, if any
  • does the plane support the notion of a takeoff derate, and if so, what data should be given
  • what lights does the plane have

If you have the data, you can add the type by modifying the source files as per the checklist below:

  1. src/mlx/const.py: look for the constants named AIRCRAFT_xxx. Add the new type at the end of the list of those constants, with a number 1 greater than the number of the last existing type. The part of the constant's name after the underscore (xxx above) should be the ICAO code of the aircraft type.
  2. src/mlx/const.py: below this list of constants, you can find an array named aircraftTypes. Add the type constant to it.
  3. src/mlx/const.py: further below you can find a dictionary mapping te aircraft type to the corresponding ICAO codes. Add the new type to it.
  4. src/mlx/acft.py: add a new subclass of mlx.acft.Aircraft. Its name should be the ICAO code. Check an existing aircraft and add the same variables containing the weights, the flap speed limits and the gear speed limit. There may be some other member variables or functions that should be
  5. src/mlx/acft.py: there is a dictionary named _classes towards the end of the file. Add the type to it.
  6. src/mlx/web.py: the mlx.web.BookedFlight class contains two dictionaries, the mapping between the types and the values the MAVA website uses to identify the type. Add the appropriate values here.
  7. src/mlx/fsuipc.py: add a subclass of mlx.fsuipc.GenericAircraftModel for the new type named the ICAO code of the type followed by the word Model. Implement its constructor to supply the base class with the flaps notches (starting with 0), the array of constants describing the fuel tanks the model has, and the number of engines. Also implement the name of the model, which should be something like "FSUIPC/Generic ...". If necessary implement other functions or set other members.
  8. src/mlx/fsuipc.py: add the new type and model class to the dictionary named _genericModels towards the end of the file.
  9. src/mlx/fsuipc.py: if you have a model that has some non-generic characteristics, create a specific class for it. This class should be a subclass of the generic class created, and it should be registered at the bottom of the file, as the other models are.
  10. src/mlx/gui/common.py: this file contains a dictionary called mlx.gui.common.aircraftNames. Add the new type it it. It contains the mapping from the type constants to their language-specific names. The string ID is "aircraft_" followed by the lower-cased ICAO code.
  11. locale/hu/mlx.po, locale/en/mlx.po: the beginning of this file contains mapping from the string ID previously used to the actual name of the aircraft. Add the new type as appropriate.
  12. dcdatagen.py: this program generates some source and message files related to the delay codes. Currently there are two tables, one for old-timer types and the other for the "modern" types. The file contains a list of lists called typeGroups. Add the type's ICAO code the appropriate list.

When all the changes have been made, run make in the root directory to update some source files.