diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/404.html b/404.html new file mode 100644 index 00000000..e54381fe --- /dev/null +++ b/404.html @@ -0,0 +1,951 @@ + + + +
+ + + + + + + + + + + + + + +A button is the general term for a key, knob, rotary encoder, slider cursor, or even touch surface on a deck. On a given deck, each element that can be pressed, turned, or slid is a button.
+The Button Definition is a list of parameters that describe what the button will do when it is manipulated and how it will be represented on the deck if the deck can some how represent the state of that button. Here is an example of button definition:
buttons:
+ - index: 2
+ name: MASTER WARNING
+ type: push
+ command: sim/annunciator/clear_master_warning
+ annunciator-animate:
+ text: "MASTER\nWARN"
+ text-color: firebrick
+ text-font: DIN Condensed Black.otf
+ text-size: 72
+ dataref: AirbusFBW/MasterWarn
+ animation-speed: 2.0
+
The following section describe common button definition attributes.
+The button Activation page describes attributes specific to what a button will trigger or do when used.
+The button Representation page describes attributes specific to the rendering of the button on the deck.
Each «Button» on a deck is designated by its Index.
+On a given Page, the Index of a button must be unique on that Page since it addresses a very precise key, knob or slider on the deck.
+Depending on the model of deck, buttons have coded named index.
+On a simple deck with a number of similar keys, the index of a button is its ordering number: 0, 1, 2... until the number of keys is reached. On a more complex deck, with button and knobs, knobs may be indexed with name like knob0, knob1, knob2... until the number of knobs is reached.
+The Index of a button is a mandatory parameter of the Button definition. There is no default value.
Optional. A button can be named.
+The name of a button on a page must be unique. If more than one button have the same name, an error is reported and the definition of the button is ignored.
+If no name is provided, a unique, long, technical name is created from deck name, page name, and index.
Mandatory. The type of a button defines what the button will do and how it will be used.
+The button activation describe button-type specific attributes. In other words, depending on the value of the type attribute, other button defining attributes will be expected.
+The label of a button is a short reminder of what the button does. The text of the label is laid over the button image if any. The labelling of a button uses the following attributes:
+ label: SHORT TITLE
+ label-color: white
+ label-size: 24
+ label-font: Seven Segment.ttf
+ label-position: ct
+
Note: The Button Label should not be confused with Button Text. The Label exist for all buttons, and is displayed according to its attributes if the underlying button is capable. The text of the label is defined as a button attribute and is static (cannot be changed dynamically).
+The Button Text is a text that is part of the Button representation.
See Colors.
+See Fonts.
+In pixels. Internally, Cockpitdecks uses 256 × 256 pixel images.
+The position of the label is a 2 letter code:
+1. l, c, or r for left, center, or right-justified on the image (horizontal alignment),
+2. t, m, or b, for top, middle, or bottom of the image (vertical alignment).
Regularly, buttons have additional paparemeteres.
+The button options parameter is a string of comma separated options. An option is either a simple string or word, or a name=value string.
+options: 3dot,appearance=metal,mode=open,level=6
Options are, by nature, not indispensable to the button’s activation or rendering but rather add to it to alter behaviour or appearance.
+A Button has a value that is maintained and used mainly for representation.
+Please head here for details about a button's value computation.
A Button can force its first, initial value to set its startup or original state.
+ initial-value: 2
+
This value is assigned as the button's current value on startup.
+In case of a Button with multiple values, each value has a independant initial-value
attribute in its own attribute section.
Each button maintain its internal state: How many times it is pressed, released, turned clockwise or counter-clockwise, what is it current value, its previous, or last value. State information can be used by Button designer to control the button behavior and its representation.
+(Please refer to button activations, each activation type returns its own set of state values.)
+The type
attribute of a button determine how the button will behave, what it will do when pressed, turned or slid.
The representation of a Button determine what and how the button will display on the deck device. This depends on the capabilities of the button on the deck: LED, image, coloured led button, sound...
+The representation of a button is determined by the presence of a special attribute in the definition of the button.
+For example, if a button definition contains an attribute named annunciator
, the button representation will be an Annunciator. A button can only define one representation in its definition. Otherwise, a warning is reported and the button is ignored.
When a button is created, internal meta data are set first. Second, the Activation is installed and initialised. Third, the Representation is installed and initialized, as it may already use some activation information for rendering. Finally, the button is initialised. It will be rendered when the page that contains it is activated on a deck.
+Each button has a validity function that ensures that all necessary attributes are provided in its definition. If the activation of the button is not valid, its activation function will never be triggered, because of missing or misconfigurated parameters. If its representation is not valid, it will not be rendered on the deck.
+If a button is not valid, a small red triangle appears in the lower right corner of the key icon if the button is capable of representing it. A small blue triangle appears in the lower right corner of the key icon if Cockpitdecks suspect the button is a placeholder.
Each button has an describe()
method that prints in plain English what the button does and what it renders on the deck.
Each button has an inspect(what: str)
method that exposes internal values and state. The inspect method takes one parameter what
that determines what is displayed when invoked.
These methods can be invoked from the Inspect button activation.
+ + + + + + + + + + + + + +The Cockpit is the container entity of Cockpitdecks. For a given aircraft, it locates deck definitions, loads them and prepares each deck for use with X-Plane.
+Decks are particular to an aircraft. Cockpitdeck will look for a folder named deckconfig
in the X-Plane folder of that aircraft.
Cockpidecks will first look for a file named config.yaml
in the deckconfig
folder. In that file, Cockpitdecks will find all decks connected to the system and available to it. It will also find a few global parameters.
Cockpidecks will also look for a file named secret.yaml
in the deckconfig
folder. In that file, Cockpitdeck will find information such as the serial numbers of the deck devices used. Serial numbers are needed to distinguish all decks of a similar type.
Configuration files for decks are all Yaml-formatted files.
+XPlaneAircraftFolder
+ (...)
+ ⊢ deckconfig
+ ⊢ config.yaml
+ ⊢ secret.yaml
+ ⊢ resources
+ ⊢ icons
+ ⊢ icon-off.png
+ ⊢ icon-on.jpg
+ ⊢ fonts
+ ⊢ B612-Regular.otf
+ ⊢ DIN.ttf
+ ⊢ docs
+ ⊢ README.md
+ ⊢ layout1
+ ⊢ config.yaml
+ ⊢ page1.yaml
+ ⊢ page2.yaml
+ ...
+ ...
+ ⊢ layoutN
+ ⊢ page1.yaml
+ ⊢ page2.yaml
+ ...
+
The deckconfig
folder contains the following files and sub-folders:
Resources are fonts, icons, other images, wallpapers, documentation, and texts used and related to that aircraft.
+Folder containing all icon images for that aircraft. Images should be in JPEG or PNG format. Typical icon size is 256 × 256 pixels, RGB(A). Icons are named after their file name without the extension.
+Folder containing specific fonts used for that aircraft.
+Typical fonts include standard, formal font like DIN, icon fonts like FontAwesome or WeatherIcon font, or fancier font like 7-bar LED fonts. Fonts are named by their file name without extension for TrueType fonts. Open Type Fonts need to supply their extension .otf
.
Docs folder may contain documentation files, like explanatory images, and descriptive texts. Simpler text or markdown files are preferred.
+Newt to the the above resources folder, there will be one folder per Layout for a deck.
+Layout folders are explained separately.
The file named config.yaml
in the deckconfig
folder contains declarations for each deck that will be used and global, aircraft-level attributes.
# Definition of decks for Toliss A321
+#
+aicraft: Toliss A321
+decks:
+ - name: XPLive
+ type: loupedeck
+ layout: live
+ brightness: 70
+# These attributes are default values at global level
+default-wallpaper-logo: Airbus-logo.png
+default-icon-color: (94, 111, 130)
+default-label-color: white
+default-label-font: DIN.ttf
+default-label-size: 14
+cockpit-color: lightblue
+
The parameters apply to all decks for the given aircraft.
+Optional information. The name of the aircraft for this set of deck.
+Color for the cockpit. This color is used as the default background color for icons.
+Name of a image file (JPEG or PNG) that will be used as the (default) background of icons.
+The cockpit-texture
file will be searched at different places depending on where it is specified.
+The cockpit-texture
file can be specified at the Cockpit, Deck, Page, or Button level.
+Cockpit-level default textures will be seached in the following folders (in that order):
+- resources
+- resources/icons
+If the AIRCRAFT is specified, Cockpit-level textures and all other levels textures will be searched in the following folders:
+- AIRCRAFT/resource
+- AIRCRAFT/icons
+If a texture is not found at a lower level, the texture of the level above is used.
+If no texture is found, a uniform cockpit-color
icon is used.
Name of image file, located in the resource
folder, to be loaded when the deck is not used.
Name of default values of several parameters, defined at the aircraft-level. These values will be used for all missing values. They can be raffined at Layout and Page level if necessary.
+If no aircraft-level global parameter values are not provided, Cockpitdecks will use its own internal default values.
A list of deck structure, one per deck.
+Yaml allow for other attributes in the file. They are ignored by Cockpitdecks. You may include other attributes like aircraft name, ICAO code, descriptions, notes, even change log of your file.
+The secret.yaml file contains the serial numbers of your connected decks.
+If you have more than one deck of the same type (i.e. two Streamdecks, two X-TouchMini, etc.) this file is mandatory to distinguish between the two physical devices. Otherwise, it is optional.
# My decks and their serial numbers.
+# Format:
+# DeckName: Serial number
+# DeckName must match name given in config.yaml.
+XPLive: AAA0000000000000000000A0000
+
Configuration et customization is organized in a hierarchical way. The the top, highest level is Cockpitdecks, the application.
+Under Cockpitdecks is the Cockpit. If not redefined after, all attributes defined in the Cockpit are used for all other elements.
+Under the Cockpit is the Deck. This allow to change a few parameters for each deck. For example, a given deck might have large icons, requiring the use of a large default font size.
+Under the Deck is the Layout. This allow to change a few parameters for each layout, like the background color of a panel. Layout parameters are melted into Deck parameters.
+Under the Layout is the Page, to control page-level specificities, like, for exemple, a specific background color or texture for a special page.
+That's it. At the "lowest" level, at the Button level, there are no default global values, just the values the button will use.
+
+This hierarchical organisation is exploited in default value lookups.
deckconfig
folders reside in X-Plane aircraft folders and are specific to that aircraft.
+In addition to these aircraft specific folders, Cockpitdecks has a global configuration folder called resources
located where the Cockpitdecks software resides.
resources
folder located where the Cockpitdecks software resides contains the following files and subfolders:
This is a global level configuration file. It always is loaded first and can be overwritten by aircraft, deck, or page-specific variants.
+Icons in this folder are available to all aircrafts.
+Fonts in this folder are available to all aircrafts.
+Cockpitdecks provides a few fonts found here and there together with their respective copyright files.
A copy of Cockpitdecks documentation is included there. The documentation folder produced in the GitHub wiki of Cockpitdecks.
+The resource folder contains a few image files used as logos and wallpapers.
+There is also an image with color names that can be used in color
attributes.
This file defines icon fonts. Icon fonts are fonts that are used to display iconic characters often named intuitively. Cockpitdecks comes with a copy of Font Awesome icons, and Weather Icons.
+Defines a few constants that should never be changed. Change at your own risk.
+Abstract
+In summary, a Cockpit is defined for a given X-Plane aircraft.
+A Cockpit contains one or more Decks. Each Deck represent a physical deck device used to interact with X-Plane. A Deck is assigned a Layout. A Layout is a collection of Pages. Each Page defines what knobs and buttons on the physical deck do, when they are turned or pushed, and what information they displays in return (through images or LEDs), information extracted from X-Plane data and behavior.
A Deck represents a physical device connected to the computer, be it a
+a device that will be used to interact with the X-Plane flight simulator.
+A Deck uses and displays a collection of buttons called a Page of buttons. A Deck can display different pages of buttons at different times; a button on a page can be assigned to load another page of buttons.
+Each Page define the set of buttons on the deck device, what each button does when pressed or turned, and how it will appear on the deck device. The collection of pages that can be installed on a deck is called the Layout of the deck.
+In addition to the Pages it contains, a Deck defines deck-level attributes, such as the overall brightness of the device, or how to fill unused or undefined buttons.
+Decks are declared in the config.yaml
file in the deckconfig
folder in the decks
attribute. The decks
attributes contains one or more decks as defined by the following attributes:
name: StreamdeckMK2
+Mandatory. Name of the deck.
type: streamdeck
+Optional. Type of deck. Streamdeck, Loupedeck, or Xtouchmini.
layout: layout_folder_name
+Optional. Name of the layout for this deck. Default to default
.
brightness: 80
+Optional. Overall brightness of deck. Default to 100%.
default-label-font: DIN Medium.ttf
+Optional. Default font to use for deck. Default to DIN, which is provided with Cockpitdecks.
default-label-size: 13
+Optional. Default label size. Cockpitdecks manipulates icon 256x256 pixels.
default-homepage-name
+Optional. Default page name in layout. Default to index
.
The type of Deck defines the "device driver" that will be used to talk to the deck. If a new model of deck appears in the future, it will be necessary to design its "device driver" for Cockpitdecks to use it.
+For a given aircraft, a deck has a Layout. The Layout of a deck is a collection of Pages that will be used and displayed on the deck device.
+A Layout is a folder in the deckconfig
folder.
XPlaneAircraftFolder
+ (...)
+ ⊢ deckconfig
+ ⊢ icons
+ ⊢ fonts
+ ⊢ layout1
+ ⊢ config.yaml
+ ⊢ page1.yaml
+ ⊢ page2.yaml
+ ...
+ ...
+
The deck definition should contain a layout
attribute that indicates which layout will be used for that deck. The default layout name, if not indicated is default
. If no layout is found for the deck, a default, minimal layout is created.
The project started from the multiplication of accessory devices. Some are very dedicated and allow for little flexibility. miniCockpit devices fall into that category. Some other devices are very generic and allow for customisations. Streamdecks, Loupedeck devices or other MIDI-based devices fall into this category.
+I created a single software to allow for the second category of devices to be used with X-Plane. This software needs to rely on conventions or generalisation to cope with all options and particularities of those devices. That is what I tried to bring into this project.
+The history of this project explains decisions and processes that were taken to cope with the diversity of devices.
A first step was clearly to generalise all particularities of devices. Pressing keys, rotating knobs or encoders, sliders, touch screens are all different means to interact with some devices. Little iconic display, colored buttons, or multi-led ramps are all different means to communicate feedback to the user. This leads to two abstractions for input (what is called Activation) and output (what is called Representation).
+A second step was to isolate all interactions with X-Plane: Issuing commands and monitoring dataref values. This is done in a collection of Simulator, Dataref, and Command abstractions.
+A final step was to isolate this software from all device particularities and specificities. This leads to abstractions such as Deck (make, models, device drivers to interact with the device) and Buttons (things a user interact with on a device). A simple abstract model describe the device capabilities and physical organisation (the Deck).
+Other entities glue things together with concepts like the Cockpit with is a collection of one or more deck, and a Page that is a grouping of buttons represented at once on a deck.
+I hope this piece of software will allow you to make a better desktop cockpit and make your flight simulation more enjoyable.
+ + + + + + + + + + + + + +If you are already using Wortelus' X-Plane Elgato Stream Deck Connector (ZIBO + more), installation and use of Cockpitdeck is simplified.
+If we assume you have one or more Streamdeck devices (not the Streamdeck +) already working with the above software, you just need to install Cockpitdeck next to «X-Plane Elgato Stream Deck Connector (ZIBO + more)», in the same python environment but you need to add Pillow
and ruamel.yaml
Python packages:
$ pip install ruamel.yaml pillow
+
If you want to use the Metar/Weather icon, you need to add:
+
$ pip install 'avwx-engine[scipy]' suntime timezonefinder
+
Wortelus's application works in a similar way as Cockpitdeck and use the same other packages. Cockpitdeck should start right away.
+First install or copy the deckconfig folder provided for Airbus A321 to X-Plane Airbus aircraft folder. Then start cockpitdeck:
+$ cd cockpitdecks
+$ python bin/start_cockpitdeck_udp.py path-to-folder-where-deckconfig-resides
+
As simple as it may appears when working, Cockpitdecks is a complex piece of software that relies on numerous technologies, systems, and interfaces to provide, ultimately, a confortable user experience.
+First of all, Cockpitdecks tries to provide a uniform representation of different deck models. Each deck model, from different manufacturers, has its own way of doing things. Different decks are accessed differently, some through basic serial (USB) interfaces, some through application programming interfaces, and some other through existing "protocols" made to talk to devices like HID or MIDI. Some device even allow several methods to be used.
+Cockpitdecks uses the appropriate method to hide the complexity of accessing the deck devices, to hide their particularities, at the expense of a complex and modular installation process. Some will use a single device, some other will use more than one, combining different models and brands to suit their needs.
+Cockpitdecks communicates with X-Plane through the network UDP protocol. This offers the advantage that Cockpitdecks and X-Plane do not necessarily need to run on the same computer, as long as both computer are on the same local network.
+Through UDP ports, X-Plane reports some internal paramater values (called datarefs), and accepts commands to execute.
+Some commands cannot be executed directly through UDP. For exemples, commands that have a start and an end cannot be started or ended though UDP. It is an X-Plane UDP limitation.
+To circumvent this, Cockpitdeck provides a small python plugin called the Cockpitdecks Helper plugin, that need to be installed into X-Plane to allow for start and end commands. The Cockpitdecks Helper plugin will execute start and end commands on behalf of the Cockpitdecks application. Cockpitdecks Helper plugin just need to be installed and will provide its services to Cockpitdecks. This plugin does not take any resource, it only adds and removes commands each time an aircraft is loaded.
+The Cockpitdecks Helper Plugin works automatically, reads deckconfig
configuration and creates a pair of (beginCommand, endCommand) for each long press command.
+Cockpitdecks Helper Plugin is written in the python language. So it needs the XPPython3 X-Plane plugin installed. XPPython3 plugin allow for execution of python code inside X-Plane.
+The Cockpitdecks Helper plugin is not necessary if Cockpitdecks is installed as an X-Plane python plugin. (See below.)
Cockpitdecks is a regular python application and will run with python 3.10, not newer if you use XTouchMidi devices.
+It is recommended to create a virtual environment and run Cockpitdecks from that environement. A set of packages need to be installed in that environment before Cockpitdecks can run. Create a new folder, in that folder:
$ git checkout https://github.com/devleaks/cockpitdecks.git
+$ pip install ruamel.yaml pillow
+
If the Weather/Metar button representation is necessary, add
+
$ pip install avwx-engine scipy suntime timezonefinder
+
To have Cockpitdecks manage Streamdeck devices, add
+
$ pip install streamdeck
+
To have Cockpitdecks manage Loupedeck devices, add
+
$ pip install
+git+https://github.com/devleaks/python-loupedeck-loupedecklive.git
+
To have Cockpitdecks manage Touch Mini devices, add
+
$ pip install
+git+https://github.com/devleaks/python-berhinger-xtouchmini.git
+
To execute long press commands, the Cockpitdecks Helper plugin needs to be installed in XPPython3 PythonPlugins folder.
+... /X-Plane 12/resources/plugins/PythonPlugins/PI_decks_helper.py
+
First, you have to completely stop (quit completely) original manufacturer deck configuration applications. They take exclusive access to the device and that prevents Cockpitdecks from finding and using them.
+To start Cockpitdecks, use the cockpitdecks_udp_start.py
script by supplying the X-Plane aircraft folder where deck confit resides. Start the python script and supply the folder name where deckconfig
folder resides.
$ python cockpitdecks_udp_start.py "/Applications/X-Plane 12/Aircraft/Extra Aircraft/Toliss A321"
+
Cockpitdecks will look for deckconfig
folder in the aircraft folder and start.
Cockpitdecks will repetitively try to connect to X-Plane. If it fails to connect, it infinitely tries again until it succeeds. If not connected, decks will load but no command will be issued to X-Plane and no data will come from X-Plane to update decks.
+When Cocpiktdecks successfully connects to X-Plane, it refreshes all pages by reloading them to reflect the state of the aircraft on the decks.
+If Cockpitdecks fails to connect to X-Plane or notices it does no longer receive dataref values from X-Plane, it will again repetitively try to connect to it until it succeeds.
The aircraft folder (Toliss A321) where cockpitdecks tries to find a deckconfig
folder can be anywhere, it does not need to be in the X-Plane aircraft folder. However, the deckconfig
folder must be in the X-Plane aircraft folder for the Cockpitdecks Helper Plugin. (For Unix technical people, a symbolic link does the trick.)
To report an issue with Cockpitdecks, you should always include the XPPython3.log
file created in the X-Plane folder. Cockpitdecks also create a cockpitdecks.log
files with more information.
The level of information produced in the file is controlled by the logging level parameter. (info=some information and warnings, debug=a lot of information for debugging purpose, your XPPython3.log file may grow quite large.) The parameter is available at the global plugin level (the entire plugin will report all messages), or can be set at a Cockpitdecks internal module level to pin point issues.
+ + + + + + + + + + + + + +For a given deck, a Layout is a collection of Pages that will be displayed on that deck.
+A Layout is a folder, inside the deckconfig
main folder.
+The Layout is named and addessed by the name of the folder.
Layouts were created to cope with different deck models. If you have a set of 30 commands, you can display them all on a 32 key deck. But you have to make two pages of buttons on a 16 key deck. Same button definitions, but two layouts.
+The Layout folder contains the following files:
+ ⊢ layout_name
+ ⊢ config.yaml
+ ⊢ page1.yaml
+ ⊢ page2.yaml
+
The config.yaml
file inside a layout folder defines Layout-level attributes.
# This is at layout level
+default-icon-color: (94, 111, 130)
+default-label-color: blue
+default-label-font: DIN Bold.ttf
+default-label-size: 13
+default-page-name: index
+
The default value for each attribute is the value found the Cockpit attributes.
+default-icon-color: blue
+Optional. Default color to use for icon background.
default-label-color: white
+Optional. Default color to use for layout labels.
default-label-font: DIN Medium.ttf
+Optional. Default font to use for layout labels.
default-label-size: 13
+Optional. Default label size.
default-homepage-name
+Optional. Default page name in layout.
The default value of some attributes (like font, colors, and sizes) is fetched at the Cockpit level if they are not specified at the Layout level.
+Other files in the folder are considered as Pages in the layout.
+If a deck has no layout specified, Cockpitdeck will generate one with one default page that will display a logo image on the deck and use the first available push button to toggle X-Plane Map On or Off.
+ + + + + + + + + + + + + +A Page is a collection of button definitions that will be installed and used on the deck at a given moment.
+A deck displays one Page of buttons and allow end-users to press them to trigger actions. Actions to be performed are defined in the button definition, together with the appearance of the button on the deck. Actions are constrained by the type of push button or encoder. A push button cannot be rotated. The appearance of the button is also constrained by the ability of the deck: Image icon, LED, colored LED, or, sometimes, no display at all.
A Page contains the following attributes:
+name: Index
+buttons:
+ - index: knobTL
+ name: FCU Airspeed
+ type: knob
+ commands:
+ - sim/autopilot/airspeed_down
+ - sim/autopilot/airspeed_up
+ options: dot, nostate
+includes: views
+fill-empty-keys: true
+
Name of the Page. Superceedes the file name. Case sensitive.
+If no name is given, the name of the page is the page file name (without the .Yaml
extension.)
+For a given layout, all pages must have different names, otherwise an error is reported, and the page with the same name is ignored.
Mandatory.
+A list of button definitions. Please refer to the Button section for details about button definitions.
Includes is a list of other pages to include in this page.
+Included pages are first merged inside the main page, and then submitted for display and use.
Default values to be used at the Page-level for display.
+Whether to fill unused keys with a default button definition as a placeholder.
+The default value of some attributes (like font, colors, and sizes) is fetched at the Layout level if they are not specified at the Page level.
+The buttons
attributes contains all button definitions.
If no Page is found in the Layout folder, Cockpit deck will create a default page which consists of a logo displayed on the deck (if the deck is capable of displaying images).
+The first available button will be programmed to toggle the X-Plane Map On or Off.
Cockpitdecks uses X-Plane UDP connection to perform two tasks:
+Here are some remarks about the use of X-Plane UDP for these purposes.
+Cockpitdecks has a two-way communication channel with X-Plane. When a user presses a button on a deck, a command is issued to X-Plane and/or a dataref value is changed. In the other direction, Cockpitdecks received values of datarefs it monitors, and if a value has changed, it notifies the deck to change its appearance accordingly.
+Decks have sometimes 30 buttons, and simulator pilots sometimes have several decks. During developments, Cockpitdecks controlled up to 6 decks. This led to the monitoring of an average of 80 different datarefs to change the appearance of 80 buttons or LED encoders.
+We only request dataref values to be sent at the lowest emission rate, that is once per second.
+A UDP packet of values contains at most 14 or 15 values. It takes a few packets to get all dataref values.
+We experimentally observed that there is a performance limit of about ~100 datarefs that can be requested from X-Plane. After that, UDP packets will be emitted, but with some noticeable delay (up to a few seconds). And since they will be emitted late, their value will no longer reflect the current X-Plane value.
+To request more datarefs, you can request them by batch of less than 100 datarefs and switch batches of requested datarefs at regular interval. It works very well.
+Cockpitdecks created a dataref batch collector.
+Horizontal and Vertical Arrays
+Add ability to collect an array of values, especially arrays of characters (I.e. strings).
+This is not easy give UDP restrictions (packet size), and X-Plane UDP choices (it only returns float).
+May be an exception should be make for strings with restrictions, like ASCII characters only, limited to the maximum size of a UDP packet.
+Getting a 40 or 80 character string in one operation would be a major improvement.
+Getting arrays of maximum ~14-15 floats in one operation too.
+Commands that are initiated with beginCommand and terminated with endCommand should get some support too. Like, for example, begining the command with a timeout, if the end of the command is not received within the timeout, the command is automagically ended. (I did a plugin that does that, or something similar.)
+ + + + + + + + + + + + + +Typical buttons display an information in a static way, an icon or a LED that is updated when a status or a value has changed.
+Animation is a button representation option that consists of continuously sending representation updates to continuously change the button's appearance.
+For example, in its simplest form, a icon animation consist of sending a different images to a key at regular interval, cycling to a list of images (vey much like a GIF animation...).
+Another simple animation consists of making an icon «blink» on or off. A more complex animation can consist of a parametrized drawing, an image is drawn at each iteration and sent to a key.
+Animations are automatic. They should not be confused with button appearance updates that occur automagically when underlying button values change.
+Most of the time, the value button determine if the animation runs. When the value of the button is On, the animation runs. When Off, the animation does not run and may displays an alternate representation.
+An icon-based animation is a procedure that changes the icon to display at regular internal.
+The icon to display is specified through its index value in the list of icons available to the button (through the multi-icons
attribute).
icon-off
: When not running, an alternate icon can be displayed.
A blinking annimation is an procedure that forces some of all part of a Representation alternatively On and Off and provoque a rendering update after changes, leading to a blinking button effect.
+In this case, the animation controls and changes the value of the button, switching between On and Off states. The representation changes accordingly.
+A Drawing animation is a parametrised drawing that uses a single parameter value (for exemple the button's value). When the value changes, the procedure optionally uses a tweening algorithm to progressively change the value from the old one to the new one.
+As a proof of this concept, the FollowTheGreens Representation displays a portion of taxiway centerline with "flashing" lead light when it is activated.
+Animations do not need to be fast. As another proof of concept, the Weather representation pictures a Metar report on a icon. The representation is updated each time the Metar is updated (about every 30 minutes). It is another form or use of animation.
+ + + + + + + + + + + + + +An Annunciator is a special image used for display on a deck key.
+An Annunciator image is build dynamically from its definition and from data coming from X-Plane. Airbus airliners extensively use annunciator buttons.
+Annunciator do not specify what they do, this is done by the button activation definition. Annunciator only address the representation of the button, the content of the image displayed on a deck key.
+On a deck, the representation of keys that accepts images can either be
+Annunciators exits in 3 sizes:
+1. Large, square 1in × 1in.
+2. Medium, rectangular, 5/8in × 1in, or smaller but in the 5:8 ratio.
+3. Small, rectangular, 1/2in × 1in, or smaller but in the 1:2 ratio. (Or sometimes 3:8 ratio.)
+Given the limited size of deck key images (typically less that 100 pixels), annunciator always occupy the maximum space on the key. However, the above size of the annunciator govern the aspect ratio of the image: 1:1, 5:8, 1:2.
Annunciator can display from 1 to 4 different data or information on a single key. Depending on the annunciator model, data is displayed on two rows, in two colums.
+
Each portion of an annunciator that can be used to display information is called an (annunciator) part. In an annunciator of type A, there is only one part called A0. In an annunciator of type E, there are three parts, E0, E1, and E2, arranged like shown on the above illustration.
+Annunciator of type F can display 4 different informations. The button underlying such an annunciator has therefore 4 distinct values.
+Each annunciator part is defined independently of the other parts.
+In a part, displayed information is either
+1. A Text, which can optionally be framed, or
+2. A LED of some kind: Block, bars, dot, or lgear (a small triangle)
+(Since Cockpitdecks provides icon fonts, (or you can load your own font,) it is possible to display any icon from a font with Text information and optionally frame it.)
- index: 5
+ name: A/THR
+ type: annunciator-push
+ annunciator:
+ size: medium
+ model: B
+ parts:
+ B0:
+ color: lime
+ led: bars
+ dataref-rpn: ${AirbusFBW/ATHRmode}
+ B1:
+ text: A/THR
+ color: white
+ size: 60
+ dataref-rpn: "1"
+ command: AirbusFBW/ATHRbutton
+
The Annunciator defintion starts at the annunciator:
attribute.
Code letter from A to F to specify how annunciator parts are organised on the annunciator.
+Annunciator size: large, medium or small. Full size is a large size that occupies the whole square button. Size mini exists but is practically not used.
+The part attribute can be used to group all part definitions.
+Each part is addressed by the name of the part: A0, B0, B1, etc. The content is the part definition.
B0:
+ color: lime
+ led: bars
+ dataref-rpn: ${AirbusFBW/ATHRmode}
+
The part definition must contain either a text
attribute or a led
attribute.
+
A part is either lit or not, On or Off. Either status can be represented by supplying background and foreground colors.
+
There are two styles of annunciators. Both are named after major brands of annunciator manufacturer. Annunciators appears differently according to their style.
+The first style is Korry (annunciator-style: k
), where the annunciator appears like a translucent window with back light. When the annunciator is not lit, the text or drawing is slightly readable on the display. When lit, the text appears to glow.
+
The second style is Vivisun (annunciator-style: v
). When the annunciator is not lit, it has the color of the button (usually black) and no text is readable. When lit, displays on a Vivisun annunciator are sharp, very much like a "retina display" (high resolution display).
Both styles truthfully reproduce keys on decks. Combined with the adjustment of the intensity of the deck back light, they provide a real immersive experience.
+annnunciator-style
can be defined at the Cockpit, Deck, or Page level.
Annunciators can optionally be protected by plastic cover guards.
+dateref
+Dataref path to value driving the guard status (open or protected).
type
+Cover or grid
color
+Color of guard. Defaults to red.
+Translucent color (with alpha, or transparency channel) can be supplied.
color: (255, 0, 0, 100)
+Is a translucent red color (r,g,b,a), a=0=transparent, a=255=full opaque.
In the definition of the button, the type
attribute determine what the button will do.
For a given button on a deck, the action that the button will be able to carry over is limited to a set of valid types. A push button is not capable of rotations of an encoder.
+Each activation below list configuration attributes and internal values it maintains. Numeric internal values are accessible as ${state:variable-name}
in formula.
type: none
+Button with no activation are button used for display purpose only.
In spite of having no activation, the button maintain an internal state.
+activation_count
last_activated
initial_value
previous_value
current_value
guarded
managed
type: page
+When the button is pressed, a deck will load a page of buttons.
page
+Mandatory. Name of the page to load. The page must be in the Layout of the target deck.
remote_deck
+Optional. If present, will load the page on the target deck.
page
: page that is currently displayed.
type: push
+Push button.
command
+Mandatory. X-Plane command that is executed each time the button is pressed.
Note
+Command is a mandatory parameter but if no command is necessary a command placeholder value can be used. Command placeholder value are any of the following string:
+none, noop, no-operation, no-command, do-nothing
+They all are ignored and do not trigger any activity in X-Plane.
auto-repeat
+Auto repeat command at specified pace while the button remains pressed.
auto-repeat
option accepts a couple of optional values:
delay
: Time (in second) after which the auto-repeat starts, default to 1 second.speed
: Time (in second) between 2 executions of the command. options: auto-repeat=3/0.5,dot
+
Auto-repeat will start 3 second after the button was pressed, the command will auto-repeat every 0.5 seconds, twice per second. (dot
option also set for other purpose.)
type: longpress
+Push button that will carry the command as long as the button will remain pressed.
Long press command should not be confused with auto-repeat commands. A Longpress command in one command that is executed once as long as the button remain pressed. An auto-repeat command is the same command that is executed several times at regular interval (typically once every 0.2 seconds, 5 times per second) as long as the button is pressed.
+Note
+The Longpress command requires installation of a XPPYthon3 plugin in X-Plane to circumvent a few X-Plane UDP limitations.
+command
+Mandatory. X-Plane command that is executed while the button is pressed.
+X-Plane will issue a beginCommand
when the button is pressed and a endCommand
when released.
Note
+Please note that the use of longpress command needs the addition of a little plugin to circumvent X-Plane UDP limitations when used through UDP.
+type: onoff
+Push button.
commands
+Optional pair of X-Plane commands that are executed alternatively. Two commands must be supplied, but the same command can be provided twice.
set-dataref
+Optional dataref to set On(=1) or Off (=0).
Either attribute can be set or both. In the latter case, the command is first executed and then the dataref is set.
+type: updown
+Cycle Up and Down button.
commands
+X-Plane commands that are executed when pushes increase value, and when pushes descrease value.
stops=3
+Number of stop values. For example: Stops=3 will give 0-1-2-1-0 cycles, with 3 stops 0, 1, and 2.
initial-value
+If an initial value is supplied, it's sign indicated how the value will evolve.
+For example, if the initial value is 1, the next value will be 2 (go up). If the initial value is -1, the initial value will be set to 1, but the next value will be zero (go down).
set-dataref
+Optional dataref to set the value of the current stop.
Very much like On/Off activation either commands
or set-dataref
can be supplied or both.
Type: encoder
+An Encoder is a rotating knob or dial with steps. Steps are often materialised by a little sound or a slight resistance in the rotation.
commands
+An Encoder has two commands, one that is executed for each step while turning clockwise, and one for each step when turning counter-clockwise.
rotation_clockwise
: number of times/clicks the encoder was turned clockwise.rotation_counterclockwise
: same.type: encoder-push
+An EncoderPush is the combination of an Encoder and a push button.
commands
+An EncoderPush has 3 commands:
type: encoder-push
+An EncoderOnOff is the combination of an Encoder and an OnOff button.
commands
+An EncoderPush has 4 commands:
options: dual
+With option dual
, the activation uses two more commands.
commands
+An EncoderLongPush has 4 commands:
type: encoder-push
+An EncoderValue is an Encoder that increases or decrease an internal value each time it is rotated clockwise or counterclockwise. The value can be written to an X-Plane dataref or used for other pruposes.
initial-value
+Initial value. Default to 0.
step
+Amount of value increase or decrease.
stepxl
+Alternate value for step increase or decrease. If the encoder is capable of push action, the push action will switch between the step
and stepxl
values.
min
+Minimal value.
max
+Maximal value.
formula
+Optional. Formula to transform the ${state:button-value}
before it is sent to the dataref.
set-dataref
+Optional dataref to set to the value of the computed value. The value is sent right away, after each encoder activation.
type: slider
+A Slider is a one dimensional cursor that produces a continuous value within a range. The value can be written to an X-Plane dataref, directly, or after a computation.
set-dataref
+Optional. Dataref to write the value to, if present.
formula
+Optional. Formula to transform the ${state:button-value}
(value produced by the slider) before it is sent to the dataref.
type: swipe
+A Swipe is a 2 dimensional movement of a finger on a surface. The event produced consists of the start and end positions of the finger relative to the surface (x, y) and timing information (time stamp).
(Currently not used.)
+The Swipe event has no attribute.
+The event of a swipe is complex. The entire event is available as last_event
.
+The event has the following structure:
ts_start: 123.456
+ts_end: 135.246
+pos_start: (23, 48)
+pos_end: (78, 42)
+
Reload, Stop, or Inspect are special activations for developer.
+These activations are normally not used during regular operations.
Each Activation has a is_valid()
method that checks whether all necessary attributes or parameters are available to it. The inspect keyword to trigger button validity inspection is valid
.
+Each Activation also has a describe()
method that displays and explains what it does. The inspect keyword for displaying activation description is desc
.
Cockpitdecks offers a few special activations that are normally not called in regular use.
+type: reload
+No option. Provoke the reload of all decks from initialisation.
+The procedure first gracefull terminates the current setup, and then reloads the setup.
+If a page different than the home page was currently loaded, the process will try to reload the same page if available in the new setup.
+This activation is mainly used during development process to create buttons, alter their appearance and re-load the configuration to see the changes.
+(Please note that reloading decks is a complex process, since it involves the reset of all devices, reloading all configurations, and displaying pages as they used to be, if still present.)
type: stop
+No option. Gracefully stops all decks and terminates Cockpitdecks.
Provoke the output of information for all buttons of all pages or all decks.
+Mainly for development purpose.
+Inspection always starts at the Cockpit level and may or may not crawl down into its constituting parts like decks, layouts, pages, and buttons. Some inspection terminates earlier in the drill down. For example, threads
inspection stops at the Deck level.
Button Inspect has one attribute
+what
+The value of the what
attribute determine what is displayed when activated.
threads
: list Cockpitdecks and deck threads that are currently running.
+datarefs
: list datarefs and values (the page containing the buttons need to be loaded first before it can display values).
+datarefs-listener
: List all datarefs and which buttons (listeners) are using the dataref.
+status
: list internal variables and statuses of each button.
+valid
: check button validity and report invalid status.
+desc
: print a description of what each button does in plain English, both for activation and representation.
+image
: produces an image of each deck, images are saved in the Cockpitdecks home directory and named after the deck.
+longpress
: list Longpress command that should have a couple of additional commands added to X-Plane through the plugin.
index: 4
+type: inspect
+what: desc
+
When button index 4 is pressed, it will display what each button does (description) in plain English on the output or debugging screen or file.
+ + + + + + + + + + + + + +Buttons are defined by a list of attributes.
+Some attributes are unique to a button, very specific, and cannot have default values like, for exemple, the button index or a button label attribute.
+Some other attributes are used by numerous buttons, like for example the color of the label. These common attributes benefit from a sophisticated default value lookup.
+Before we can look up at the attribute evaluation method, we must notice that all objects we manipulate in Cockpitdecks are hierarchically organized.
+This hierarchy is very important.
+As an example, let us find the value of the label-color
.
+First, the button will perform a direct lookup in its attribute. If it finds a label-color
it will use it. If it does not find it, it will as its default-label-color
. The button will then ask its parent entity for the default-label-color
.
So the Page will search for a default-label-color
in its attributes. If it finds it, it will use it. If it does not find it, it ask its parent entity.
The Deck will search for a default-label-color
in its attributes. If it finds it, it will use it. If it does not find it, it ask its parent entity.
Finally, the Cockpit will return a default-label-color
. If there is no value for the default-label-color
, Cockpitdecks will issue an error. It simply means that there is no default value for that attribute and that a value must be supplied by the user in the definition of the button.
Cockpitdecks attempts to provide a day and a night theme. The attribute cockpit
can be set to day
(or light
) or night
(or dark
).
cockpit-theme: dark
+
The effect is that in night
(or dark
) theme, default values prefixed with dark-
will be favored. If no default value prefixed with dark-
is found, the regular default value is fetched.
Example for label color:
+In day
mode, the default value for label color is default-label-color
, as usual.
In night
mode, the default value dark-default-label-color
value is first searched, and if not defined, the default-label-color
is retuned.
Note
+Ultimately, this scheme can be extended to any theme name value, like airbus, or barbie. However, it is advisable to limit theme default values to global appearance parameters like colors, fonts, textures, and sizes.
+Sometimes, configuration values can be specified at different level for a given entity.
+At the highest level, a Cockpit will start with a set of default values provided in its code.
+It will then loads additional parameters in a global resource configuration file. That file is the same for ALL aircrafts. The config.yaml file is located in the home directory of Cockpitdecks software, in the resources folder.
+Next, Cockpitdecks will look for an aircraft specific configuration file, in the deckconfig folder of that aircraft. It will load the config.yaml file of that aircraft, and default values loaded from there will apply to that aircraft only.
+A Deck will start with the configuration attributes supplied by the Cockpit. The Cockpit uses the configuration passed in the the global, aircraft-level configuration file.
+A deck will load a Layout. When doing so, the deck may read an optional configuration file located in the folder of the Layout it will use. The attributes specified in the layout configuration file will take precedence over those at the deck level.
+In addition to button definitions, a Page contains other page-level attributes.
+When a page includes another page, their respective attributes get melted (combined). The attributes of the included page overwrite the attributes of the base page.
+Since a page can include more than one other page, the attributes of the included page are added (on top of) the attribute of the base page and other included pages. But since the order of page inclusion is not specified, attributes may be piled up in any order.
+In other words, it is advisable to not include any page-level attribute in a page that will be included in another page, it may lead to unexpected behavior or presentation. It is safer to limit inclusion to the buttons
attribute, where buttons of main page and included page are merged together.
The index
attribute is a mandatory attribute of a Button. It designate a very precise button on the deck. Hence, it defines what the button is capable of performing and how it will be rendered.
Streamdeck Mk.2, XL, Mini are composed of square icon keys. Image sizes vary with models.
+Streamdeck + (Plus) as 8 square keys, 4 knobs, and 1 larger LCD capable of touch interactions.
Streamdeck Plus encoders are aligned at the bottom of the deck and have indices e0 to e3.
+Streamdeck Plus has a 800x100 pixel touchscreen between the keys and the encoders.
+LoupedeckLive has 6 knobs, 12 square keys (90x90), and 2 side LCD (60x270).
+There is an additional row of 8 push button labeled 0 (dotted-circle) to 7.
Both LCD and all 12 keys form a larger (480x270) LCD capable of touch interaction.
+In an alternate presentation, side LCD can be considered as 3 individual buttons each.
+To simplify, we assume in this case that all 6 side buttons are square (60x60). Space between these button is filled with default color, image, or pattern.
XTouchMini has 8 encoders with 8 "multi-led" displays, and 16 buttons with LED.
+There is a slider and two more buttons on the side. These two buttons were meant to be used as "page" switches between 2 pages labeled A and B. For simplicity, we chose to not change the use of these two buttons and they should be programmed as Page Loader activation. The currently loaded page can be highlighted, like on the above photograph, Page A is loaded.
The Representation of a button determine how it will be displayed on the deck device.
+The representation depends on the capabilities of the button on the deck. There is a list of valid representations or a given button on a deck. A image or icon cannot be displayed on a LED-only button.
The first attribute mentioned in each section below determines the type of Representation (icon
, text
, multi-icons
, etc.)
+If more than one representation is found, or a representation that is not valid for the given button, a warning message is reported and the button does not render anything.
If no Representation is found, a warning message is reported and the button is assumed having no representation. For example, a X-Touch Mini slider has no representation. To suppress the warning message, the representation
attribute can be used and set to false
.
- index: slider
+ name: SLIDER
+ type: slider
+ representation: false
+
will not issue any warning message.
+dataref: dataref-path
+Path to a dataref that is interpreted to determine whether the value is managed.
If the value is managed, the value can be displayed as a text string in an alternative way depending on the text-alternate
value.
+text-alternate: dash=4
: Represent managed value by a set of -
. Default is 3 dashes.
+text-alternate: dot
: Represent managed value by a single dot •
.
- index: 0
+ type: none
+ name: FCU Airspeed display
+ label: SPD
+ text: ${sim/cockpit2/autopilot/airspeed_dial_kts_mach}
+ text-format: "{:3.2f}"
+ text-color: khaki
+ text-size: 24
+ text-font: Seven Segment.ttf
+ text-position: cm
+ text-bg-color: (40, 40, 40)
+ managed:
+ dataref: AirbusFBW/SPDmanaged
+ text-alternate: dash
+
In example above, speed managed mode, if AirbusFBW/SPDmanaged
dataref value is non zero, the text will display ---
. Otherwise, it will display the air speed.
dataref: dataref-path
+Path to a dataref that is interpreted to determine whether the button or key is guarded (protected against unintentional use by a cap or lock). If guarded, it can be displayed in an alternative way depending on the options value.
type
: Protects the button with a full red cover (type: full
) or a see-through grid (type: grid
)(cover is the default).
color
: Color of the guard. Default is red for cover, and translucent red for grid.
label: RAM AIR
+ guard:
+ type: grid
+ color: black
+ dataref: ckpt/ramair/cover
+ # 0=closed, 1=opened
+
Guarded buttons or keys need to be pressed twice to activate, the first activation lifts the guard, the second one acts normally. To replace the guard, a long press of more than 2 seconds is necessary to replace (close) the guard. (Make sure long press lasts 2 seconds or more, otherwise the button will be activated!)
+icon: ICON_FILE_NAME
+An image file is loaded on the deck key if it is capable of displaying images.
icon: isi
+frame:
+ frame: frame_image.png
+ frame-size: [256, 256]
+ content-size: [128, 128]
+ content-offset: [64, 64]
+
A frame
is a special "background" image that is first loaded, and the icon itself is laid over the background image. In the above example, icon isi
will be resized to 128x128px and placed (pasted, laid over) at position (64, 64) in the frame image.
+
+The purpose of framed icon is to provide a uniform icon representation (the frame) with varying inner content (the icon itself).
+It is different from a textured background because it allows for icon placement and resizing before pasting over the underlying image frame.
text: "SOME\nTEXT"
+An image file is created with a uniform background color or texture and text laid over.
+The text laid over the button should not be confused with the label. The text laid over is additional to the label, and can be dynamic to display a changing value like the heading of the aircraft or the amount of fuel left in a tank.
text-bg-color: lime
+Background color of the image or icon where the text is displayed. Default background color is cockpit color.
text-*: value
+Values for font, font size, color, and position of the text on the image.
It is possible to use subsitution of coded string in text values:
+${dataref-path}
is replaced by the scalar value of the dataref pointed by dataref-path
.${formula}
is replaced by the value computed in the formula
.${state:name}
is replaced by the scalar value of the button' state name
.Note: A Text string value is not a formula and is not evaluated. Above strings are simply substituted.
+text: ${formula}
+text-format: 4.2f
+formula: 3.14 2 ${dataref-path} * *
+
Will produce an icon with text value "3.14
" text in the middle.
multi-icons
multi-icons:
+ - ICON_FILE_1
+ - ICON_FILE_2
+
Multiple icon files are displayed according to the value of the button.
+For example, for an OnOff activation type there may be two icons for On and Off positions; for a UpDown activation type, there may be one icon for each stop position.
No attribute.
+multi-texts
multi-texts:
+ - text: Option 1
+ text-color: green
+ - text: Option 2
+ text-color: amber
+ - text: ${aicraft/some_value}
+ text-format: "Limit reached {4.1f}"
+ text-color: red
+ text-font: DIN Bold
+ text-position: tr
+ formula: ${dataref_for_text_selection}
+
A Multitext attributes contains a list of IconText-like attributes (a list of text block) where each text block can contain attributes like in an IconText text block.
+A single text block is selected according to the value of the button.
In the above example, the formula ${dataref_for_text_selection}
return 2, the second text block
+
text: ${aicraft/some_value}
+ text-format: "Limit reached {4.1f}"
+ text-color: red
+ text-font: DIN Bold
+ text-position: tr
+
None
+The selection of the text block must be performed by a formula and not a dataref.
+When a formula is present in the attributes of a button, it is always favored over a list of datarefs, even if the list contains only one dataref. (If there a button uses multiple datarefs and there is no formula, the value that is returned for that button is a diectionary of all dataref values.)
icon-animation:
+ - ICON_FILE_1
+ - ICON_FILE_2
+
Multiple icon files are displayed in sequence automagically when the button is On.
+icon-off: ICON_FILE_NAME
+The icon to display when the button is Off. If there is no icon-off, the first icon in the icon-animation list is used.
speed
+Time in second an icon is displayed before displaying the next one.
icon-side: ICON_FILE_NAME
+An IconSide is a special icon for LoupedeckLive devices, used on either side of the main panel. IconSide have particular display capabilities to cope with their specifics, sizes, and their positions that allow to display information regarding the nearby encoders.
labels
+Labels that are displayed on the icon.
label-positions
+Label anchor position expressed in percentage of the 100% height of the side image.
Note: There might be similar icons to control the display of other, larger display like the Streamdeck Plus bottom LCD display.
+`led: led
+Turns a single LED light On or Off depending on the button's value.
led: colored
color: orange
Turns a single LED light On or Off depending on the button's value. The color of the LED is determined by the color attribute.
+The color
attribute can use a formula to determine the color (single hue value in 360° circle.)
led: multi-leds
+MultiLeds are LED-based display that use more than one LED for reporting information.
+X-Touch Mini encoders, for example, are surrounded by 11 LED that can be lit individually.
+
led-mode: fan
or led-mode: 2
; name or number
+Valid modes are:
The value of the button determine how many leds will be displayed (0 to 11).
+Annunciators are special type of button display. There is a dedicated page for them.
+annunciator:
+ text: "MASTER\nWARN"
+ color: red
+ font: DIN Condensed Black.otf
+ text-size: 72
+ dataref-rpn: AirbusFBW/MasterWarn
+ options: blink
+
Switches are drawings often used by OnOff activations that can be used in replacement of icons.
+Switches is a drawing of a simple two or three-way switch.
+Circular switches are multi-value rotation switches or selectors.
+Push switches are simpler two state push button.
Some decks have particular LCD displays. Cockpitdecks designed specific activations and representations for those.
+Above switches are special instances of dynamically drawn representations.
+There are other dynamically drawn represetations for displaying data, or weather information.
+The sky is the limit.
Each Representation has a is_valid()
method that checks whether all necessary attributes or parameters are available to it and valid. If the validity function fails, a warning is reported and the button is not rendered. The inspect keyword used to verify the validity of the representation is valid
.
+Each Representation has an describe()
method that explains what it displays in plain English. The inspect keyword used to describe the representation is what
.
A Button can have 0, 1, or more than one value in the special case of annunciators or side buttons. Activations and Representations of the button knows how to manage the different values.
+Each value of a button is either None or a numeric value (floating point number). If a button has several values, its value is a list of all individual values, each individual value being None or a number.
+A button builds its representation from its value. The value of the button is computed from one or more dataref values returned by X-Plane and/or from some internal state variable values.
+A Button can get its value from the following sources:
+If no attribute determine the value of a button, it will return its internal state.
+A dataref is the name of a value used by the X-Plane simulator.
+The value can be a string, integer, or float value, either a single value or an array of (same type of) values. A dataref has a name to access it. Names are organized in a folder-like structure (namespace using /
separator). Some datarefs are read-only, some other can be written and modified.
Dataref name | +Value | +Description | +
---|---|---|
sim/cockpit/misc/barometer_setting | +Float | +Value of the atmospheric pressure at the aircraft location in inches of mercury | +
There are thousands of datarefs in a running instance of X-Plane. Datarefs drive almost everything in the simulator.
+A dataref is always monitored. Its value is fetched from the simulator at regular internval (typically every second). When a Dataref's value has changed, all buttons that depend on that Dataref are notified to update their appearance.
+To explore datarefs, there is a handy X-Plane plugin called DataRefTool. There are also a few web pages that collect, report, and present them so that they can be searched.
+Cockpitdecks manages its own set of datarefs.
+All datarefs that starts with a special key word are NOT forwarded to X-Plane but rather managed internally inside Cockpitdecks. Otherwise, they are not different from X-Plane datarefs. They can be set and used like any other datarefs.
+When a button emit an internal dataref, it's definition mention it clearly so that it can be used by other buttons.
set-dateref: Cockpitdecks/my-local-variable
+
+# in the same or another button, it can be used like so:
+
+ formula: ${Cockpitdecks/my-local-variable}
+
In the above example, the prefix Cockpitdecks/
denotes internal datarefs.
The current default prefix for internal datarefs is data:
.
Internal datarefs can be used as inter-button communication, to set a value in one button, and use or read it in another one.
+When a button cannot fetch its representation from X-Plane, it is possible to use some Cockpitdecks internal variables made available through the button state. Each button maintain its state, a few internal variables, that can be accessed in formula.
+State variables made available to formula are listed in the Button Activation page.
+The value of the button can then be either a list of (name, value) pairs, or a single value.
formula: {state:button_pressed_count} mod 2
+
The raw value acquired from a source may not be usable by a button representation. Before a raw value can be used by a representation, it needs normalisation. The normlaisation of a value is the process of transforming the (raw) value from the datarefs or formula in values usable for representation.
+Some dataref values are changing very rapidly over time, sometimes in insignificant changes. To prevent updating a button's state each time a value changes, a Dataref value can be rounded.
+sim/weather/aircraft/qnh_pas 0
+
Value 101308.35278 will be rounded to 101308.
+Some button may not maintain any state or use any value. Example of such button are simple push button with no feedback mean.
+The value of the button is determined by a single dataref value.
+In its simple form, the value of a button is deduced from the value of a single dataref. If the value of the dataref is zero, the representation is OFF, otherwise, it is ON.
+The status of a button is deduced from the value of either a single dataref, or a formula expression.
+Ranges are used as buckets to determine in which range/bucket the value falls. Then, the number index of the range, starting with 0, is used to determine which icon to display.
+There must be a matching number of ranges and icons.
+(Note: Currently not used.)
A Representation is driven by a single final value. However, it is possible to compute that final value form a list of dataref values and mathematical operations. This is done through a formula
attribute. The formula is written in Reverse Polish Notation, a method to write and execute operations on values. Since a formula allows for value transformation, a formula should always produce a value that is directly usable by a representation. The value of a button can be computed from data coming either from X-Plane (through dataref values) and/or from the button's internal state values.
Examples of formula
:
# Simple math (in reverse polish notation):
+ formula: ${AirbusFBW/OHPLightsATA34[8]} 2 * floor
+
+ # Constant 1; always 1; always True or On
+ formula: 1
+
+ # Insert 0 = true, 1 = false
+ formula: ${sim/cockpit2/switches/avionics_power_on} 1 - abs
+
+ # Boolean operation not
+ formula: ${sim/cockpit2/switches/avionics_power_on} not
+
+ # Boolean operation
+ formula: ${AirbusFBW/OHPLightsATA34[8]} 4 eq
+
+ # Formula used for display of a value
+ formula: ${sim/cockpit/misc/barometer_setting} 33.8639 *
+ text: ${formula}
+ text-format: "{: 4.0f}"
+
+ # The following two lines are equivalent; they both return the same value
+ formula: ${sim/cockpit/autopilot/vertical_velocity}
+ dataref: sim/cockpit/autopilot/vertical_velocity
+
Only one formula attribute can be used for a button or a annunciator part.
+The formula for computation is expressed in Reverse Polish Notation.
+The result of the formula is a numeric value (float value that can be rounded to an integer if necessary.)
It is intimidating at first to write RPN formula, but once a user get use to it, it actually is equaly easy to write RPN formula and formula with parenthesis.
+In a nutshell, rather than writing
+(8 / 2) + (4 × 5)
+in RPN, we write
+8 2 / 4 5 × +
+We place the value we act upon first, then the operation we perform on those values.
+`
The following operator have been added:
+- %
: Pushes reminder of division of last two elements, modulo.
+- floor
: Round element to smaller interger value.
+- ceil
: Round element to larger interger value.
+- round
: Last element rounded to closest integer value.
+- roundn
: Element rounded to last element of stack (forced to interger):
+1.2345 2 roundn => 1.23
+- abs
: Absolute value of last element
+- chs
: Change sign of last element
+- eq
: Test for equality of last two elements. Pushes 1 for True, 0 for False on the stack.
+- not
: Boolean not operator, insert True and False values.
In formula:
+${dataref-path}
is replaced by the scalar value (converted to float) of the dataref pointed by dataref-path
. Example: ${sim/aircraft/fuel/tankleft}
.${state:name}
is replaced by the scalar value of the (current) button' state variable named name
. Names of available state variables depend on the activation; each activation lists internal state variables made available through the button' state. Example: ${state:activation_count}
.${button:cockpit-name:deck-name:page-name:button-name:button-variable-name}
: Substitute de given button name by its value. Example: ${button:Airbus A321:sd-xl:efis:apu:status:activation_count}
. If no button variable name is given, the current value of the button is returned.In all case, if the value is not found, it is replaced by None, which translate into 0 (zero) in formula (to prevent the formula from failing to compute). If the value is not found, a warning message is reported.
+The following formula determine the final status On(=1) or Off(=0) from the number of times a button was pressed:
+formula: ${state:activation_count} 2 %
+
In case a button has multiple values, each value comes from a part of the button. Each part of the button is independant of other parts of the same button. Each part maintains its single value.
+All part values are aggregated into either a dictionary of values or an array of values that is made available at the button level.
+For example, Annunciator, or Side representation, have more than one individual values that are fetched and maintained to provide a single table (or array) of individual values.
+Another example is a button that has more than one dataref and no formula. In this case, the returned value is a dictionary of all dataref values of that button.
A Button can force its first, initial value to set its startup or original state.
+ initial-value: 2
+
This value is assigned as the button's current value on startup.
+In case of a Button with multiple values, each value has a independant initial-value
attribute.
A 32 button page can quickly request more than 40 datarefs from the simulator. The simulator takes a few precious cpu cycles to pack and send datarefs. We experimentally found a limit around one hundred datarefs. The fewer requests, the better. Unless otherwise specified, Cockpitdecks request a dataref once per second. Datarefs are sent in UDP packets of about 14 values. It takes on average 2 or 3 UDP packets to get all dataref values.
+To limit to number of requested datarefs at a point in time, and to allow for almost unlimited datarefs requests, Cockpitdecks has the concept of Dataref Set.
+A Dataref Set is a limited number of datarefs that are requested from the simulator together.
+The Dataref Set Collector is responsible for scheduling the collection of multiple dataref sets, one at a time.
+Each dataref in a set is monitored, value changes are registered, a Dataref Set is said to be completed when all dataref values have been received at least once.
A button can have a dataref-sets
attribute, it is a set of individual Dataref Sets. The attributes of a Dataref Set are described in the following Section. A button will receive completion events for each individual set, and anither « total » completion event when all sets are completed.
Collection name. Must be unique for Cockpitdecks.
+Attempt to register a set with an existing name will fail to register the second set.
List of datarefs in set.
+There is a maximum value of datarefs in a set (20). If more datarefs are requested, a warning is sent and additional datarefs are ignored.
How long, after all datarefs have been collected at least once (set is completed) does the Collector schedule the collection again for update. The set will be completed again after all datarefs have been updated after the collection has been requested for update.
+The array
attribute is an integer value. If present, it tells that each datarefs in the datarefs
attribute is an array of values of size array
. All datarefs in the set must have the same array length. As a result, this attribute will lead to the creation of array
sets, one fo each element of the array of dataref values.
+Typical arrays of values that can be requested as such are weather data like clouds or wind layers:
set-dataref: data:all-cloud-layers-completed
+dataref-collections:
+ -
+ name: cloud-layers
+ datarefs:
+ - sim/weather/aircraft/base
+ - sim/weather/aircraft/tops
+ - sim/weather/aircraft/cloud_type
+ - sim/weather/aircraft/coverage
+ array: 3
+ set-dataref: data:cloud-layer-completed
+ -
+
The above example will create 3 equal sets of 1 datarefs and is equivalent to the following:
+Please note how sets are named after the root name above.
dataref-collections:
+ -
+ name: cloud-layer#0
+ datarefs:
+ - sim/weather/aircraft/cloud_type[0]
+ set-dataref: data:cloud-layer-completed[0]
+ -
+ name: cloud-layer#1
+ datarefs:
+ - sim/weather/aircraft/cloud_type[1]
+ set-dataref: data:cloud-layer-completed[1]
+ -
+ name: cloud-layer#2
+ datarefs:
+ - sim/weather/aircraft/cloud_type[2]
+ set-dataref: data:cloud-layer-completed[2]
+ -
+
A dataref that is set to an incremental value each time the set is completed.
+In the above example, data:cloud-layer-completed[2]
local dataref will be set to an incremented value each time the set of four datarefs is completed, while the value of local dataref data:all-cloud-layers-completed
will be set to an incremented value when all three sets are completed.
++If a Dataref Collection is too large, it simply can be split into smaller Collections.
+
+A dataref can be part of multiple sets.
Datarefs in sets are not available through the Page. They must directly be accessed through the set in the Collector. The Collector is part of the Simulator.
+value = page.get_dataref_value(dataref_name)
+
value = simulator.collector.collections[collection_name].datarefs[dataref_name]
+
The Dataref Sets Collector fetches sets of datarefs one at a time.
+It is started by the Simulator.
+If no set needs updating, the Collector does nothing.
+If a set is loaded for update, the Collector regularly monitor its progress. When all datarefs in the set have been updated (the set is said to be completed), the Collector unloads the set from update and notifies the set's owner of completion. If some dataref in the set do not get updated for a while (timeout), the Collector temporary unloads the set and schedule another set for collection. Sets are scheduled randomly with a probability that increases over time to prevent starvation (very much like UNIX nice(1)).
+The Dataref Sets Collector is awaken every minute to check whether sets need updating.
The following resources are common to all buttons.
+Color can either be expressed by their name, as defined in the Python PILLOW package, or by a tuple of 3 or 4 values, representing red, green, blue, and optionally the transparency.
+All values should be in the [0..255] range. For colors, 0 is black, 255 is pure color; for transparency, 0 is transparent, 255 is opaque.
icon-color: (100, 40, 40, 200)
+ label-color: darkorange
+ text-color: mediumaquamarine
+
Cockpitdecks uses the same convention as python number to text formatting.
+Font files need to be placed in the deckconfig/resources/fonts
folder.
+Font files must be either Truetype fonts (TTF) or Opentype fonts (OTF).
+The name of the file is used to designate the font.
+Fonts are loaded on start up.
text-font: DIN Condensed Black.otf
+
Cockpitdeck comes with a few fonts appropriate for aeronautical use: Standard formal fonts like DIN, fancier fonts like LED fonts, icon fonts like font-awesome and weather-icon.
+For Truetype font, it is not necessary to add the .ttf
extension. For Opentype fonts it is necessary to add the .otf
extension.
Icon image files need to be placed in the deckconfig/resources/icons
folder.
+Image files must be either JPEG images (JPG, JPEG) or Portable Network Graphic (PNG).
The name of the file is used to designate the icon.
+Icons are loaded on start up, uniformly resized and cached for faster successsive starts.
+Typical icon size should be (square) 128 to 256 pixels.
Internally, Cockpitdeck use 256 pixel icons. Icons are resized to the deck requested size upon display.
+ icon: OFF_WHITE_FRAMED
+
Resources are in the deckconfig/resources
folder.
+A few wallpaper images are used for display on idle deck.
Documentation of the aircraft decks can be placed in the folder deckconfig/docs
or in the folder deckconfig/resources
in a textual form (including markdown), or as PDF.
All configuration files are Yaml formatted. Yaml is simple, structured, and readable.
+Yaml is loaded and interpreted by the python Yaml parser. Users must be aware that some keywords are sometimes interpreted by some parser. To prevent this interpretation, keywords should be placed between quotes.
+For example:
+variable: on
+will be interpreted as boolean value true.
variable: "on"
+will be interpreted as string on
.
The following keywords have been noticeably discovered:
+on, off, true, false, yes, no (all mapped to Boolean values True or False).
Cockpitdecks uses a Yaml 1.2 compliant parser (ruamel.yaml) that refuse those interpretation as describe in the Yaml 1.2 specifications.
+ + + + + + + + + + + + + +Cockpitdecks proceeds by starting autonomous threads of execution that monitor different aspects of the interaction of decks with X-Plane.
+In addition, each deck has its own, internal, mechanism to capture user interactions.
Cockpitdecks threads are often created in start() procedures and terminated in terminate() procedures.
+Most of the callback are executed directly from the caller. If a user presses a key, the device driver will detect it and execute a callback to excute the function. That callback directly execute the function which, often, consists of executing a command in X-Plane and refreshing the pressed key icon to reflect the new state.
+Sometimes, callbacks are executed indirectly. The callback function enqueues a request for action. In this case, a separate monitoring thread dequeues the request for action and does it.
A thread monitors datarefs by collecting them as they arrive on UDP port, compare each value with the previous one and fire a "value changed" event if detected.
+Each dataref maintains a list of buttons that use/rely on it, and each of those buttons gets notified of the change to adjust. When a button receives the message that one of its dataref has changed, it can adjust its internal state, and if it is currently rendered on a deck, adjust its display.
A thread permanently monitors the connection to X-Plane. When there is no connection, the thread attempt to initiate a new connection until it succeeds. When it created a new connection, it immediately request dataref updates and update all decks with all dataref values.
+If the connection breaks, it restarts its attempts to connect.
+When there is no connection to X-Plane, Cockpitdecks works as expected, however, no command get issued to X-Plane, and no dataref value gets collected, hence, no deck icon gets updated to reflect the state changes.
When a Page Reload is requested, the requesting button may be deleted during the process. To prevent this, some operations like Page Reload or Cockpitdecks Stop are not executed directly. They are enqueued in an execution queue, and performed by another, external thread that will survive at least as long as the execution of the process requires it. (For Cockpitdecks Stop function, it is actually the thread that will terminate all other thread and then commit suicide.)
+When a value can be used by numerous variants and propose a default value, all "parents" object will propose the value as default-...
. However, in the leaf object where the value is used, the default-
part disappears from naming:
+Deck or Page parent objects have default-icon-color
attribute, while leaf Button that actually use the icon color has icon-color
attribute.
It all started with simple annunciators! Most buttons are not static images but rather drawn on the fly(!) from attributes in their definition (text, options, sizes…) and dataref values. This allow for extreme flexibility. The basic, simple image processing/drawing package used (Python Pillow) is the limit. It allows for stylish glow and lightly readable display when the button is in its off state (called Korry style).
+Unstoppable after the design of annunciators, rotating switches and simpler push buttons where also created with drawings to replace static images, together with labels around them. It does not always appear like in the cockpit, but close enough and it does the work. But above all, it no longer is necessary to crop screen dump images and end up with a zillion icon images to reflect different states, or button positions, the price to pay is to adjust a few parameters in the definition of the button.
Datarefs whose name starts with local:
behave like any other datarefs but are neither forwarded to X-Plane, nor read from it. They can be set, read, etc. like any other datarefs allowing for a kind of inter-button communication: one button sets it, another one adjust its appearance based on it, even buttons on another deck!
Truly, the sky is the limit. Enjoy.
+The DrefCollector is an Activation meant to be used for collecting large amount of slow changing datarefs like, typically, weather information.
+Weather in X-Plane uses no less that 200 datarefs that could be fetched to provide information about the weather around the aircraft.
+The DrefCollector splits the large collection of dataref in batches of a limited size and fetch those datarefs batch after batch. Ultimately, when all batches have been fetched, the entire collection is ready to be used.
+The DrefCollector is monitored periodically for batches that do not get updated frequently.
+DrefCollector exposes all datarefs it fetched in a dref_collection
attribute.
The WeatherViewer is a Representation that uses all weather-related datarefs to provide weather information to pilots.
+(The Weather Viewer uses the DrefCollector activation.)
Cockpitdecks is designed to accommodate different deck types.
+To allow Cockpitdecks to manage a new deck type, two interfaces need to be provided.
A Deck is a physical device. It has
+brand
))model
)secret.yaml
file.Inside Cockpitdecks, a Deck has the following attributes:
+All buttons available for interaction are listed in a configuration file that enumerates all buttons, their possible interaction and display capabilities.
+Here is a configuration file for a Loupedeck LoupedeckLive device.
# This is the description of a deck's capabilities for a Loupedeck LoupedeckLive device
+#
+---
+type: loupedecklive
+brand: Loupedeck
+model: loupedecklive
+driver: loupedeck
+buttons:
+ - name: 0
+ action: push
+ view: image
+ image: [90, 90, 0, 0]
+ repeat: 12
+ - name: left
+ action: swipe
+ view: image
+ image: [60, 270, 0, 0]
+ - name: right
+ action: swipe
+ view: image
+ image: [60, 270, 420, 0]
+ - name: center
+ action: swipe
+ view: image
+ image: [360, 270, 60, 0]
+ - name: 0
+ prefix: e
+ action: encoder-push
+ view: none
+ repeat: 6
+ - name: 0
+ prefix: b
+ action: push
+ view: colored-led
+ repeat: 8
+
Note
+In this very special case, there will be a conflict because a portion of the screen is used twice: The center
screen correspond to the 12 push buttons. Deck should use either one but not both. If both remain activated, Cockpitdecks will warn about illegal use of center screen for button or the opposite. Example:
+set_key_image: key «center»: invalid index for center display, aborting set_key_image
+These warnings can safely be ignored. To suppress the warning, simply comment out the portion of unused buttons.
Name of the button.
+Interaction with the button. Interaction can be:
+none
: There is no interaction with the button. It is only used for display purpose.press
: Simple press button that only reports when it is pressed (one event)push
: Press button that reports 2 events, when it is pushed, and when it is released. This allow for "long press" events.swipe
: A surface swipe event, with a starting touch and a raise events.encoder
: A rotating encoder, that can turn both clockwise and counter-clockwiseencoder-push
: An encoder couple to a push button.cursor
: A linear cursor (straight or circular) delivering values in a finite range.Feedback ability of the button. Feedback visualisation can be:
+If the feedback visuallisation is an iconic image, the image
attribute specifies the characteristics of the image (size, and eventually, position on a larger surface.) X
is horizontal and correspond to the width
, Y
is vertical and correspond to the height
.
The result of a deck definition is the list of valid definitions for each button of that deck. This includes, for each button, its activation capabilities, its representation capabilities, and the list of valid index name to designate a precise button on the deck.
+Here is an excerpt of the meta data available in the definition of a button:
...
+'2':
+ index: '2'
+ _index: 2
+ action: push
+ view: image
+ activations:
+ - page
+ - reload
+ - inspect
+ - stop
+ - push
+ - longpress
+ - onoff
+ - updown
+ representations:
+ - icon
+ - text
+ - icon-color
+ - multi-icons
+ - multi-texts
+ - icon-animate
+ - side
+ - data
+ - annunciator
+ - annunciator-animate
+ - switch
+ - circular-switch
+ - push-switch
+ - ftg
+ - weather
+ image: [90, 90, 0, 0]
+...
+e0:
+ index: e0
+ _index: 0
+ action: encoder-push
+ view: none
+ activations:
+ - page
+ - reload
+ - inspect
+ - stop
+ - push
+ - longpress
+ - onoff
+ - updown
+ - encoder
+ - encoder-push
+ - encoder-onoff
+ - encoder-value
+ - knob
+ representations:
+ - icon
+ - text
+ - icon-color
+ - multi-icons
+ - multi-texts
+ - icon-animate
+ - side
+ - data
+ - annunciator
+ - annunciator-animate
+ - switch
+ - circular-switch
+ - push-switch
+ - ftg
+ - weather
+...
+slider:
+ index: slider
+ _index: 0
+ action: slider
+ view: none
+ activations:
+ - slider
+ representations:
+ - none
+...
+
The meta data is available in each individual button.
+The second interface provided for decks is the software necessary to:
+This require the coding of a bridge between Cockpitdecks and the API that controls the device.
+Currently, this require the coding of a single python class with the following functions:
+General:
+Interaction control:
+(in more recent versions of drivers, there sometimes is a callback function per interaction type: key_change_call_back, dial_change_callback, touch_callback...)
+Feedback:
+If the deck has image capabilities:
+If the deck has sound and/or vibrating capabilities:
+If the deck has lit button with color capabilities:
+If the deck has lit button without color capabilities:
+If the deck has lit button with several led capabilities (led ramps, etc.):
+The following functions are also necessary and can be overwritten if necessary.
+ def __init__(self, name: str,
+ config: dict,
+ cockpit: "Cockpit",
+ device = None):
+ def init(self):
+ def get_id(self):
+ def read_definition(self):
+ def get_button_value(self, name):
+ def set_defaults(self, config: dict, base):
+ def load_layout_config(self, fn):
+ def inspect(self, what: str = None):
+ def load(self):
+ def change_page(self, page: str = None):
+ def reload_page(self):
+ def set_home_page(self):
+ def load_home_page(self):
+ def make_default_page(self, b: str = None):
+ def get_index_prefix(self, index):
+ def get_index_numeric(self, index):
+ def valid_indices(self):
+ def valid_activations(self, index = None):
+ def valid_representations(self, index = None):
+ def key_change_callback(self, deck, key, state):
+ def key_change_processing(self, deck, key, state):
+ def print_page(self, page: Page):
+ def fill_empty(self, key):
+ def render(self, button: Button):
+ def start(self):
+ def terminate(self):
+
For deck with iconic display capabilities:
+ def get_display_for_pil(self, b: str = None):
+ def get_index_image_size(self, index):
+ def load_icons(self):
+ def get_icon_background(self, name: str, width: int, height: int,
+ texture_in, color_in, use_texture = True, who: str = "Cockpit"):
+ def create_icon_for_key(self, index, colors, texture, name: str = None):
+ def scale_icon_for_key(self, index, image, name: str = None):
+ def get_image_size(self, index):
+ def _send_key_image_to_device(self, key, image):
+
Cockpitdecks software has been organized in such a way that it could probably be used with other simulator software, provided some adaptation of course. Adaptation would be confined to the interaction of Cockpitdecks with the simulator software.
+Interaction from Cockpitdeck to simulator software:
+A few set of special buttons are dynamically drawn based on attributes.
+Attributes are numerous to allow for design flexibility, however default values will always provide a usable representation.
The idea of drawn buttons came after the flexibility discovered when designing Annunciators. All annunciators are drawn buttons: Texts, frames, basic icons…
+A Switch is a drawing of a two or three-way switch on an image key.
+Switches are often used by On/Off activations.
+They can be used in replacement of an icon.
Ticks are marks on the side of the switch to label corresponding positions. The tick underline is the visual line line that connect all ticks.
+ switch:
+ switch-style: 3dot
+ tick-underline: true
+ tick-label-size: 36
+ tick-label-font: DIN Bold
+ tick-labels:
+ - "ON"
+ - "MID"
+ - "OFF"
+ options: 3way,horizontal
+
Switches, Circular Switches, and Push Switches have numerous attributes in common to control their appearance. See Circular Switches for a list.
+options: 3way
+Defines a switch with 3 positions, 2 extremities, and one middle position.
options: horizontal
+Draws and manipulates the switch horizontally rather than vertically.
options: hexa
+Draws an hexagonal base to mimic Airbus switch inserts and fixation instead of a round base (default).
options: invert
+Inverts On and Off positions.
A Circular Switch is a rotating knob/switch used to represent a rotation switch. It is displayed on an image key. Circular switches are often used by Up/Down activation to cycle and bounce through the set of possible values.
+They can be used in replacement of multi-icons.
+ circular-switch:
+ switch-style: normal
+ down: 20
+ left: 20
+ tick-from: 135
+ tick-to: 315
+ tick-space: 20
+ tick-underline-width: 12
+ tick-color: red
+ tick-underline-color: red
+ needle-color: lime
+ needle-length: 130
+ tick-labels:
+ - "0"
+ - "1"
+ - "2"
+ - "3"
+ - "4"
+ - "5"
+
+![[circular-switches.png]]
button-size
button-color
button-off-color
witness-fill-color
witness-stroke-color
witness-stroke-width
A PushButton is a simple button that can be used to trigger a command. It can be On or Off, and it's state can be reflected graphically by adjusting its color for instance.
+Later…
+Knobs are circular rotating buttons used to set values by rotating the button clockwise or counterclockwise. Although they can be drawn and « turn » according to dataref values, they cannot currently be used with activations to trigger their rotation. Real, physical rotation knobs must be used instead. (Mimicking a rotation knob with a push button is a difficult task that requires awkward manipulations such as long pushes. We may later offer a possibility to allow for rotation knows on icon button, because the surface of some icon button (LoupedeckLive) reacts to touch and swipes. It would therefore be possible to detect precisely where the button was touched (left, right, up, center…) and assign activations accordingly.)
+So we shall just say that Knob icons can be used as simple push button, with an alternative representation.
A DataButton is a particular case of a display only button.
+A DataButton displays four informations:
+ - index: 4
+ name: Fuel Level
+ type: none
+ label: Fuel
+ label-size: 10
+ label-position: ct
+ data:
+ icon-name: "gas-pump"
+ data: 75.4256
+ data-format: "{:02.0f}"
+ data-font: DIN Condensed Light
+ data-size: 24
+ data-unit: "%"
+ data-progress: 100
+ data-trend: 0
+ dataref-rpn: ${sim/aircraft/fuel_level} 10 *
+ bottomline: Go Faster
+
Data button representation aims at providing a dashboard-like single value highlighted in a deck key image, very much like common web dashboards.
+Decor representation displays simple connected lines to populate unused icons. They can be used to display visual helper lines that connect annunciators (bleed air, hydraulics, etc.) The idea behind Decor icons is to provide a quick alternative to blank icons when filling large decks with numerous keys.
+Decor icon are governed by two parameters type
and code
. The type is a category of drawings. The code determine which drawing will be made in that category.
type: line
Decor icons of type line
display a single horizontal or vertical line, and corner angles. The code
determine which line get drawn.
type: line
+code: H
+
type: segment
Decor icons of type segment
display segments that are present in the code
attribute.
+
+For example:
+
type: segment
+code: BGNSIL0123
+
H
code in type line
above.
+width: 10
+Width of the line.
color: red
+Color of the line.
The aircraft representation displays the name of the aircraft (ICAO type designator) located in the dataref: sim/aircraft/view/acf_ICAO
. All 4 (or more) characters are fetched and displayed in the icon. (We currently limit fetching the first four characters only, which should be sufficient for ICAO aircraft code designator.)
The representation attribute is
+
aircraft:
+ text-font: B612-Bold
+ text-size: 32
+
If a set-dataref
is present, the aircraft representation increases the value of that dataref by one each time the aircraft name changes in the sim/aircraft/view/acf_ICAO
. This can be used by other button or by Cockpitdecks itself to be notified of an aircraft or aircraft model change.
(Please refer to the dedicated Weather Representation page.)
+The WeatherButton is a special data button that displays METAR information of the station closest to the aircraft in a small, iconic representation.
+ - index: 8
+ name: METAR
+ type: weather
+ station: OTHH
+
(To do. Cycle through forecast each time button is pressed.)
+X-Plane weather is flexible and proposed with several variant. We designed a few set of X-Plane specific button representation to present these data sets.
+Toliss Airbus Aircrafts A319, A320, A321, and A340 share numerous functions, with particularities or specialties. They share a common set of functions, displays, or dataref values. This has led to the development of very specific buttons representation.
+These buttons are highly specific and would probably not be usable in other aircrafts. However the very specific code used to produce these buttons is an example for alternative development.
+ + + + + + + + + + + + + +Some decks exhibit displays that are larger than a key with and iconic representation. Those displays often have touch and swipe capabilities. This led to design activations and representations specific to these larger displays to be used with your favourite flight simulation software.
+++Please note, for example, that the LoupedeckLive deck has a unique central display screen accepting touches and swipes. A plastic grid cover gives the illusion that there are two vertical side screens and 12 « keys » in the middle, but underlying is a unique 480 × 360 pixel screen. Each key is a 90 × 90 pixel portion of that screen.
+
Larger screens can be used in two different ways:
+In the later case, the specificity of the display is not apparent, and resulting buttons are treated as regular keys with iconic image display (with different sizes sometimes.)
+When considered as a single larger display, it is difficult to remain generic since each display will have special size, location, and behavior. Cockpitdecks buttons assigned to those specific display are therefore also very specific.
+Having no activation at all to use those display solely for displaying purposes is always an option. However simple activations can make the passive display a lot more enjoyable.
+For exemple, if the display is capable, touching or swiping the display can be used to change its content. On startup, display heading, swipe left, display speed, swipe right display heading, etc.
Touch is similar to button press activation and can be used as such.
+Swipe returns movement start and end position and timing. These values can be interpreted to model a limited set of movements like swipe left, right or up, down. Raw values can also be used as an increasing or decreasing sliding cursor.
+Given the sizes of each display, representations fitting those displays will always remain very specific.
+The highly specific Airbus FCU representation reproduces the central display with all possible modes.
+The Airbus FMA displays the five annunciators on top of the Primary Flight Display (PFD).
+There are two modes of display. The first one make use of a larger, horizontal display and shows all five annunciators next to each other. The second one use five keys with iconic display and show one annunciator on one key. In both cases, data necessary for display is fetched only once, the first annunciator being the master one with all data, other annunciators are slave ones and fetch their data from the master annunciator.
Airbus FMA display is a pure display with no activation associated with it.
+On LoupedeckLive decks, vertical displays exploit their proximity to the lateral encoder dials to present direct encoder feedback. For example, next to the QNH adjustment encoder, the current atmospheric pressure is displayed. Pushing the encode switches between Standard pressure and local ambiant pressure.
+Image or drawn icons (especially text messages) are also an alternative way to decorate those displays. One can imagine displaying ATC instructions on a tape display, with swipe actions to acknowledge messages.
+ + + + + + + + + + + + + +Isolate a framework that register and observe datarefs, make a better tool than NASA connector.
+Evolve towards a XPPython UDP library.
+When dataref(s) meet conditions, events are triggered.
+Usable for observation, data collection, even « co-pilot » type of interaction: if this then that.
+Better isolate activation / representation.
What about grouping all default- into a style*? Using one indirection like
+Normal-font=…
+Label-font=…
+Icon-background=…
+All these grouped into a style?
+May be provide default-airbus.Yaml, default-Boeing.Yaml?
+Style could simply be an includes of defaults.
Make a350/a380 type tick marks on rotating knobs. LED around knob
+Make a icon-builder app (electron?)
+Abstraction of command:
+Allow for « local » commands like change page, stop, inspect.
+Command has a list of optional/mandatory arguments, especially local commands.
+When executed, a command receive an instance of cockpit? Xplane? App?
Large displays: Gently pressing on a part of the display triggers FCU mode changes like Speed/Mach, Heading/Track, or even knobs push/pull (with long press). May be vertical swipes will increase/decrease values.
+Base idea: create a single « plugin » for all decks. Hide deck particularities, they all have buttons, encoders, led, iconic image…
+Base: extend wortelus idea to several deck types.
+Yaml is most readable, structured, text based config language.
+Target: make a XPPython3 plugin. (Cancelled, because some deck connector internals.)
+wortelus uses Streamdeck python package.
+Step one: make a similar package for each deck type/model: Loupedeck and XTouchMini.
+Issue: different techniques to access device: busy loop in connections and/or blocking io. Impossible to use in XPPython3 flight loops, or need to rewrite all those loops as flight loop: Too complicated.
+Workaround: Remain outside of simulator process, communicate with UDP
Add Saitek Panels (HIDAPI)
+Think « miniCockpit »
+Add OSC/MIDI relay type to be able to create cockpit in OSCTouch.
+Make electron app for icon design that spits out Yaml button definitions.
+Evolve towards library
+Behave similarly as TouchPortal
Should be easy for software developer.
+Installation not easy if not familiar with Python eco-system.
+Configuration through Yaml files.
+Need to hunt for datarefs and commands in X-Plane (using DataRefTool for example.)
To, From
+Dist from takeoff, ATD
+Dist to landing, ETA
+Metar at departure, TAF at Arrival
Fuel, 1 per tank
+Tire, landing gears
+Elec volt
+Hyd Pressure
+AirCo "flow"
+Oxy?
Cockpitdecks offers different types of Weather Representation, mainly on icons.
+These Representations, together with accompanying custom Activations, have led to development of highly customized activations and representations to exhibit the potentials of Cockpitdecks.
+While some Representations remain highly generic, like graphical representation of METAR at the closest station, some others are highly specific like those that represent X-Plane simulated weather.
+live-weather
+ station: LFBO
+ update: 30 # minutes
+
Reports the current live weather for the closest Metar location. (Closest to the current aircraft location.)
+real-weather
+ mode: region
+
Provides the Real weather currently installed into X-Plane in a short, Metar-like summary.
+This is done by fetching a limited set of values from the weather-related datarefs (temperature, pressure, wind, weather conditions...)
There are two modes: aircraft
and region
.
xp-weather
+ mode: region
+
Provides a detailed weather report from all weather-related datarefs.
+There are two modes: aircraft
and region
.
This representation fetches all weather-related datarefs from the simulator (wind layers, cloud layers, weather conditions, more than 100 datarefs) for a location or region and attempt to automagically generate a METAR from the collected data.
+To collect and monitor such an amount of datarefs, Cockpitdecks designed Dataref Sets.
+ + + + + + + + + + + + + +The interaction with X-Plane is two folds.
+When a button is activated, Cockpitdecks will either submit a command, or ask to change the value of a writable dataref, or both.
+It will also, optionally, execute another view
command. The purpose of the view command is to modify the focus proposed on the screen consecutively to the first command executed. For example, when the Status
ECAM button is pressed, the view
command changes to show the ECAM display.
To render an image or an icon on a deck key, Cockpitdecks will use the values of one or more datarefs and/or values internally kept by the button, like the number of times it was pressed.
+When Cockpitdecks create a new Button, it will collect all datarefs used by the button. It knows how to find them through the Activation and Representation attributes.
+The Page where the button is located will collect all datarefs of all buttons on that Page.
+When a Page is displayed on a deck, Cockpitdecks will ask X-Plane to periodically send the values of all datarefs used on that page.
+Cockpitdecks will periodically receive all dataref values, and when the value of a dataref has changed, all buttons that use the dataref will be notified of the change. The button can then handle the change, may be re-compute its value, and change its appearance accordingly.
+When a Page is unloaded from a deck, Cockpitdecks ask X-Plane to stop sending datarefs values for the datarefs the page uses. X-Plane may, however, continue to send the value of datarefs for other decks connected to it. A button may therefore receive notifications of dataref value changes, even if it is not currently displayed. Buttons will handle the change of value, including computations, but it will not render since it is not currently displayed on a key.
Alternatively, a button can also use values coming from other sources to render. Currently, buttons are able to use internal state values such as the number of times a button was pressed, or the number of times an encoder was turned clockwise.
+The weather button display the latest, current Metar of an airport. It is automagically updated every 30 minutes. It actually uses two datarefs (latitude and longitude of aircraft) to guess what is the closest Metar station. It is updated if the closest station changes, or every 30 minutes. (The refresh time is a parameter.)
+The Metar for the closest station is fetched from a remote server, hence the isolation of these types of buttons (that fetch values outside of X-Plane eco-system) from other, more common buttons.
+The TAF works in a similar way.
X-Plane connector through UDP uses the following threads of execution to permanently collect dataref values from X-Plane as requested by deck displays.
+The connect loop monitors the connection to X-Plane.
+If there is no connnection, if it cannot connect to X-Plane to submit a command, or if it does not receive any data periodically, the connect loop attempts to connect until it succeeds.
+When a new connection is established, the dataref collection loop is started and buttons get notified of dataref value changes.
+The connect loop is created and managed by the XPlaneBeacon
class.
The dataref collection loop permanently collects data from X-Plane and notifies buttons of dataref value updates.
+If it cannot connect to X-Plane, or if the data collection otherwise fails, a time out occurs.
+When several times out have occured, the collection process disconnects and terminates. (There is no need to monitor dataref values if we cannot collect them.) It will be restarted by the connect loop once a new connection is established.
+The dataref collection loop is created and managed by the XPlaneUDP
class.
The Simulator represent the simulator software and contains all procedures necessary for interaction with the Flight Simulation software.
+There currently is only one type of flight simulation software supported and it is Laminar Research X-Plane (release 12 onwards).
+(It is possible to create a new Simulator implementation for another software.)
X-Plane contains all interactions with X-Plane software.
+A few parameters are necessary in case Cockpitdecks cannot find X-Plane UDP Beacon on the local area network.
+Cockpitdecks permanently monitor the connection to X-Plane. If X-Plane is not started or not reachable, Cockpitdecks will regularly report the issue and continue trying to establish a connection to X-Plane.
+When a new connection is established, Cockpitdecks will ask the simulator to start sending necessary datarefs values and will start dataref change monitoring. (See below.)
+Cockpitdecks will continue monitoring the connection to X-Plane. If the connection is lost, for example if X-Plane is stopped, Cockpitdecks will notify all decks and Cockpitdecks will restart trying to establish a new connection until it succeeds. If there is no connection to X-Plane, there is no change of value of dataref that depends on X-Plane.
+Once a connection to X-Plane is established, Cockpitdecks will start monitoring required datarefs. Each time a dataref value has changed, all buttons relying on the value of that dataref will be notified of the change to, for exemple, adjust their appearance accordingly.
+++There is a maximum value of datarefs that can be requested from the simulator (50).
+
See Dataref Sets.
+When a button is turned or pressed, it often is necessary to issue a command to X-Plane. If a connection to X-Plane is established, Cockpitdecks will ask X-Plane to execute that command.
+If there is no connection to X-Plane, Cockpitdecks will report the command that should have been executed.
{"use strict";/*!
+ * escape-html
+ * Copyright(c) 2012-2013 TJ Holowaychuk
+ * Copyright(c) 2015 Andreas Lubbe
+ * Copyright(c) 2015 Tiancheng "Timothy" Gu
+ * MIT Licensed
+ */var Wa=/["'&<>]/;Vn.exports=Ua;function Ua(e){var t=""+e,r=Wa.exec(t);if(!r)return t;var o,n="",i=0,s=0;for(i=r.index;i