Skip to main content

LEA Professional Connect Series

The lea_connect driver controls LEA Professional Connect Series amplifiers — both the Network Connect models (analog inputs) and the Dante Connect models (analog plus Dante) — over the published LEA Open API TCP protocol on port 4321. It covers the whole range, from the 2-channel 352 to the 8-channel 168N.

One amplifier channel is one GEM zone, addressed by channel number. The driver subscribes to each channel's state, so level, mute, channel enable, faults and load-monitor status arrive as the amplifier changes them — including changes made at the WebUI or by a fault — with no polling.

Firmware

The TCP API needs LEA Connect firmware 1.1.0.x or later. Earlier firmware speaks only the websocket API and will not answer on port 4321. The relative bump verb (fader_bump) needs 4.0.4.0 or later; nothing else in this driver depends on it.

How the protocol works​

Everything in the amplifier is an element with a URL, and there are four verbs:

Line sentAmplifier answers
get /amp/channels/1/output/fader/amp/channels/1/output/fader -20.0
set /amp/channels/1/output/mute trueOK
bump /amp/channels/1/output/fader -3OK
subscribe /amp/channels/1/output/mutethe value now, and again on every change
unsubscribe /amp/channels/1/output/muteOK

Every line in both directions ends in \n. Values containing spaces are double-quoted ("Analog 1+2"). Out-of-range numbers are clamped, not refused — an amplifier that answers OK did not necessarily do what was asked, so the driver clamps before sending. Anything the amplifier cannot parse comes back as error: ... with the offending line echoed, which the driver logs.

Subscribed state versus polled telemetry​

The driver draws a hard line between the two, and it matters for attribute history:

  • Subscribed — mute, output fader, channel enable, channel name, fault, thermal fault, ready, primary input source, and load-monitor status, per channel; plus the four power-supply status flags, auto-standby enable and the device name. These change when a person or a fault changes them.
  • Subscribed, but gated by a hold — signal detect. The amp pushes it with the programme material, so the attribute is written through signal_hold_ms (see below).
  • Read once on connect — Hi-Z/Lo-Z mode, load-monitor enable, and the clip and limiting indicators. Subscribe to the last two with subscribe_protection when you want to watch them.
  • Polled — AC line voltage, current and watts, on power_poll_interval (default 60 s).
  • Polled only on request — per-channel output watts, volts and measured impedance, on meter_poll_interval (default 0, off).

The driver never subscribes to a meter. The protocol guide's own example session shows a level subscription pushing roughly ten updates a second, per channel; on an 8-channel amp that is a firehose into attribute_history. Read meters on demand with get_meters, or accept the history cost deliberately by setting meter_poll_interval.

Signal detect is the same kind of value, and on real hardware it is the loudest thing on the connection. Measured on a 168N passing audio, signalDetect pushed about nine times a second across eight channels over a 20-second sample, while every other subscribed element sat at its connect value for the whole window. It stays subscribed — a channel starting to pass audio is worth knowing at once — but the attribute is gated: presence is written as it arrives, and absence waits out signal_hold_ms (3 s by default) and is cancelled by the next detection. That turns a transient-rate element into the state-rate one a zone tile can render, and takes the steady-state attribute write rate for an idle-but-playing amplifier to zero. Set signal_hold_ms to 0 to record every transition.

Clip and limiting sit outside the subscribed set for the same reason. A limiter engaging on musical peaks is normal and can toggle several times a second on a hard-driven channel; across eight channels that is a stream of writes for something nobody acts on per event. Channel fault and thermal fault — rare, and worth acting on — are always subscribed.

Every value is change-guarded — an unchanged reading is not written.

Prerequisites​

  • Amplifier on the LAN over wired Ethernet or joined to an existing wireless network — not its own access-point mode — with a static address or a DHCP reservation.
  • Firmware 1.1.0.x or later.

