ELARA Python API
The LuxWave ELARA API is a Python client library for communicating with the ELARA Server, a high-performance RF channel emulator. Control RF inputs/outputs, configure channel impairments (delay, Doppler, noise), stream scenarios, and retrieve monitoring data over the connection.
Installation
The ELARA API needs 64-bit Python 3.10 or later, on Windows (x64) or Linux (x86_64).
If you have the earlier package
Earlier versions of the API were installed as elara_python. If you have it, remove it first,
before you install luxwave. If you do not have it, go on to Install with pip.
Scripts written for the earlier package keep running; new scripts import from luxwave, as
shown under Import below.
elara_python was installed for all users
(from an administrator prompt on Windows, or with sudo on Linux), it has to be removed the same
way: run pip uninstall elara_python from an administrator prompt or with sudo (or
run the install script once that way, see Install offline), then install normally.
Installed luxwave before you removed elara_python? Removing
elara_python then also removes part of luxwave, and import luxwave
fails. Install luxwave again over itself:
Offline, run the install script again instead (see Install offline).
Install with pip
With internet access, install the API from a terminal:
This installs the API, and nothing else, into the Python that runs your scripts or, when a virtual environment is active, into that environment.
Install offline
Without internet access, take the wheel files and the install script from the Toolkit's download card for
the Python API. Put them in one folder and, from that folder, run install_python.bat on
Windows, or bash install_python.sh on Linux:
The script installs the API into the Python that runs your scripts or, when a virtual environment is
active, into that environment. It takes the wheel that fits that Python and stops with a message, before
installing or removing anything, if none does. If that Python has the earlier package
elara_python, the script removes it first. It ends by printing the installed API version.
Import
Check your API version
The installed API version is available as the standard package attribute:
Network
The API signs in over HTTPS (port 443) to the LuxWave login service, auth.luxwave.lu, and
connects to the ELARA Server through the board's own ports. A proxy or firewall between this computer and
either must let them through. If the login service cannot be reached, the constructor raises a
ConnectionError that says so.
Ensure the ELARA Server process is reachable on the target host before connecting.
Quickstart
Use Case
A common use case for the ELARA Python API is automated channel emulation testing: a test script connects to the ELARA hardware, configures the RF front-end to match the frequency plan of the device under test (DUT), then uploads a time-varying sequence of impairments (multipath delay, Doppler shift, and additive noise) so the DUT experiences a controlled, repeatable radio environment without any actual over-the-air propagation.
The script below models this workflow end-to-end. It configures one input and two output ports, generates 1 000 impairment steps where delay ramps from 10 ms upward and Doppler increases linearly, uploads those steps to channel 0, fires the scenario, captures monitoring data to verify the hardware is running correctly, then stops everything cleanly. This pattern can be extended for multi-channel, long-duration, or parametric sweep tests simply by adjusting the impairment generation loop.
How the code works, step by step
Step 1: Connect & authenticate
ELARA(host, username, password) is the only constructor. It first validates
your LuxWave account credentials. If they are correct,
it connects to the ELARA Server. The constructor finishes by
loading the current hardware state into api.inputs,
api.outputs, api.channels, and api.system_settings
from the live hardware state, so your script always starts with an up-to-date view of the
device without a separate query.
Step 2: Configure RF ports
The ELARA hardware has physical RF input and output ports identified by zero-based indices.
update_inputs() and update_outputs() each accept either a single
object or a list, so both a single port and multiple ports can be updated in one call.
The server stores the new carrier frequency and alias, and the method also updates the
corresponding entry inside api.inputs / api.outputs so subsequent
ChannelConfigInput / ChannelConfigOutput references stay
consistent. Frequency values are clamped to the hardware limits
(api.system_settings.limit_input_frequency_minimum_hz /
…maximum_hz) before transmission.
Step 3: Build the impairment timeline
A scenario is a time-ordered list of ChannelConfig objects. Each object
describes the channel impairments to apply for one hardware tick: delay, Doppler shift,
additive noise, input routing, and output routing. Building this list in Python gives you
full numeric control: you can use linspace ramps, pre-recorded traces, or lookup tables
from a propagation model. In the example, a simple linear ramp is constructed with a
list comprehension. The interval between steps is 10ms. For example, a scenario of 1000
steps will run for 10 seconds before looping back to the start.
ChannelConfigInput links a source RFInput port to the channel
and adds an attenuation value (dB). ChannelConfigOutput similarly links a
destination RFOutput and can optionally carry geographic coordinates
(lat, lon, alt) for geo-tagged emulation scenarios.
Step 4: Upload the impairment list
set_channel() sets the human-readable display name for the channel.
set_channel_impairments() replaces any previously loaded impairment steps
for that channel with the new list. For larger scenarios the upload may take a few
seconds. An optional progress_callback(sent, total) argument lets you
display upload progress in long-running scripts.
Step 5: Start the scenario
start_scenario() accepts a ChannelStart (or a list for
synchronised multi-channel starts). start_index selects the first step to
apply (useful for resuming mid-scenario). Pass ScenarioMode.PLAY_ONCE
to play the scenario once from start_index to the last step; the hardware
then resets to step 0 and the channel transitions to IDLE automatically.
Step 6: Read monitoring data
fetch_monitoring() captures a live I/Q snapshot at the DAC output.
The returned Monitoring
object contains parallel arrays: i_samples / q_samples for the
complex baseband signal, delays / dopplers / noise_levels
for the active impairment values at the capture instant, and config_steps
for the step index that was running on each captured sample.
Step 7: Stop and disconnect
stop_scenario() halts scenario playback immediately. The impairment steps
remain on the server and can be restarted without re-uploading. close()
closes the connection. Always call
close() at the end of your script to release the server-side connection slot.
Multi-client state synchronisation
When multiple clients connect to the same ELARA board simultaneously, a frequency
change made by one client is not automatically broadcast to the others. Use
fetch_input() or fetch_output() to poll the server for
the latest port state at any time:
fetch_input() or fetch_output() refreshes
all ports in the local cache.
Subsequent reads of api.inputs and api.outputs reflect the
latest server state without an additional network round trip.
progress_callback to set_channel_impairments():
lambda sent, total: print(f"{sent/total*100:.0f}%").
The callback is invoked periodically as steps are uploaded.
ELARA(host, username, password, force_logout, board_name)
Creates a new ELARA client instance. On construction, the client authenticates the user against the LuxWave account system, connects to the ELARA Server, and synchronises local state (inputs, outputs, channels, system settings) from the server.
Parameters
| Name | Type | Description |
|---|---|---|
| hostrequired | str | IP address or hostname of the machine running the ELARA Server (e.g. "192.168.1.10" or "127.0.0.1"). |
| usernamerequired | str | Your LuxWave account username. |
| passwordrequired | str | Password associated with the username. |
| force_logoutoptional | bool | When True, any existing active session for this user is forcibly evicted and the new session takes over immediately. Default: False. If an active session exists and force_logout is False, a PermissionError is raised. |
| board_nameoptional | str | Names the subscription the board takes on its first connection (see Board lock). The name must be 1 to 40 characters once leading and trailing whitespace is trimmed, with no control characters such as a tab or a line break and no lone surrogates (U+D800 to U+DFFF); otherwise a ValueError is raised before anything connects. Default: None. Without it, the subscription keeps a name your administrator gave it, or gets a suggested name such as Board 2, and then a warning gives its number and name. On later connections of the same board the name is not changed. |
Instance Attributes (populated after construction)
| Attribute | Type | Description |
|---|---|---|
| inputs | list[RFInput] | RF input ports reported by the server. Each element is an RFInput with fields index, name, alias, frequency_mhz. Refreshed on construction and by fetch_input(). |
| outputs | list[RFOutput] | RF output ports reported by the server. Each element is an RFOutput with fields index, name, alias, frequency_mhz. Refreshed on construction and by fetch_output(). |
| channels | list[Channel] | Channels available on the hardware. Each element is a Channel with fields index, name, cable_con_loss_db, scenario_mode. Refreshed on construction and by any fetch_* call. |
| system_settings | SystemSettings | Hardware capabilities and parameter limits from the server. See SystemSettings for the full field list (frequency limits, delay limits, calibration values, converter settings, etc.). Populated on construction. |
board_name is not a string of 1 to 40 characters without control characters or lone surrogates. Raises ConnectionError if this computer cannot reach the LuxWave login service, or the service answers that it is temporarily unavailable (see the network the API needs under Installation). Raises PermissionError if there is no active subscription, if another session is already active (force_logout=False), if the board is refused because none of your subscriptions of the package it runs is locked to it and none is free (see Board lock), if the board could not be recorded on a free subscription (try again), or if your account is locked to a different computer (see Node lock). A refused board's message lists your subscriptions of that package by number and name, for example
"All 4 subscriptions for ZCU111_ExtClk are in use on other boards: S-135 Lab A, S-136 Lab B, S-137 Rack 2, S-138 Board 4. Ask your administrator to free one."
PermissionError with the message
"This account is locked to a different computer." If that happens, ask your
administrator to reset the node lock for your account.
The Python API and the MATLAB API share a single lock, so both must be run from the same computer.
Each subscription has a number, such as
S-137, and a name. The name is set when
a board first connects with the subscription: the board_name you pass; without
it, the name the subscription already has (your administrator gave it one, or it kept its
name when its board lock was reset); otherwise a suggested name such as Board 2,
and a warning tells you the number and the name. After that first connection, only an
administrator can rename a subscription.
When every subscription of that package is locked to another board, the constructor raises a
PermissionError whose message lists them by number and name. If that happens,
ask your administrator to reset a board lock or to add a subscription.
If a free subscription cannot be recorded for the board, for example because the connection to LuxWave dropped, the board is not let in: the constructor raises a
PermissionError with the message
"The LuxWave login service is temporarily unavailable. Please try again."
Connecting again is safe; if it keeps happening, contact your administrator.
close() and
stop_monitoring() raises a PermissionError with the message
"Your subscription for package 'ZCU111_ExtClk' has ended or no longer covers this board. Please contact your administrator."
The API also prints this message when it happens, through Python's standard logging
module (logger 'luxwave_api', shown on stderr unless your script configures logging),
so a script that only receives monitoring updates sees why they stopped.
When the check cannot reach LuxWave for 10 minutes in a row, the same happens, with the message "Your subscription for package 'ZCU111_ExtClk' could not be checked for 10 minutes. Please check your connection to LuxWave; if this keeps happening, contact your administrator."
To continue once the subscription is renewed, call
close() and connect again
with a new ELARA(...), or connect again with force_logout=True.
Example
connect()
Opens the connection to the ELARA board. This is called automatically during construction and does not need to be called manually unless reconnecting after a close().
close()
Closes the connection to the ELARA Server. Always call this when you are done to release the connection resource.
Example
update_inputs(inputs)
Sets the carrier frequency (and optional alias) for one or more RF input ports. Values are clamped to the hardware limits defined in SystemSettings before being applied.
Parameters
| Name | Type | Description |
|---|---|---|
| inputsrequired | RFInput | list[RFInput] | A single RFInput or a list of them. Each object must have a valid index matching an existing input port. Only frequency_mhz and (optionally) alias are applied. |
frequency_mhz is outside the hardware
range [limit_input_frequency_minimum_hz / 1e6,
limit_input_frequency_maximum_hz / 1e6] it is silently clamped to the
nearest boundary.
Example
update_outputs(outputs)
Sets the carrier frequency (and optional alias) for one or more RF output ports. Values are clamped to the hardware limits defined in SystemSettings.
Parameters
| Name | Type | Description |
|---|---|---|
| outputsrequired | RFOutput | list[RFOutput] | A single RFOutput or a list. Each object's index must match an existing output port. |
Example
set_channel(channels)
Sets the display name for one or more channels.
Parameters
| Name | Type | Description |
|---|---|---|
| channelsrequired | Channel | list[Channel] | One or more Channel objects. index must match an existing hardware channel. name is applied. |
Example
set_channel_impairments(channel_index, channel_impairments, progress_callback)
Uploads a list of ChannelConfig steps to a specific channel. The server's existing impairment list for that channel is cleared first, then the new list is uploaded.
All impairment values (delay_ms, doppler_hz, noise_dbm,
attenuation_db) are clamped to hardware limits before being applied. The noise
has its own rules, because ELARA's noise is always on: a step with noise_enable=False
runs at the channel floor (see noise_floor_dbm()). If its
noise_dbm is not a finite number, it is sent with the floor as its level. With
noise_enable=True, a noise_dbm below limit_noise_minimum_dbm
is raised to the minimum and one above limit_noise_maximum_dbm is lowered to the
maximum. A level that is not a finite number (such as nan) gets the channel floor:
the step is sent with noise_enable=False and the floor as its level. The floor is
for switching the noise off, the minimum for a level you set, so a channel's floor may be below
the minimum. The API reports these steps in its
noise warnings. Reading the channel back with
fetch_channel_impairments() returns the steps as sent;
monitoring shows the delivered levels. On an older board that does not
report noise floors, noise_enable=False switches the noise off,
limit_noise_minimum_dbm takes the place of the floor, and noise_enable
is sent as given.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| channel_indexrequired | int | Zero-based index of the target channel. | |
| channel_impairmentsrequired | list[ChannelConfig] | ChannelConfig | The complete ordered list of impairment steps. step_number is automatically assigned by position in the list. On the fast upload, every step uses the first step's inputs and outputs, in any order. |
|
| progress_callbackoptional | Callable[[int, int], None] | None | Called periodically as steps are uploaded. Receives (sent: int, total: int). Useful for showing upload progress. |
Example
progress_callback to track progress
in long-running uploads.
ValueError naming the channel and the step. Nothing is sent, and the
steps are left as they were passed. For example, when the third step of channel 3 adds an input,
the error reads:
CH3 row 2 (step_number 2) routes Rx_0, Rx_1 -> Tx_2, but the scenario routes Rx_0 -> Tx_2 (row 0, step_number 0); a channel's inputs and outputs stay the same within one scenario; nothing sent
On a board without the fast upload, the steps are sent as given.
set_channel_impairments() logs one line per kind, never one per step, before the
upload starts. The lines go through Python's standard logging module,
logger 'luxwave_api', and are printed on stderr unless your script configures
logging. The four kinds read like this (the first only on a board that reports noise floors):
ELARA channel 3: 100 of 120 steps ask for noise off; ELARA's noise is always on, so they get the channel floor, -90.0 dBmELARA channel 3: 12 of 120 steps ask for less noise than the minimum (lowest -95.0 dBm); set to -90.0 dBmELARA channel 3: 5 of 120 steps ask for more noise than the maximum (highest -20.0 dBm); set to -30.0 dBmELARA channel 3: 3 of 120 steps ask for a noise level that is not a finite number; set to the channel floor, -90.0 dBm
To send them elsewhere, configure logging as usual, for example
logging.basicConfig(filename="elara.log"). To silence them:
logging.getLogger('luxwave_api').setLevel(logging.ERROR).
noise_floor_dbm(channel_index)
Returns a channel's noise floor in dBm. ELARA's noise is always on: a step with
noise_enable=False runs at the channel floor, and so does a noise_dbm
that is not a finite number. The floor may be below limit_noise_minimum_dbm: a
level you set with noise_enable=True is held between the noise minimum and maximum,
whatever the floor. Each channel has its own floor. It comes from the board settings received
when the session was opened; nothing is sent to the board.
Parameters
| Name | Type | Description |
|---|---|---|
| channel_indexrequired | int | Zero-based index of the channel, as in set_channel_impairments(). |
float, the channel floor in dBm, or None when the
board does not report noise floors. On such an older board, noise_enable=False
switches the noise off.
Example
fetch_channel_impairments(channel_index, progress_callback)
Reads back the complete impairment configuration currently stored on the server for a given channel. Returns an ordered list of ChannelConfig objects.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| channel_indexrequired | int | Zero-based index of the channel to read from. | |
| progress_callbackoptional | Callable[[int, int], None] | None | Called periodically as steps are retrieved, with (received, total). |
list[ChannelConfig], the ordered list of impairment steps
stored on the server for the specified channel.
Example
fetch_monitoring(index)
Requests a live I/Q snapshot at the DAC output from the ELARA hardware. Returns I/Q samples, delays, Dopplers, noise levels, and the associated configuration step indices.
Parameters
| Name | Type | Description |
|---|---|---|
| indexrequired | int | Output port index to monitor (0-based). |
Monitoring, an object containing
i_samples, q_samples, delays, dopplers,
noise_levels, and config_steps.
Example
start_monitoring(index, callback, interval_s, monitoring_type)
Starts a continuous monitoring stream instead of one-shot
fetch_monitoring() polling. The board pushes a
monitoring snapshot at a fixed rate; each snapshot is passed to your optional
callback and cached for get_latest_monitoring(). Call
stop_monitoring() to end the stream.
Parameters
| Name | Type | Description |
|---|---|---|
| indexrequired | int | Output port index to monitor (0-based). |
| callback | callable | Called as callback(Monitoring) for each snapshot. Optional. |
| interval_s | float | Requested push interval in seconds (default 0.05). |
None. Snapshots arrive via callback and
get_latest_monitoring(), which returns the most recent
Monitoring (or None until the first arrives).
Example
fetch_input(index)
Fetches the latest server state for the specified RF input port and returns the matching
RFInput. Also refreshes api.inputs,
api.outputs, and api.channels.
Parameters
| Name | Type | Description |
|---|---|---|
| indexrequired | int | Zero-based index of the input port to fetch. |
RFInput, the current server state for the port,
including the latest frequency_mhz. Returns None if no port with that index exists.
fetch_input(), api.inputs,
api.outputs, and api.channels all reflect the latest server state.
Example
fetch_output(index)
Fetches the latest server state for the specified RF output port and returns the matching
RFOutput. Also refreshes api.inputs,
api.outputs, and api.channels.
Parameters
| Name | Type | Description |
|---|---|---|
| indexrequired | int | Zero-based index of the output port to fetch. |
RFOutput, the current server state for the port,
including the latest frequency_mhz. Returns None if no port with that index exists.
fetch_output(), api.inputs,
api.outputs, and api.channels all reflect the latest server state.
Example
start_scenario(channel_starts)
Starts scenario playback on one or more channels. The scenario engine begins
iterating over the uploaded impairment steps from the specified
start_index.
Parameters
| Name | Type | Description |
|---|---|---|
| channel_startsrequired | ChannelStart | list[ChannelStart] | One or more ChannelStart objects specifying the channel index, starting step, and desired ScenarioMode. |
Example
stop_scenario(channel_stops)
Stops scenario playback on one or more channels immediately.
Parameters
| Name | Type | Description |
|---|---|---|
| channel_stopsrequired | ChannelStop | list[ChannelStop] | One or more ChannelStop objects identifying the channels to stop. |
Example
RFInput
Represents an RF input port on the ELARA hardware.
| Field | Type | Default | Description |
|---|---|---|---|
| index | int | 0 | Zero-based hardware port index. Used to reference this input in other calls. |
| name | str | "" | Hardware port name (read-only, populated from server). |
| alias | str | "" | User-defined label for the port. |
| frequency_mhz | float | 0.0 | Carrier frequency in MHz. |
RFOutput
Represents an RF output port on the ELARA hardware. Fields are identical to RFInput.
| Field | Type | Default | Description |
|---|---|---|---|
| index | int | 0 | Zero-based hardware port index. |
| name | str | "" | Hardware port name (from server). |
| alias | str | "" | User-defined label. |
| frequency_mhz | float | 0.0 | Carrier frequency in MHz. |
Channel
Represents a logical channel connecting one or more RF inputs to one or more outputs through the emulation pipeline.
| Field | Type | Default | Description |
|---|---|---|---|
| index | int | 0 | Zero-based channel index. |
| name | str | "" | Human-readable channel label. |
| scenario_mode | ScenarioMode | IDLE | Current playback state (read-only, from server). |
| current_step | int | 0 | Index of the step currently being played (read-only). |
ChannelConfig
Defines a single scenario step: a snapshot of all impairment parameters to apply to a channel at a given point in time.
| Field | Type | Default | Description |
|---|---|---|---|
| step_number | int | 0 | Playback order index. Automatically assigned by position when using set_channel_impairments(). |
| delay_enable | bool | False | Whether delay impairment is active for this step. |
| delay_ms | float | 0.0 | Propagation delay in milliseconds. Clamped to hardware limits. |
| doppler_enable | bool | False | Whether Doppler frequency shift is active. |
| doppler_hz | float | 0.0 | Doppler frequency shift in Hz. Clamped to hardware limits. |
| noise_enable | bool | False | True: the noise runs at noise_dbm. False: the noise runs at the channel floor (see noise_floor_dbm()); ELARA's noise is always on. On an older board that does not report noise floors, False switches the noise off. |
| noise_dbm | float | 0.0 | Noise power level in dBm, used when noise_enable is True. A finite level is held between limit_noise_minimum_dbm and limit_noise_maximum_dbm: a lower one is raised to the minimum, a higher one lowered to the maximum. A level that is not a finite number, such as nan or an infinity, gets the channel floor, which may be below the minimum; noise off gives the channel floor too. |
| inputs | list[ChannelConfigInput] | None | Per-input attenuation and position metadata for this step. |
| outputs | list[ChannelConfigOutput] | None | Per-output position metadata for this step. |
ChannelConfigInput
Per-input parameters for a single ChannelConfig step, including attenuation and spatial position.
| Field | Type | Default | Description |
|---|---|---|---|
| input | RFInput | None | Reference to the RF input port this entry applies to. |
| attenuation_db | float | 0.0 | Signal attenuation applied to this input (dB). Clamped to hardware limits. |
| lat | float | 0.0 | Geographic latitude of the emitter (decimal degrees). |
| lon | float | 0.0 | Geographic longitude of the emitter (decimal degrees). |
| alt | float | 0.0 | Altitude of the emitter in metres. |
ChannelConfigOutput
Per-output spatial metadata associated with a ChannelConfig step.
| Field | Type | Default | Description |
|---|---|---|---|
| output | RFOutput | None | Reference to the RF output port this entry applies to. |
| lat | float | 0.0 | Geographic latitude of the receiver (decimal degrees). |
| lon | float | 0.0 | Geographic longitude of the receiver (decimal degrees). |
| alt | float | 0.0 | Altitude of the receiver in metres. |
ChannelStart
Command payload used with start_scenario().
| Field | Type | Default | Description |
|---|---|---|---|
| channel_index | int | 0 | Zero-based index of the channel to start. |
| start_index | int | 0 | Step index from which playback begins. |
| scenario_mode | ScenarioMode | IDLE | Playback mode. Use ScenarioMode.PLAY_ONCE, ScenarioMode.PLAY_ONCE_HOLD, or ScenarioMode.PLAY_REVERT_LOOP to start playback. |
ChannelStop
Command payload used with stop_scenario().
| Field | Type | Default | Description |
|---|---|---|---|
| channel_index | int | 0 | Zero-based index of the channel to stop. |
Monitoring
Returned by fetch_monitoring(). Contains raw sample arrays captured at the selected tap point.
| Field | Type | Description |
|---|---|---|
| i_samples | list[float] | In-phase (I) component samples. |
| q_samples | list[float] | Quadrature (Q) component samples. |
| delays | list[float] | Delay values applied at the time of capture (ms). |
| dopplers | list[float] | Doppler shift values at the time of capture (Hz). |
| noise_levels | list[float] | The delivered noise level of each channel at the time of capture (dBm). On a board that reports noise floors, a channel whose step has noise_enable=False reads its channel floor, give or take the board's noise level step: under 1 dB near -90 dBm, so the reading can be slightly above or below the floor. |
| config_steps | list[int] | Step indices from the scenario active at each sample instant. |
| DNA | list[int] | Device identifier reported by the hardware. |
SystemSettings
Read-only hardware configuration and operational limits populated from the server during construction. All limit fields define the valid range for the corresponding parameter; values outside these ranges are automatically clamped by the API.
General
| Field | Type | Description |
|---|---|---|
| package_name | str | Firmware package name. |
| product_name | str | Hardware product name. |
| information | str | Freeform info string. |
| scenario_sample_time_s | float | Time per scenario step (seconds). |
Limits
| Field | Type | Description |
|---|---|---|
| limit_delay_minimum_ms | float | Minimum allowed delay (ms). |
| limit_delay_maximum_ms | float | Maximum allowed delay (ms). |
| limit_doppler_minimum_hz | float | Minimum allowed Doppler shift (Hz). |
| limit_doppler_maximum_hz | float | Maximum allowed Doppler shift (Hz). |
| limit_noise_minimum_dbm | float | The lowest noise level you can set with the noise on (dBm): a finite noise_dbm below it is raised to it. A channel floor (noise_floor_dbm()) may be below it. |
| limit_noise_maximum_dbm | float | Maximum noise power (dBm). |
| limit_attenuation_minimum_db | float | Minimum input attenuation (dB). |
| limit_attenuation_maximum_db | float | Maximum input attenuation (dB). |
| limit_input_frequency_minimum_hz | float | Minimum RF input frequency (Hz). |
| limit_input_frequency_maximum_hz | float | Maximum RF input frequency (Hz). |
| limit_output_frequency_minimum_hz | float | Minimum RF output frequency (Hz). |
| limit_output_frequency_maximum_hz | float | Maximum RF output frequency (Hz). |
ScenarioMode
Describes the current execution state of a channel's scenario engine. Also used as a command parameter in ChannelStart to specify the desired playback mode.
| Value | Integer | Description |
|---|---|---|
| ScenarioMode.PLAY_ONCE | 1 | Plays all uploaded steps once in sequence from start_index to the last step, then resets the hardware to step 0 and stops (transitions to IDLE). |
| ScenarioMode.PLAY_ONCE_HOLD | 2 | Plays all uploaded steps once from start_index to the last step, then holds at the last step indefinitely (IDSS/IDOSS zeroed). Sending stop_scenario() resets to step 0. Sending start_scenario() again resumes from the new start_index in the requested mode. |
| ScenarioMode.PLAY_REVERT_LOOP | 3 | Ping-pong loop: plays forward from start_index to the last step, then reverses step-by-step back to start_index, and repeats indefinitely. Turnaround points are played once only (not doubled). IDSS/IDOSS are automatically sign-correct for both directions. Calling stop_scenario() immediately resets to step 0 and goes IDLE. If the window contains only one step, that step is held indefinitely. |
| ScenarioMode.IDLE | 0 | Channel is stopped. This is the state after stop_scenario() or after a scenario completes naturally. Do not pass to start_scenario(). |
Internal reset states (RESETTING, LOADING_STEP0) are managed privately by the server and are never exposed to the API.