The Common Demo Application Framework

All demo applications shipped with pyespargos are built on top of a shared common application framework, located in the demos/common directory of the repository. Instead of every demo re-implementing the same boilerplate (connecting to ESPARGOS devices, calibrating, collecting a CSI backlog, drawing a Qt/QML user interface), the framework provides these building blocks once, so that each demo only has to implement its own signal-processing and visualization logic.

If you write your own ESPARGOS application on top of the demo framework (the fastest way to get started is to copy and modify an existing demo), you get its features for free. This page describes the framework in general and, in particular, how it is configured through YAML configuration files and command-line options.

Structure

The framework is centered on the ESPARGOSApplication base class, which every demo subclasses. Optional functionality is added through mixins that a demo combines as needed:

  • ESPARGOSApplication: the base class. Handles command-line argument parsing, YAML configuration loading, QML engine setup, and creation and calibration of the ESPARGOS Pool.

  • BacklogMixin: adds a CSIBacklog and a settings panel for it (backlog size, stored CSI fields, packet filters).

  • CombinedArrayMixin: adds support for phase-coherent multi-board combined arrays (see Phase-Coherent Multi-Array Systems), including parsing of the array geometry and per-cable length compensation.

  • SingleCSIFormatMixin: adds selection of a single preamble format (L-LTF, HT20, HT40 or HE20) to work with.

A typical demo therefore starts like this:

from demos.common import ESPARGOSApplication, BacklogMixin, SingleCSIFormatMixin

class EspargosDemoPhasesOverSpace(BacklogMixin, SingleCSIFormatMixin, ESPARGOSApplication):
    ...

Beyond configuration, the framework also provides a graphical pool drawer for connecting to and calibrating ESPARGOS devices at runtime, so many settings can additionally be changed interactively from the user interface while a demo is running. The remainder of this page focuses on how a demo is configured before it starts, from configuration files and the command line.

Configuration Overview

Every demo is configured from a single nested configuration dictionary that is assembled, in order of increasing precedence, from three sources:

  1. Built-in defaults: sensible defaults defined by the framework and by the individual demo.

  2. A YAML configuration file, loaded with -c/--config.

  3. Command-line option overrides, passed with -o/--option.

Later sources are deep-merged on top of earlier ones: a source only needs to specify the keys it wants to change, and all other keys keep their previous value. The configuration is grouped into top-level sections:

  • pool: which ESPARGOS devices to connect to (hosts) and how to operate them: WiFi channel, calibration behavior, RF switch, receiver/FFT gain, MAC filtering, and so on.

  • backlog: CSI backlog settings, i.e., size, which CSI fields to store (lltf, ht20, ht40, he20), and packet filters (e.g. exclude_11b). Only relevant for demos using BacklogMixin.

  • combined-array: the geometry of a phase-coherent multi-board array. Only relevant for demos using CombinedArrayMixin (see Phase-Coherent Multi-Array Systems).

  • generic: framework-wide application settings, such as preamble_format and kiosk_mode.

  • app: reserved for settings specific to the individual demo.

To see the complete list of configuration keys and their default values for any demo, run it with --help. The bottom of the help output lists every available option, for example:

Configuration options for -o/--option (as CLI arguments) or -c/--config (as YAML file):
  backlog:
    backlog.size: default: 20
    fields:
      backlog.fields.lltf: default: true
      backlog.fields.ht20: default: false
      ...
  pool:
    pool.hosts: default: []
    pool.channel: default: 13
    ...
  generic:
    generic.preamble_format: default: 'auto'
    generic.kiosk_mode: default: false
  app: default: {}

YAML Configuration Files (-c/--config)

A configuration file is a YAML document whose top level is an object (dictionary) with the same section structure as above. It is loaded with the -c (or --config) argument and merged on top of the defaults, so you only need to include the sections and keys you actually want to override.