Setup​

  1. In the amplifier WebUI, confirm the firmware version and network address, and name each output channel. The driver reads those names; with auto_create_zones on it uses them to label the zones it creates.
  2. System → Devices → Add Device: choose LEA Professional Connect Series (lea_connect), set ip, leave port at 4321, save and enable.
  3. On connect the driver reads the device info, learns the channel count from /amp/deviceInfo/numOutputs, and subscribes each channel. An 8-channel amplifier opens with about 120 lines at the default 50 ms throttle — roughly six seconds to fully converge.
  4. Create one zone per amplifier channel, with address set to the bare channel number (1 through 8). Or set auto_create_zones on the device and let the driver create them from the amplifier's own channel names. Existing zones are never touched, a channel whose zone you disabled is not recreated, and a channel name the amplifier repeats across outputs (the factory default is OutputName on every channel) falls back to <device> Channel <n> so the zones stay distinguishable.
  5. For a room that needs on-screen volume, set the AV zone's Volume Device to this amplifier and its audio output routing address to the channel number. Volume, mute and power state mirror back onto that zone.

Ganging the amplifier — group_all_zones​

The amplifier has no grouping of its own (see the known quirks), so ganging is done here. With group_all_zones on, the amp behaves as one logical output:

  • Level, mute and channel enable sent to any zone are applied to every channel — volume, volume_up, volume_down, set_fader, fader_bump, mute_on, mute_off, mute_toggle, on, off, power_on, power_off.
  • The resulting state is published to every zone, so all the tiles move together rather than seven of them showing a level nobody set.

The stateful verbs are resolved once, against the channel the caller addressed, and the absolute result is sent to every channel. That matters: eight mute_toggles each computed from their own channel would split the amp in half the first time one channel was muted on its own, and eight volume_ups computed from eight different levels would stay eight different levels forever.

Per-channel tuning is not ganged. Crossover, EQ, limiters, load-monitor limits, input routing, Hi-Z mode and channel names stay on the channel they were addressed to. That is how a room is tuned — an installer trimming EQ on the channel feeding the back wall does not mean it for the other seven, and a gang that stamped one channel's tuning across the amp would be a commissioning accident rather than a feature.

Observations are aggregated rather than last-wins, because they genuinely differ per channel: fault, thermal_fault, limiting, clip and signal_detect are reported for the group if any channel reports them, and clear only when the last channel holding them lets go. Publishing whichever channel reported most recently would make the group flap at the rate the channels disagree. Everything else — impedance, load status, input source — stays a per-channel write to the zone at that address, and the per-channel truth for the ganged values is always on the device as ch<n>_<name>.

One command per channel

The protocol has no multi-channel addressing, so a ganged command is n separate writes at command_throttle spacing — about 400 ms for an 8-channel amp at the default 50 ms. The channels step rather than move in perfect lockstep.

Attributes​

Device — required​

AttributeTypeDescription
ipstringLAN IP or hostname of the amplifier.

Device — optional​

AttributeTypeDefaultDescription
portint4321LEA Open API port. Fixed at 4321 on current firmware.
channelsint—Channel count override. Normally read from the amplifier; set it only if the amp does not report one.
fader_min_dbfloat-80The dB value that volume 0 maps to. Raise it (e.g. -40) to spread a 0-100 slider over a more useful part of the fader. Clamped to -80..-1.
volume_stepint2How far volume_up / volume_down move, in points on the 0-100 scale.
power_poll_intervalint (ms)60000AC line voltage / current / watts read cadence. One sample is taken on connect, then on this interval. 0 disables it.
meter_poll_intervalint (ms)0Per-channel watts / volts / impedance read cadence. When set, one sample is taken as soon as the channel count is known, then on this interval. 0 (default) disables it.
subscribe_protectionboolfalseSubscribe to the per-channel clip and limiting indicators rather than reading them once on connect.
signal_hold_msint (ms)3000How long signal presence must stay absent before the channel reports no signal. 0 writes every transition.
auto_create_zonesboolfalseCreate one zone per channel on connect, labelled from the amp's channel names.
group_all_zonesboolfalseGang the amplifier into one output — see below.
command_throttleint (ms)50Minimum spacing between lines sent to the amplifier.

Reflected device attributes​

