Skip to main content

SPAN Smart Panel

The span_panel driver polls a SPAN Smart Panel over its on-LAN REST API. It auto-discovers circuits, mirrors them as zones under the power subsystem, and exposes panel-level telemetry — main relay state, grid/feedthrough power, run config, DSM grid state, islanding state, and battery state-of-energy — as device attributes.

All traffic stays on the LAN. There is no SPAN cloud round-trip at runtime.

Status

Built against the SPAN documented REST API. Onboarding uses /api/v2/auth/register to exchange a passphrase for a JWT bearer; telemetry and control use /api/v1/*. The /api/v1 surface is documented to deprecate 2026-12-31 — when SPAN extends /api/v2 to cover telemetry, or the integration moves to MQTT/eBus, the transport swaps internally with no change to how you configure the device.

The panel's built-in MQTT/Homie 5.0 broker is intentionally not used.

Prerequisites

  • SPAN panel reachable from the GEM controller on TCP/443 (HTTPS, self-signed cert accepted).
  • A panel passphrase. There are two ways to mint one:
    • SPAN Home app — issues a passphrase tied to your account.
    • Door switch — press the panel door switch for proof-of-proximity, then complete the registration flow within the timeout window.

Setup

  1. System → Devices: add a device with driver span_panel. Fill in:
    • ip — panel LAN IP
    • passphrase — proof-of-proximity passphrase (secure)
  2. Save and enable. The driver:
    • calls /api/v2/auth/register (the only v2 call it makes) and caches the returned JWT as the access_token device attribute,
    • reads /api/v1/status to populate serial_number, firmware_version, door_state,
    • calls /api/v1/circuits to enumerate circuits — each one is auto-created as a zone under the power subsystem (created on demand) with zone.address = the circuit UUID and control = power_default,
    • starts polling /api/v1/panel, /api/v1/circuits, /api/v1/storage/soe, /api/v1/islanding-state every 5 s, and re-reads /api/v1/status (serial / firmware / door) about once a minute (every 12 poll cycles).

Attributes

Device

AttributeRequiredTypeNotes
ipyesstringPanel LAN IP.
passphraseyesstring (secure)Proof-of-proximity passphrase from the SPAN Home app or door-switch flow.
portnointOverride the panel port (default 443 for https, 80 for http). Useful when proxying.
protocolnostringhttps (default) or http. Use http only behind a plaintext proxy.
poll_intervalnointTelemetry poll interval in seconds. Default 5, range 1..300.
access_tokennostring (secure, readonly)JWT cached after registration. The driver auto-refreshes by re-registering on 401/403.

Runtime-populated (read-only):

AttributeTypeSource
serial_numberstringregistration response, refreshed from /api/v1/status (system.serial)
firmware_versionstring/api/v1/status (software.firmwareVersion)
main_relay_statestring/api/v1/panel.mainRelayState
grid_power_wfloat/api/v1/panel.instantGridPowerW
feedthrough_power_wfloat/api/v1/panel.feedthroughPowerW
run_configstring/api/v1/panel.currentRunConfig
dsm_grid_statestring/api/v1/panel.dsmGridState
islanding_statestring/api/v1/islanding-state.islanding_state
battery_soe_percentfloat/api/v1/storage/soe (soe.percentage)
door_statestring/api/v1/status (system.doorState)
discovered_circuitsstring (json)Last circuits snapshot for diagnostics.
last_errorstringMost recent failure reason (registration error, panel unreachable, etc.) — written whenever a poll or connect fails.

Telemetry from /api/v1/panel, /api/v1/circuits, /api/v1/storage/soe, and /api/v1/islanding-state refreshes every poll (5 s by default). Identity fields read from /api/v1/statusserial_number, firmware_version, door_state — refresh only at connect and then about once a minute, so the door reading is not real-time.

Zone

Zone address is the circuit UUID from /api/v1/circuits. Per-circuit attributes populated by the poller:

AttributeType
statestring — on (relay closed) or off (relay open)
relay_statestring — raw CLOSED / OPEN
instant_power_wfloat
consumed_energy_whfloat
produced_energy_whfloat
prioritystring — MUST_HAVE / NICE_TO_HAVE / NON_ESSENTIAL
is_user_controllablebool
is_sheddablebool
is_never_backupbool
tabsstring (CSV)

Per-circuit power feeds the Power Management dashboard: instant_power_w carries the power.circuit metric role (Top Circuits widget) and the two energy counters carry energy.consumed / energy.produced (Energy Today widget). instant_power_w is signed — positive is consumption, negative is backfeed/export. The device-level battery_soe_percent carries the battery.soc role, so a SPAN with attached storage shows up on the dashboard's battery readouts.

Configurable

AttributeTypeDefaultNotes
ct_clamp_reversedboolfalseCorrect a single physically-reversed CT clamp on a pure-load circuit — e.g. a fridge that reports a steady negative instant_power_w. When enabled, GEM negates instant_power_w and swaps the consumed_energy_wh / produced_energy_wh counters for that circuit.
Use sparingly

ct_clamp_reversed is a retrofit escape hatch — the proper fix is recommissioning the CT in SPAN. Do not enable it to paper over a tab-mapping swap (two circuits crossed at the panel), which would only hide the partner circuit's error instead of fixing it.

Commands

CommandArgsPurpose
onaddressSet the circuit's relay to CLOSED (zone on).
offaddressSet the circuit's relay to OPEN (zone off).
rebootaddress, delayOpen the relay, wait delay seconds (default 5), close it again. Useful for power-cycling a non-essential load.

All three relay commands are refused with circuit … is not user-controllable when SPAN marks the circuit non-controllable (e.g. the mains feed or never-backup loads). The driver checks the last cached circuit snapshot before sending, so the refusal is immediate.

Quirks

  • SPAN's API serializes float32 telemetry as full float64, leaking artifacts like 1557.4998779296875 for what was 1557.5. The driver rounds to 1 decimal place — only ~7 significant digits are real.
  • The panel rejects relay writes for circuits where isUserControllable=false. The driver checks the cached snapshot before sending and returns an error early.
  • After auth-related 401/403 errors the driver re-registers automatically using the stored passphrase. If the passphrase was rotated externally, registration will fail until the device row is updated.

Troubleshooting

SymptomCheck
registration returned no access token on first connectWrong passphrase, or the proof-of-proximity window expired. Mint a fresh passphrase from the SPAN Home app and retry.
Repeated re-register failed warningsPassphrase has been invalidated (e.g. rotated). Update the device's passphrase attribute with a freshly minted value.
Circuit relay command returns circuit ... is not user-controllableThe circuit is locked at the panel level (e.g. main breakers, never-backup loads). Cannot be controlled remotely.
No new zones appear after wiring changeReload the device (System → Devices → the Reload action on the device row) to re-call /api/v1/circuits. The poller does not auto-create new zones — it only refreshes telemetry on circuits discovered at connect.
Device shows offline or telemetry stops updatingCheck the device's last_error attribute for the most recent failure reason. A reachable panel that fails every endpoint marks the device disconnected; any one endpoint succeeding keeps it connected.
  • Devices — device CRUD and attributes
  • Zones — control types, relay-state translation