Skip to content

Commit

Permalink
Moved reference. Now adding code automatically also
Browse files Browse the repository at this point in the history
  • Loading branch information
devleaks committed Dec 22, 2024
1 parent 9a00dbe commit 769439f
Show file tree
Hide file tree
Showing 34 changed files with 197 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ In a nutshell, the representation of the *Mosaic* is built from the representati

# Deck Type Definition

Here is an example of definition of a mosaic for the LoupedeckLive left screen.
Here is an example of Deck Type definition of a mosaic for the LoupedeckLive left screen.

```yaml hl_lines="3 20"
- name: left
Expand Down Expand Up @@ -77,6 +77,10 @@ Here is an example of definition of a mosaic for the LoupedeckLive left screen.
- 30
```
In the above example, the left 60 × 270 pixel LCD screen will be split into 3 60 × 60 pixel icons with 30 pixels empty space between themselves.
### Other Examples
One Deck Type can define one or more mosaic for its large LCD displays. For example, a 800x100 pixel large LCD can propose a Mosaic of 4 x 200x100 pixels.
If a user prefers an alternate Mosaic of 8 x 100x100 pixels, it is necessary to create another Deck Type, with another name, where the alternate mosaic is expressed.
Expand Down
4 changes: 4 additions & 0 deletions docs/Cockpit.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ If you have more than one deck of the same type (i.e. two Streamdecks, two X-Tou
XPLive: AAA0000000000000000000A0000
```

> [!WARNING] Serial Numbers
> We experimentally noticed that serial numbers as displayed on the device and as reported by some software package do not always correspond. This also depends on the operating system. As a practical illustration, for HID devices, the request for its serial number throught HID specific protocol calls returns a value WA1234MHK0G, while the core operating system raw USB device probe returns A00WA1234MHK0G. Some device do not respond to serial number requests and in this case, an arbitrary software dependent value is returned, and not guaranteed to be unique(!).
> As a consequence, Cockpitdecks maintains a list of valid serial numbers for a given device.

# Resources

Resources are fonts, icons, other images, wallpapers, documentation, and texts used and related to that aircraft. All these elements are organized into the `resources` folder.
Expand Down
3 changes: 3 additions & 0 deletions docs/Extending/Development/API/activation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Activation

::: cockpitdecks.buttons.activation.activation
5 changes: 5 additions & 0 deletions docs/Extending/Development/API/deck.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Deck

::: cockpitdecks.deck
options:
show_inheritance_diagram: true
11 changes: 11 additions & 0 deletions docs/Extending/Development/API/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Cockpitdecks API

Here are the main Cockpitdecks entities meant to be extended by developers

- [`Representation`][representation]
- [`Deck`][deck]
- [`Deck Type`][resrouces.decktype] (Resource)
- [`Instruction`][instruction]
- [`Simulator`][simulator]

- [`Activation`][activation]
3 changes: 3 additions & 0 deletions docs/Extending/Development/API/instruction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Instruction

::: cockpitdecks.instruction
3 changes: 3 additions & 0 deletions docs/Extending/Development/API/representation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Representation

::: cockpitdecks.buttons.representation.representation
3 changes: 3 additions & 0 deletions docs/Extending/Development/API/resources/decktype.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Deck Type

::: cockpitdecks.decks.resources.decktype
3 changes: 3 additions & 0 deletions docs/Extending/Development/API/simulator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Simulator

::: cockpitdecks.simulator
2 changes: 2 additions & 0 deletions docs/Extending/Development/Adding Activations.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,5 @@ Its accompanying button definition:
```
When switch is moved to TEST, backlight is set to 100%, BTR sets it to 80%, and DIM to 30%.
# Activation API
2 changes: 2 additions & 0 deletions docs/Extending/Development/Adding Instruction.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,5 @@ Its accompanying button definition:
```
When button is pressed, the message *X-Plane rocks* is printed on the console.
# Instruction API
2 changes: 2 additions & 0 deletions docs/Extending/Development/Adding Representations.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,5 @@ type: push
specialty-icon:
param1: value
```

# Representation API
12 changes: 12 additions & 0 deletions docs/Extending/Development/Adding a Simulator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
To add a new simulator to Cockpitdecks, the developer has to create a new Simulator sub-class derived from `cockpitdecks.Simulator` (or one of its subclass).

```python hl_lines="3-4"
class SubLogicFlightSimulator(Simulator):

name = "A2FS1"

def __init__(self, cockpit, environ):

```

# Simulator API
44 changes: 44 additions & 0 deletions docs/Extending/Development/Internals/Activation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Activation occurs when a Button is requested to handle an Event.

A first step consists of the Activation preparation and initialization. This occurs when the deck is installed and each page created.

Initialization of the Activation will result in the creation of one or more Instructions. In the process, the Performer entity responsible for executing the Instruction is clearly identified. For example, CockpitInstruction are performed by the Cockpit entity, while SimulatorInstructions are executed by the simulator software.

The initialization of the Activation result in a global status is_valid() that returns True if the Activation contains all information necessary for handling events.

When the Button receives the event, it calls the activate() function on its activation, supplying the event.

```py
# In the Button class
def activate(self, event) -> bool:
result = self._activation.activate(event)
if result:
self.render()
else:
logger.warning("there was an issue handling the event")
```

Activate() functions return the status of the execution, True if all instructions were carried out without error.

The Activation activate() function always proceeds in similar patterns:

1. It first checks whether the Activation is capable of handling the event.
2. Depending on the event type, it executes one or more Instructions, collecting the result of the execution.
3. When all Instructions have completed, it returns a global status for the entire Activation.

Here is a pseudo-code that handles button press events:

```py
# In the Activation class
def activate(self, event: PushEvent) -> bool:
status = False
if not self.can_handle(event):
return False
if not super().activate(event):
return False
if event.pressed:
status = self.instruction.execute()
return status # Normal termination
```

From then on, the Button must decide what to do next, including if necessary regenerating its appearance.
10 changes: 10 additions & 0 deletions docs/Extending/Development/Internals/Data and Value Changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Cockpitdecks uses two types of value that can come from different sources:

1. **Data** are simple *scalar* typed values (mainly string, float or integer). They can either come from the simulator software or Cockpitdecks internal values.
2. **Value** are complex scalar typed values that depends on one or more **Data**. If the Value depends on more than one Data, a **Formula** is used to combined all Data together and ultimately provide a single final value.

Values are used by buttons and observables. Values are used when there is a need to combine and modify raw values as provided by the simulator or by Cockpitdecks.

Values are notified when one of its underlying Data has changed. This allows the Value to compute its new value. the Value in turn notifies the Button or the Observable that created it of its change. The Button or Observable can adjust as needed.

Changes of Data value enter Cockpitdecks through Events. The SimulatorEvent (or one of its sub-class) is used to report the change of a value in the simulator software. The CockpitEvent (or one of its sub-class) to report change of value in the Cockpit.
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ One, a gentleman approached me with questions about the configuration of a deck.

That, together with numerous code refactoring, abstractions, and conventions, lead to a flexible, configurable, autonomous application that now allow to use common deck models with X-Plane fight simulator. As an illustration of code refactoring, Cockpitdecks was first designed to work with X-Plane only, using X-Plane terminology of Datarefs, Commands, etc. Refactoring brought in a new abstractions for Simulator applications, with neutral generic terminology and allow now for different simulation software to be used with Cockpitdecks.

Cockpitdecks underwent numerous refactoring processes. Some basic, like name changes, some easy, like abstractions (insertion of intermediate often abstract classes), and some heavy (computer value from data with formula). But, through all these changes, the syntax of config.yaml files for buttons rarely changed. Vocabulary get richer because of addition of activations or representations, but older existing definitions kept working with minimal changes. Pages developed a year ago still work surprisingly well after all these internal changes!

Everything was created with fun and heart and is freely available to other to enjoy.

Towards the end, we added very basic straightforward user interfaces to interactively create buttons on web pages without coding. While the core functions are working as expected, a web user interface specialist could build a friendlier application from the feasibility rough cut we laid over. My knowledge of web user interface disappeared over time as things were getting highly specialised and refined. I’m sure there is room for a little svelt or vue application if someone is tempted by collaborating. (Backend already exists.) This web-based user interface would allow any one to design buttons, button pages and deck layouts to use with any simulation software. Next to that, built in extension mechanism allow developers to bring their own creations to Cockpitdecks.
Towards the end, we added very basic straightforward user interfaces to interactively create buttons on web pages without coding. While the core functions are working as expected, a web user interface specialist could build a friendlier application from the feasibility rough cut we laid over. My knowledge of web user interface disappeared over time as things were getting highly specialized and refined. I’m sure there is room for a little svelt or vue application if someone is tempted by collaborating. (Backend already exists.) This web-based user interface would allow any one to design buttons, button pages and deck layouts to use with any simulation software. Next to that, built in extension mechanism allow developers to bring their own creations to Cockpitdecks.

# See Also

Expand Down
51 changes: 51 additions & 0 deletions docs/Extending/Development/Internals/Rendering.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
Rendering occurs as follow.

Request to render always starts from the Button. The Button solely calls the procedure render() on itself.

To render a Page for example, the Page will call render() on each button in turn. It may then call a supplemental procedure to fill unused icons with images.

The Button render() call is quickly transferred to the Deck for specific rendering handling. So the Button asks the Deck to render itself:

```py
# In the Button class
def render(self) -> None:
self.deck.render(self)
```

From the button index, the Deck will deduce rendering possibilities. It will then ask the button to supply the data for the rendering.

```py
# In the Deck class
def render(self, button: Button) -> None:
button_representation = button.get_representation()
render_data = button_representation.render()
# transform render_data if necessary
# send it to device driver for handling (display, sound, coloring...)
self.device.handle_data(render_data)
```

In other words, the representation of the button is responsible to generate and provide whatever is necessary for the deck device driver.

Let us take a very practical example.

The deck device driver has a function to display an iconic image on a key. That function expects the index of the key to designate it unambiguously, and an image in JPG format with the proper size 90 × 90 pixels.

If we use a generic representation that produces an image, the resulting image will be a 256 × 256 pixel transparent PNG image. We need to convert and resize that image before we can send it to the device driver.

```
def render(self, button: Button) -> None:
brep = button.get_representation()
render_image = brep.render()
# transform render_data if necessary
keyicon = render_image.resize([90, 90]).convert("RGB")
# send it to device driver for handling (display, sound, coloring...)
self.device.set_key_image(key=button.inedx, image=keyicon)
```

This is a very simple example, but it shows the flow of information and the sequence of calls to get the work done.

To emit a sound, the representation render() function would be responsible for generating, for example, a sound file in WAV format. The deck render function would then pass that sound to the device driver play_sound() function that expects a sound file to play.

To color a LED, the representation render() function would be responsible for generating a color and a light intensity (in 0..1 value range). THe deck render function would then pass those data to the device driver turn_led_on(color, intensity) function to submit appropriate instruction to the device to turn the light on with the desired color and intensity.

People familiar with internet web development knowledge can follow the process for (Virtual) Web Decks. The device driver of Web Deck (called VirtualDeck) is a relatively straightforward JSON message generator and ultimately sends the message to the browser for display. In the browser, JavaScript process decodes the message and interpret it to display an image, play a sound, or refresh an entire page. (Communication occurs in a WebSocket channel.)
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ The other type of Simulator Instruction is a request to update a value made acce

The Maestro of Cockpitdecks is the Cockpit entity. Internal components are interchangeably called *Cockpitdecks* items or *Cockpit* items (word is shorter *!*).

## Cockpitdecks Data
## Cockpitdecks Internal Data

Cockpit or Cockpitdecks Data is an internal Cockpitdecks value mainly kept for statistical or introspection purposes. Button internal state is maintained inside a few Cockpitdecks internal data.
Cockpit or Cockpitdecks or simply Internal Data is an internal Cockpitdecks value mainly kept for statistical or introspection purposes. Button internal state is maintained inside a few Cockpitdecks internal data. (CockpitData, CockpitdecksData, InternalData are synonyms.)

End-users and Cockpitdecks developer can define and use internal cockpitdecks data. They all behave like simulator data, propagating changes to their listeners.

Expand All @@ -123,7 +123,7 @@ A Dataref is a simulator data inside the X-Plane flight simulator.

# SimVar

A SimVar is a simulator data from Flight Simulator. There are several types of SimVar. Please refer to the [Flight Simulator SDK](https://docs.flightsimulator.com/html/Introduction/SDK_Overview.htm) for more information.
A SimVar is a simulator data from Microsoft Flight Simulator. There are several types of SimVar. Please refer to the [Flight Simulator SDK](https://docs.flightsimulator.com/html/Introduction/SDK_Overview.htm) for more information.

# See Also

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
27 changes: 0 additions & 27 deletions docs/Extending/Development/Simulator.md

This file was deleted.

2 changes: 1 addition & 1 deletion docs/Extending/Extending Cockpitdecks.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ In addition of defining a new deck model, it might be necessary to add a new met

## New Simulator Software

Core class [[Simulator|Simulator]] can also be extended to connect Cockpitdecks to another simulation software. In this case, interaction models imposed by Cockpitdecks (datarefs, commands, UDP connection) inspired by the X-Plane flight simulator software may have to be adjusted as well.
Core class [[cockpitdecks-docs/docs/Extending/Development/Reference/Simulator|Simulator]] can also be extended to connect Cockpitdecks to another simulation software. In this case, interaction models imposed by Cockpitdecks (datarefs, commands, UDP connection) inspired by the X-Plane flight simulator software may have to be adjusted as well.

# Extensions Integration

Expand Down
12 changes: 12 additions & 0 deletions docs/Resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,18 @@ For Truetype font, it is not necessary to add the `.ttf` extension. For Opentype
> Fonts placed in the resources/fonts folder are available for images on decks. They are not necessarily available as « web fonts » available in web decks.
> To be available directly, not through Cockpitdecks generated images, web decks fonts have to be made available in the asset folder and referenced in proper CSS files.
Cockpitdecks provides the following licensed fonts in its distribution:
- D-DIN (4 variants),
- Overpass, especially Overpass Mono,
- Segment7Standard,
- Split flaps Skyfont and SplitFlap-TV,
- Icon fonts Font Awesome and weathericons.

The following fonts are recommended:
- B612
- DSEG: Original 7-segment and 14-segment fonts

Any Truetype or OpenType font can be added to Cockpitdecks.
# Icons

Icon image files available to all decks need to be placed in the `deckconfig/resources/icons` folder.
Expand Down
3 changes: 2 additions & 1 deletion docs/Running/Installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ In particular, the X-Plane Cockpitdecks Helper plugin uses and requires the late
Create a new python environment and activate it. In that environment, issue the pip install command:

```sh
pip install 'cockpitdecks[weather,demoext,streamdeck] @ git+https://github.com/devleaks/cockpitdecks.git'
pip install 'cockpitdecks[xplane,weather,demoext,streamdeck] @ git+https://github.com/devleaks/cockpitdecks.git'
```

### Cockpitdecks Extension Packages
Expand All @@ -41,6 +41,7 @@ Valid installable extension packages (between the `[` `]`, comma separated, no s

| Extra | Content |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `xplane` | Add X-Plane flight simulator. Mandatory if you want to use it with X-Plane flight simulator. |
| `weather` | Add special iconic representation for weather. These representations fetch information outside of simulation software. That's why it is not bundled with Cockpitdecks. Recommended. |
| `streamdeck` | For Elgato Stream Deck devices |
| `loupedeck` | For Loupedeck LoupedeckLive, LoupedeckLive.s and Loupedeck CT devices |
Expand Down
3 changes: 3 additions & 0 deletions docs/Running/Usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ In this mode, Cockpitdecks will start a single web deck. Head for the index web

![[demo-deck.png]]

> [!NOTE] NoSimulator
> If no simulator package is loaded, Cockpitdecks will start a dummy, empty simulator connector for its internal use. The above demonstration will be fully functional. Please note that if no specific deck package has been loaded, "hardware" reprensentation may not appear correctly on the emulated web decks.
## Normal Operations

There are two possible ways of working with Cockpitdecks:
Expand Down
Loading

0 comments on commit 769439f

Please sign in to comment.