AttributeTypeNotes
model, serial_number, firmware_version, power_supply_firmware, hardware_idstringFrom /amp/deviceInfo/.
device_name, venue_name, rack_name, rack_position, asset_tag, installer_namestringThe amplifier's own naming fields. device_name is subscribed.
date_of_manufacture, date_of_installation, uptimestringAs the amplifier reports them.
channel_count, input_countintFrom numOutputs / numInputs. channel_count drives the subscription pass.
ac_line_voltage, ac_line_current, ac_line_wattsfloatPolled on power_poll_interval.
power_supply_fault, power_supply_thermal, power_okboolSubscribed power-supply status.
line_voltage_okbooltrue when the AC line is healthy. Inverted from the amp's lineWarning element — see the quirk below.
fault_state, thermal_statestringon / off rollups across the power supply and every channel — one trigger covers the whole amplifier.
auto_standby, auto_standby_threshold, auto_standby_waitbool / float / intAuto-standby configuration.
signal_generator_type, signal_generator_frequencystring / intAmplifier-wide signal generator.
ch<n>_volume, ch<n>_mute_state, ch<n>_power_state, ch<n>_fault, ch<n>_load_status, ch<n>_namemixedA compact per-channel summary, so an amplifier with no zones mapped yet still shows its state and can drive a trigger. Full channel state lives on the zone.

Zone​

Address required: yes — the bare amplifier channel number, 1 through 8. The driver refuses anything else (ch1, 1:1) and logs the address it was given rather than framing a broken line.

AttributeTypeNotes
volumeint0-100, mapped from the output fader.
fader_dbfloatThe raw output fader, -80.0 to 0.0.
mute_statestringon / off.
power_state, statestringon / off, from the channel-enable element. Both are written — the zone tiles read state, the AV layer reads power_state.
channel_namestringThe channel name stored in the amplifier.
fault, thermal_fault, readyboolSubscribed channel status.
signal_detectboolSubscribed, with absence held for signal_hold_ms.
limiting, clipboolRead on connect; live only with subscribe_protection.
load_statusstringOk, Short, Open or Low Signal.
load_monitor, load_high_limit, load_low_limit, impedancebool / floatLoad monitoring. impedance needs meter_poll_interval or a get_meters.
input_source, secondary_input_source, input_priority_modestringInput selection.
input_fader_db, input_level_db, input_signal_detect, input_clipfloat / boolInput stage.
output_mode, hiz_hpf_frequencystring / intLoZ / HiZ-70V / HiZ-100V and the Hi-Z high-pass.
output_watts, output_volts, output_dbfloatMeters — only written when polled or read on demand.
rms_limiter, peak_limiter, rms_gain_reduction, peak_gain_reductionbool / floatLimiter state.
pilot_tone, pilot_tone_status, pilot_tone_levelbool / string / floatPilot tone supervision.

Commands​

A command missing a value it needs is refused with {error: 'invalid <arg>'} and nothing is sent: a numeric setting with no value or no number in it, a blank enum, boolean, element URL or passthrough line, and a set_channel_name / set_device_name / set_venue_name with no name at all (a blank name is still sent). Every value that was sent before is sent unchanged. While the amplifier is unreachable a level or mute command answers socket not ready without moving the zone tile, and get_status answers the same error instead of success.

Channel power, level and mute​

CommandArgsNotes
on / offaddressEnable / disable the channel output. The zone on and off verbs.
power_on / power_offaddressThe same element as on / off.
mute_on / mute_offaddressMute / unmute the channel.
mute_toggleaddressResolved from the subscribed mute state — the protocol has no toggle. The new state is recorded as it is sent, so a second tap before the amplifier answers toggles back.
volumeaddress, volume (0-100)Mapped linearly in dB onto fader_min_db..0.
volume_up / volume_downaddress, stepMoves by step points (default volume_step). Computed from the subscribed fader and written absolutely, so it works on every firmware.
set_faderaddress, fader (dB)Set the output fader directly, -80.0 to 0.0.
fader_bumpaddress, amount (dB)Native relative move; positive is louder. Firmware 4.0.4.0+.

Channel input routing​