The most common reason to use a configuration file is to describe a combined array, because its geometry is too complex to express on the command line. Ready-made example configuration files ship in the config directory of the repository:

  • config/single-espargos-one.yml: a single ESPARGOS One board in its default orientation.

  • config/aperture-kit-6x4.yml: a phase-coherent large-aperture 6 × 4 array built from three boards.

For example, config/single-espargos-one.yml describes a single board:

combined-array:
  boards:
    espargosone:
      host: 192.168.1.2
      cable:
        length: 0.0
        velocity_factor: 0.76

  array:
    - - "espargosone.0.0"
      - "espargosone.0.1"
      - "espargosone.0.2"
      - "espargosone.0.3"
    - - "espargosone.1.0"
      - "espargosone.1.1"
      - "espargosone.1.2"
      - "espargosone.1.3"

Here, the boards section maps a freely chosen board name to its network host and the properties of its reference-signal cable (used for phase compensation, see Phase-Coherent Multi-Array Systems). The array section is a matrix that lays out the antennas physically: each entry "<board>.<row>.<column>" refers to one antenna of one board and its position in the matrix corresponds to its physical position in the combined array.

To run a demo with a configuration file:

./demos/combined-array/combined-array.py -c config/single-espargos-one.yml

A configuration file is of course not limited to the combined-array section; any configuration key may be set in it, for example:

pool:
  channel: 6
  secondary_channel: 2
  gain:
    automatic: false
    rx_gain_value: 40
backlog:
  size: 64
generic:
  kiosk_mode: true

Overriding Options on the Command Line (-o/--option)

Individual configuration options can be set directly on the command line with -o/--option, without editing or creating a configuration file. Each override has the form -o KEY=VALUE, where KEY is the dotted path to a configuration key and VALUE is the new value. Overrides are applied on top of both the built-in defaults and any configuration file loaded with -c, so they always take precedence.

  • The key is a dotted path into the nested configuration. For example, generic.kiosk_mode refers to the kiosk_mode key inside the generic section, and pool.gain.rx_gain_value refers to rx_gain_value inside gain inside pool.

  • The value is parsed as YAML, so its type is inferred automatically: true/false become booleans, 32 an integer, 3.5 a float, null becomes None, and anything else a string. Lists work too, e.g. pool.hosts=[192.168.1.2,192.168.1.3].

  • Multiple -o options are allowed; each sets one key, and they are applied left to right.

For example, to run a demo in kiosk mode, on WiFi channel 6, with a fixed receiver gain:

./demos/instantaneous-csi/instantaneous-csi.py 192.168.1.2 \
    -o generic.kiosk_mode=true \
    -o pool.channel=6 \
    -o pool.gain.automatic=false \
    -o pool.gain.rx_gain_value=40

-o and -c combine naturally: load a base configuration from a file, then tweak individual keys for a single run without modifying the file:

./demos/combined-array/combined-array.py -c config/aperture-kit-6x4.yml -o backlog.size=100

Convenience Command-Line Arguments

For the most frequently used settings, the framework also provides dedicated command-line arguments as shortcuts, so you do not have to spell out the full configuration key. Which of these are available depends on the mixins a demo uses; run the demo with --help to see its exact set of arguments.

  • Device hosts (positional argument): for demos that operate on plain, independent arrays, a comma-separated list of host addresses sets pool.hosts, e.g. instantaneous-csi.py 192.168.1.2,192.168.1.3.

  • -s/--single-array HOST (with CombinedArrayMixin): a shortcut that auto-generates a single-board combined-array configuration for the given host, so you do not need a configuration file just to run a combined-array demo on one board.

  • -b/--backlog-size N (with BacklogMixin): sets backlog.size.

  • --lltf / --ht20 / --ht40 / --he20 (with SingleCSIFormatMixin): restrict the demo to a single preamble format (generic.preamble_format). Without any of these flags, the format is chosen automatically.

Note

These shortcuts and the corresponding configuration keys control the same underlying settings. For the handful of settings that have a dedicated argument (device hosts, single-array layout, backlog size and preamble format), prefer the dedicated argument; use -c and -o for everything else.