CommandArgsNotes
set_inputaddress, inputPrimary input source.
set_secondary_inputaddress, inputSecondary (backup) source, or None.
set_input_fader / set_secondary_input_faderaddress, faderInput gain, -80.0 to 0.0 dB.
set_input_modeaddress, modeOverride (auto override primary) or Backup (signal-sensing override).
set_mix_faderaddress, mixer, faderOne mixer input fader. In circuit only while the primary source is Mixer.
set_dante_on_rampaddress, modeWhat the channel puts back on the Dante network. Dante Connect models only.

Channel output configuration​

CommandArgsNotes
set_channel_nameaddress, nameThe channel name stored in the amplifier.
set_output_modeaddress, modeLoZ, HiZ-70V or HiZ-100V. Check the speaker wiring first.
set_hiz_hpfaddress, frequencyHi-Z high-pass, 35 to 5000 Hz.

Load monitoring and limiters​

CommandArgsNotes
load_monitor_on / load_monitor_offaddressSpeaker load monitoring.
set_load_high_limit / set_load_low_limitaddress, limitImpedance limits in ohms — outside them the load reads Open / Short.
rms_limiter_on / rms_limiter_offaddressRMS (thermal) limiter.
set_rms_threshold / set_rms_attack / set_rms_releaseaddress, valueThreshold in volts (10-140), times in ms (1000-10000).
peak_limiter_on / peak_limiter_offaddressPeak (excursion) limiter.
set_peak_threshold / set_peak_attack / set_peak_releaseaddress, valueThreshold in volts (14-198), times in ms (1-1000).

Crossover and EQ​

CommandArgsNotes
set_crossover_gain / set_crossover_delay / set_polarityaddress, valueBand gain (-15 to 15 dB), delay (0-100 ms), polarity invert.
high_pass_on / high_pass_off / low_pass_on / low_pass_offaddressCrossover filter enables.
set_high_pass_type / set_low_pass_typeaddress, typeButterworth, Linkwitz-Riley or Bessel, 6 to 48 dB/oct.
set_high_pass_frequency / set_low_pass_frequencyaddress, frequency20 to 20000 Hz.
set_eq_enable / set_eq_type / set_eq_gain / set_eq_frequency / set_eq_qaddress, filter, valueOne output EQ band. filter is the band number.

Signal generator and pilot tone​

CommandArgsNotes
signal_generator_channel_on / _offaddressRoute the generator into the channel.
set_signal_generator_faderaddress, faderGenerator level into the channel.
pilot_tone_on / pilot_tone_offaddressPilot tone supervision.
set_pilot_tone_frequencyaddress, frequency19000 to 24000 Hz.

Amplifier-wide​

CommandArgsNotes
auto_standby_on / auto_standby_off—Auto standby.
set_auto_standby_thresholdthreshold-80.0 to 0.0 dBFS.
set_auto_standby_waitminutes1 to 240.
set_signal_generator_type / set_signal_generator_frequencytype / frequencyPink noise, white noise or tone; 20 to 20000 Hz.
set_input_sensitivityinput, sensitivity26dB or 34dB on one physical analog input.
set_device_name / set_venue_namenameThe amplifier's naming fields.

Reads and escape hatches​

CommandArgsNotes
get_status—Re-read everything: device info, amplifier settings, power supply, every channel.
get_device_info / get_power_supply—One section each.
get_channel_statusaddressOne channel's level, mute, enable, faults, input and load state.
get_meters—Output watts, volts and impedance for every channel, once.
get_elementelementRead any element by URL, e.g. /amp/channels/1/output/fader.
subscribe_element / unsubscribe_elementelementSubscribe to any element. A commissioning tool — a meter subscription pushes continuously until the connection drops.
passthroughcommandSend one protocol line verbatim, e.g. set /amp/channels/1/output/mute true. The escape hatch for elements this driver does not model.

Known quirks​

  • There is no power command. The amplifier is designed to stay powered, and auto-standby is a threshold-and-timer setting rather than a switch. power_on / power_off (and the zone on / off verbs) drive the channel enable element — the WebUI's "channel ready" control. The amplifier stays on and the channel stops passing audio. Mute is a separate state and those verbs leave it alone. For a true power cut, switch the amplifier's supply with a controllable outlet from the zone's off_action.
  • Level is a dB fader, not a percentage. The fader runs -80.0 to 0.0 dB; GEM's 0-100 maps onto fader_min_db..0 linearly in dB, so 50 is -40 dB and 0 is -80 dB (silent, but not muted). If the bottom half of a slider feels dead, raise fader_min_db.
  • lineWarning does not read backwards — the guide does. The protocol guide documents /amp/powerSupply/lineWarning true as AC line voltage is OK. Hardware says otherwise: a 168N on a healthy 124 V line reports lineWarning false while powerOk is true and no fault is set. The element is a literal warning flag, so the driver inverts it: line_voltage_ok is true when the line is healthy, which is what an attribute trigger on it should assume.
  • bump needs firmware 4.0.4.0. volume_up / volume_down deliberately do not use it — they compute the new fader from the subscribed level and write it absolutely, which works everywhere. fader_bump is the native relative move and is the one that needs the newer firmware.
  • Input sources differ by model. Network Connect amplifiers have analog inputs only, and only as many as they have channels — a 354 has no Analog 5-8. Dante Connect amplifiers expose all eight Dante inputs regardless of channel count. The driver offers the full list and lets the amplifier reject what it does not have.
  • Clip and limiting are transient, not state. They are read once on connect and subscribed only when subscribe_protection is set, so the default is quiet on a system being driven hard. They are always included in get_channel_status.
  • Mix faders are only in circuit while the channel's primary input source is Mixer.
  • The protocol has no grouping of any kind. There is no group, gang, stereo-link, zone, preset or master-fader element, no way to address more than one channel in a line, and no wildcard — /amp/channels/1,2/..., /amp/channels/*/... and every spelling of a group URL are refused with object/element does not exist. The address space is flat and leaf-only: a branch URL such as /amp/channels/1 or /amp/deviceInfo is not readable either, so the amplifier cannot be enumerated over the API — you can only read elements you already know the name of. Group channels on the GEM side (one zone per channel, gathered by a macro, a UI zone list, or an AV zone that spans them), not on the amplifier.
  • Written from the LEA Open API TCP protocol guide rev 7 (10-10-2025), which notes that more commands exist than it documents. Use passthrough for anything not modelled here.
  • Verified against a Connect Series 168N on firmware 4.0.4.14: every element this driver models was read back from the amplifier, and level, mute, channel enable, mute_toggle, volume_up / volume_down, set_fader and fader_bump were driven on it. The amplifier has 8 channels and 8 output EQ bands per channel, numbered from 1. Where the protocol guide and the hardware disagreed, the hardware won — see lineWarning above.

Troubleshooting​

SymptomCheck
Connects but nothing ever updatesFirmware older than 1.1.0.x answers only on the websocket API. Check the version in the WebUI and update the amplifier.
Zones exist but commands do nothingThe zone address must be the bare channel number (1, not ch1 or 1:1). The driver logs the address it refused.
Volume slider feels dead over its bottom halfThe fader is linear in dB, so 50 is -40 dB. Raise fader_min_db to compress the range into the part of the fader the room uses.
Channel count wrong, or zones for channels that do not existThe amplifier reports it on /amp/deviceInfo/numOutputs. If it does not answer, the driver falls back to the highest mapped zone address; set the channels attribute to pin it.
Attribute history filling upmeter_poll_interval is set. Per-channel watts and volts move with the programme material — set it back to 0 and use get_meters on demand.
An error: line in the log naming a rejected commandbump needs firmware 4.0.4.0, and some elements differ between Network Connect and Dante Connect models. The amplifier echoes the line it rejected.
Level changes made in the WebUI do not appearSubscriptions live on the TCP session. If the connection has dropped, the driver re-subscribes on reconnect and rewrites every value.
  • Zones — one zone per amplifier channel, addressed by channel number.
  • AV Zones — bind this amplifier as a zone's Volume Device.
  • Devices — add and configure the amplifier.
  • Commands — the command grid and the Test runner.
  • Attributes — the reflected state above, and triggering on it.