Skip to content

Navigation Menu

Sign in
Sign up

Migration Guide: v1 dsmState to v2 dominant-power-source #8

dcj started this conversation in General
Discussion options

We've seen questions from integration developers and users about the removal of dsmState in the eBus/Homie API — particularly from those who relied on it as a single "green light" signal for grid connectivity in dashboards and automations. This is a fair concern, and we want to be transparent about what changed, why, and how to get the same information (and more) from the v2 API.

Overview

The SPAN v1 REST API included a dsmState field in the /api/v1/status response that reported the panel's grid connectivity state. With the v2 API (MQTT/Homie 5.0), this field is replaced by the Homie property core/dominant-power-source.

The short answer: dominant-power-source is a direct replacement for dsmState with cleaner naming, real-time push delivery, and the addition of bidirectional control. No information was lost. Read on for the details.

v1: The dsmState Field

The /api/v1/status response included three related fields:

Field Example Values Purpose
dsmState DSM_ON_GRID, DSM_ISLANDED Panel's current operating mode
dsmGridState DSM_GRID_UP, DSM_GRID_DOWN Grid availability
currentRunConfig PANEL_ON_GRID, PANEL_OFF_GRID Panel run configuration

dsmState values

Value Meaning
DSM_ON_GRID Panel is connected to and operating on the utility grid
DSM_ISLANDED Panel is disconnected from grid, operating on battery or standalone
DSM_FAULTED_ON_GRID Fault condition while grid-connected
DSM_FAULTED_OFF_GRID Fault condition while islanded
DSM_UNKNOWN State not yet determined

In practice, most clients used dsmState as a simple binary signal: "Is my panel on the grid right now?"

Limitations of dsmState

  • Read-only. Clients could observe the state but not request transitions.
  • Polling-based. Required periodic REST requests to detect changes.
  • Internal naming. The DSM_ prefixed values were opaque labels with no documented semantics beyond what could be inferred from the names.

v2: The dominant-power-source Property

MQTT topic and schema

ebus/5/<serial>/core/dominant-power-source
Attribute Value
Datatype enum
Format GRID,BATTERY,PV,GENERATOR,NONE,UNKNOWN
Settable Conditionally (when grid-islandable is true)

The property's schema is available in the device's $description attribute and via the /api/v2/homie/schema endpoint.

Values

Value Meaning
GRID Panel is operating on grid power
BATTERY Panel is islanded, operating on battery
PV Panel is operating on solar (future)
GENERATOR Panel is operating on generator (future)
NONE Panel is islanded with no power source
UNKNOWN State not yet determined or fault condition

Mapping from v1 to v2

v1 dsmState v2 dominant-power-source
DSM_ON_GRID GRID
DSM_ISLANDED (with battery) BATTERY
DSM_ISLANDED (no battery) NONE
DSM_FAULTED_ON_GRID UNKNOWN
DSM_FAULTED_OFF_GRID UNKNOWN
DSM_UNKNOWN UNKNOWN

The v1 fault states (DSM_FAULTED_ON_GRID, DSM_FAULTED_OFF_GRID) are no longer distinguishable in v2 — both map to UNKNOWN. These states represent hardware conditions that require physical service intervention and are not actionable by API clients.

What's new in v2

Push-based delivery. Clients subscribe to the MQTT topic and receive updates in real time, replacing REST polling.

Bidirectional control. When the panel's core/grid-islandable property is true (indicating the panel is capable of operating off-grid), dominant-power-source becomes settable. Writing a value to the /set topic requests a power mode transition:

  • Publishing GRID tells the panel to treat the home as grid-connected
  • Publishing BATTERY tells the panel to treat the home as islanded on battery

To understand why this matters, it helps to know how the SPAN panel manages circuits during an outage. Each circuit has a configurable shed-priority that determines when it is automatically disconnected to conserve battery:

shed-priority Behavior
OFF_GRID Circuit is shed immediately when the panel enters off-grid mode
SOC_THRESHOLD Circuit is shed when battery state of charge drops to a configured threshold
NEVER Circuit is never automatically shed — it stays powered as long as the battery can supply it

Under normal operation, the battery system (BESS) controls the home's grid connection and reports its state to the panel. The panel uses this information to manage load shedding automatically. During this normal operation, the BESS is authoritative — the panel will not act on /set commands from external clients.

However, if the panel loses communication with the BESS, it no longer receives updates about grid status or battery state of charge. If the panel's last known state was off-grid, it will continue shedding circuits according to their configured priorities — even if the grid has since been restored. The /set capability allows a client to inform the panel that conditions have changed, ensuring that circuits are not unnecessarily kept offline. Publishing GRID to dominant-power-source/set restores normal operation and re-energizes shed circuits.

This gives homeowners and integrations a safeguard: the ability to override the panel's last-known state when the BESS is unreachable, preventing unnecessary disruption to circuits that could otherwise be powered.

This is new capability — the v1 dsmState was read-only.

Extensible values. The enum includes PV and GENERATOR for future power source types that the v1 API had no representation for.

Complementary v2 properties

The v2 API exposes additional properties that provide context beyond what dsmState alone offered:

Property Node Values Purpose
dominant-power-source core GRID, BATTERY, PV, GENERATOR, NONE, UNKNOWN Current power regime
grid-islandable core boolean Whether the panel supports off-grid operation
grid-state bess UNKNOWN, ON_GRID, OFF_GRID Grid state from the battery system (when commissioned)
connected bess boolean Whether a battery system is commissioned
active-power lugs-upstream float (W) Real-time power flow at the grid connection
relay core UNKNOWN, OPEN, CLOSED Main relay state

Migration Summary

Simple migration

For clients that used dsmState as a grid connectivity indicator:

v1 pattern v2 equivalent
Poll GET /api/v1/status, read dsmState Subscribe to ebus/5/<serial>/core/dominant-power-source
dsmState == "DSM_ON_GRID" dominant-power-source == "GRID"
dsmState == "DSM_ISLANDED" dominant-power-source == "BATTERY" or "NONE"
dsmGridState == "DSM_GRID_UP" bess/grid-state == "ON_GRID" (when BESS is commissioned)

Is additional signal derivation needed?

No. The dominant-power-source property directly answers the same question dsmState did: "What power regime is the panel in right now?" A client that subscribes to this single property has all the grid connectivity information that dsmState provided.

Clients that want additional confidence can cross-reference bess/grid-state (if a battery system is commissioned) and lugs-upstream/active-power (real-time grid power flow), but this is optional — dominant-power-source is the authoritative signal.

About the property name

The name dominant-power-source describes the panel's current operating power regime — not a measurement of which source is providing the most watts. When the value is GRID, the panel is grid-connected. When the value is BATTERY, the panel is islanded on battery. It is the direct successor to dsmState.

You must be logged in to vote

Replies: 4 comments 2 replies

Comment options

Yeah the name 'dominant' certainly threw me off. The common meaning of that word does not mean this or that but rather a potential combination or where one power source is on most of the time.

When you say the dominant power source is singular then as long as the grid is up no other value can be possible.

So in effect the dominant power source could never be PV unless there was no battery power and the system was off grid and could operate in that disconnected mode.

There seems to be a hierarchy then:

1 - Grid / Generator (even if PV sending energy to grid)
2 - Battery when grid down
3 - PV (only if battery missing/depleted and panel can run islanded?)

Does SPAN have a relationship with generators (perhaps MLO 40 auto start), I know my 32 panel treats generator as Grid and the user must start the generator as Grid substitute.

A matrix might help.

You must be logged in to vote
2 replies
Comment options

dcj Mar 3, 2026
Maintainer Author

Here is the thinking & context that went into the choice of dominant-power-source:

dominant-power-source is actually describing the grid-forming entity (GFE), not "who is producing the most watts."

The distinction is precise and important:

  • Grid-connected: The utility grid is the GFE. It sets voltage and frequency. The BESS and PV are grid-following — they inject/absorb power but don't form the grid. Even if 100% of the home's consumption comes from PV, the grid is still "dominant" because it's the reference that everything else synchronizes to.
  • Islanded on battery: The BESS inverter becomes the GFE. It sets voltage and frequency for the home's microgrid. PV (if present) follows the BESS's reference.
  • NONE: Islanded with no GFE — nothing is forming a grid for the home.

The name dominant-power-source is trying to say "who is in charge" not "who is producing the most watts."
The word "dominant" actually works in this sense (dominant = controlling, authoritative), but readers bring their own assumption that "power source" means "watt producer" and "dominant" means "biggest."

More than one client developer has been misled by the current name, feel free to suggest alternate names, but at this point, renaming this property would be a breaking change.

Claude suggests: rather than changing the property name, revise and strengthen the name field in the Homie $description schema. Right now it's "Current dominant power source, load-shedding trigger".
Something like "Current grid-forming power source, determines load-shedding behavior" would nudge developers toward the right mental model when they discover the property through the schema.

Comment options

Don thanks, now that I'm not mobile, let me expound with some help.

Thanks for the detailed write-up. The migration tables and the /set capability
explanation are valuable. Understanding that dominant-power-source is a
firmware-computed regime indicator (not a watts comparison) and the direct
successor to dsmState, let me share where this maps cleanly to what users need
and where gaps in my understanding remain. Under the assumption that those gaps
exist, our HA integration combines DPS with corroborating signals
(bess/grid-state, lugs-upstream/active-power, power-flows/grid) to provide
robust edge case answers for the binary "is the grid up?" question.

The question users are asking

Most automations and dashboards built on dsmState answered one question: "Is
utility grid power available?"
That's a binary yes/no.
dominant-power-source answers a richer question — "What power regime is the
panel in?"
— which is more information, not less. But translating DPS back to
the binary answer has edge cases that the guide doesn't address.

BESS communication loss

The guide acknowledges that when the panel loses BESS communication, DPS retains
its last-known state. The /set capability is a great safeguard for active
control — a homeowner or integration can tell the panel "the grid is back." But
for passive monitoring, this creates a window where DPS is stale. An automation
asking "is the grid up?" gets the wrong answer until someone actively intervenes.
In our HA integration, we corroborate DPS with lugs-upstream/active-power and
power-flows/grid as a defensive measure — if DPS says BATTERY but real-time
grid power signals are non-zero, the grid has likely been restored. This isn't
second-guessing the firmware so much as covering the acknowledged stale-state
window.

UNKNOWN is not actionable

When DPS reports UNKNOWN, a user asking "is the grid up?" gets no answer. The
guide maps both v1 fault states (DSM_FAULTED_ON_GRID and
DSM_FAULTED_OFF_GRID) to UNKNOWN, losing the distinction of whether grid power
was available during the fault. That distinction matters for automation decisions
like "should I start the generator?" or "are my shed priorities active?" Is there
another v2 signal that carries the on-grid/off-grid context during a fault, or is
this information genuinely unavailable via eBus?

Generator systems

The guide lists GENERATOR as a future value. My 32-tab panel treats a running
generator as grid — so DPS reports GRID when on generator power. For users with
backup generators, this means DPS=GRID doesn't distinguish between utility power
and generator power. That's fine today if everyone understands the limitation, but
it would be worth documenting explicitly: "DPS=GRID means the panel is operating
in grid-connected mode, which includes generator power on panels that treat
generators as a grid source."

Schema documentation

The eBus schema's $description attribute for dominant-power-source could make
the regime-vs-watts distinction explicit. A one-liner like "Reports the panel's
operating power regime, not a comparison of source wattage"
would save
integrators from having to find this discussion to understand the property's
semantics.

What would help most

A matrix of system configurations mapped to expected DPS values would let
integrators validate their logic:

Configuration Grid Generator BESS PV Expected DPS
Grid-tied, no DER Up ?
Grid-tied + battery Up Connected ?
Grid-tied + battery Down Discharging ?
Grid-tied + PV Up Producing ?
Generator backup Down Running Charging ?
BESS comms lost Restored Unreachable ?
Off-grid permanent Primary Optional ?

If those expected values can be confirmed, integrators can build reliable
derivations on top of DPS rather than around it. Or if I need redirection, let me know.

Comment options

a bit more for the brain pan...

Additional Open Questions

  1. Firmware reclaim behavior: After a user/automation /sets DPS, does
    firmware reclaim it when BESS comms are restored? Or is the /set latched
    until explicitly changed back? This determines whether /set is a momentary
    nudge or a persistent override.

  2. Panel-independent grid detection: Does the panel use any of its own
    measurements (power-flows/grid, lugs-upstream/active-power, voltage) to
    independently determine grid status, or does it rely entirely on BESS for
    grid-up/grid-down awareness?

  3. DPS update source: Is DPS always computed from BESS reporting, or are
    there other inputs (e.g., voltage collapse detection, ATS position sensing)?

  4. Generator interaction: On 32-tab panels where generator feeds through the
    same lugs as grid, does DPS=GENERATOR exist in firmware today or is it
    reserved for future use? How would the panel distinguish utility from
    generator?

Stale DPS Scenario Matrix

The core problem: the panel depends on BESS for grid state awareness. When BESS
comms are lost, DPS is stale. Our dsm_state sensor addresses this by combining
bess/grid-state, dominant-power-source, power-flows/grid, and
lugs-upstream/active-power — signals the panel has but doesn't use for DPS
computation. The scenarios below show where this combined signal detects what DPS
alone cannot.

# Sequence DPS (stale) Actual State Impact Detectable?
1 BESS comms drop while on-grid, grid stays up GRID On-grid None — stale value happens to be correct N/A
2 BESS comms drop while off-grid, grid stays down BATTERY Off-grid None — stale value happens to be correct N/A
3 Grid restored, BESS comms still down BATTERY On-grid Unnecessary shedding continues Yes: power-flows/grid resumes, lugs-upstream/active-power shifts
4 BESS comms drop while on-grid, then grid drops GRID Off-grid No shedding — battery drains faster, reduced runtime Yes: power-flows/grid drops to zero, voltage may sag
5 BESS comms drop while off-grid, then grid restores BATTERY On-grid Same as #3 — unnecessary shedding Yes: power-flows/grid resumes
6 BESS itself fails (comms + battery), grid up BATTERY or GRID On-grid, no backup Shedding state depends on last DPS Yes: bess/connected = false

DPS /set Safety by Direction

Not all /set directions carry equal user risk. Shedding unnecessarily is annoying;
failing to shed during an outage means unmanaged battery drain which in some cases
could affect life support so it's worth being proactive.

This is too much information for even a savvy DIY so local automation
might be appropriate.

Direction Action Risk Automation Safe?
GRIDBATTERY Triggers shedding Low — conservative, extends runtime Yes
GRIDNONE Triggers shedding (max) Low — conservative Possibly, but BATTERY is more appropriate
BATTERYGRID Stops shedding Moderate — if actually off-grid, unmanaged drain reduces runtime User confirmation recommended
BATTERYNONE Escalates shedding Low Unlikely use case
* → UNKNOWN Behavior undefined Unknown No
* → PV Future / undefined Unknown No
* → GENERATOR Future / undefined Unknown No
You must be logged in to vote
0 replies
Comment options

dcj
Mar 5, 2026
Maintainer Author

@cayossarian

Thanks for the thorough analysis across your comments.
I want to address everything systematically, including a few items from your earlier posts that I hadn't fully responded to yet.

A note on terminology: I'll use DPS as shorthand for the dominant-power-source property throughout this reply.

Important: Scope of SPAN API

Before diving into the technical details, I want to be clear about scope.

The SPAN Panel and its integrated BESS/backup support are designed, engineered, tested, and listed to applicable electrical standards (NEC, UL). Load shedding, grid islanding, and MID management are product-level features operating within that certified framework.

SPAN API provides best-effort visibility into the panel's state and limited, specific control capabilities — it is intended to let clients understand and track the panel's behavior, not to replace or replicate the panel's built-in control logic.

An API client that attempts to implement its own load-shedding decisions, grid-state detection, or other critical automation is operating outside the scope of what SPAN API was designed and engineered for. Such use is entirely at the client developer's and homeowner's own risk and may void the SPAN Panel Limited Warranty. See the SPAN API Scope & Responsibility Model in the SPAN API documentation.

The technical discussion in this thread is provided to help integration developers understand how the panel works — it is not a specification for building critical systems on top of SPAN API.

DPS Hierarchy

You proposed:

1 - Grid / Generator (even if PV sending energy to grid)
2 - Battery when grid down
3 - PV (only if battery missing/depleted and panel can run islanded?)

That's correct. The hierarchy follows the grid-forming entity (GFE): whichever source is forming the electrical grid that the home is synchronized to. When the utility grid is present, it's the GFE regardless of what PV or battery are doing — they're grid-following. When islanded, the BESS inverter becomes the GFE. PV as a DPS value would apply only if a PV inverter were capable of grid-forming in isolation (rare today, though some newer Enphase systems may be heading this direction).

UNKNOWN and Fault States

You asked:

Is there another v2 signal that carries the on-grid/off-grid context during a fault, or is this information genuinely unavailable via eBus?

It's genuinely unavailable via eBus. Both v1 fault states (DSM_FAULTED_ON_GRID, DSM_FAULTED_OFF_GRID) map to UNKNOWN in v2, and no other published property distinguishes them. This is intentional: a fault state reflects a hardware condition (inverter fault, Microgrid Interconnect Device fault) where the panel may not be reliably supplying power in either direction. The on-grid/off-grid distinction during a fault is not actionable — "should I start the generator?" is not a safe automation decision when a hardware fault is active. These situations require physical service intervention.

For automation purposes, treating UNKNOWN as "something is wrong, alert the homeowner" is the appropriate response.

Panel-Independent Grid Detection

You asked whether the panel uses its own measurements to detect grid status, or relies entirely on BESS.

The panel has its own voltage monitoring that independently detects grid loss — voltage drop/sag on the main conductors. This is how the panel can respond immediately to an outage without waiting for the BESS to report it.

However, this monitoring is on the home side of the Microgrid Interconnect Device (MID) — the component within or alongside the BESS that manages grid disconnect/reconnect. That means:

  • Grid loss: Detected reliably. When the MID opens during an outage, voltage drops momentarily on the home side until the BESS inverter begins forming the microgrid.
  • Grid restoration while islanded: Not detectable. While the MID is open, the home side sees BESS-generated voltage, which is indistinguishable from utility voltage. Grid restoration on the utility side of the open MID is invisible to the panel.

This is the fundamental reason /set exists as a safeguard, and it directly affects your scenario matrix (see below).

Note on terminology: in generator installations, the equivalent component is typically an Automatic Transfer Switch (ATS) or Manual Transfer Switch (MTS) — sometimes called a transfer-switch — which is external to both SPAN and the generator. I'll use "MID" when discussing BESS configurations and "transfer-switch" for generator contexts.

DPS Update Source

DPS is determined from multiple inputs:

  • The BESS (grid state reporting, authoritative when communicating)
  • The panel's own voltage monitoring (detects grid loss independently)

It's not entirely BESS-dependent for detecting outages, but for detecting grid restoration while islanded, the BESS is the only source.

Firmware Reclaim After /set

I've confirmed the behavior. The panel's internal state is event-driven — when you /set DPS, the panel transitions its grid state accordingly. When the BESS reconnects and reasserts its authoritative grid state, that produces a new state transition that overrides the previous /set.

The key point: the most recent state transition wins. A user /set is not a persistent latch — it's a temporary override for the BESS-communication-loss window. Once the authoritative source (the BESS) is back, it reclaims control automatically.

One implementation note per the Homie Convention: values published to /set topics must be published non-retained. This is a client-side responsibility — integrations should publish /set commands with retain=false.

Generator Interaction

Per our generator support article, SPAN is always installed downstream of a transfer-switch (ATS or MTS), and "today, there is no communication wiring possible between the SPAN panel and an upstream generator." The panel sees whatever voltage the transfer-switch feeds it — DPS reports GRID when on generator because the panel literally cannot tell the difference. From the same article: "SPAN power flows will present all generator power as coming from the grid during an outage."

GENERATOR as a DPS value is reserved for possible future use — it is not currently active. Distinguishing generator from utility would require either communication with the generator/transfer-switch or a grid-side voltage sensor, neither of which exists in this configuration.

Also worth noting: no automatic load shedding is available with generators — that requires a compatible integrated BESS.

Non-Integrated BESS

One more data point for your configuration matrix. Per our storage integrations article, for non-compatible battery systems: "During an outage, the SPAN Home App will continue to report all energy coming into the home as grid power." This means DPS = GRID even when actually off-grid with a non-integrated BESS — the panel has no communication with the battery system and cannot know it's islanded. No automatic load shedding is available in this configuration.

This underscores the broader point: DPS reflects what the panel knows, which depends on what systems are communicating with it.

Scenario Matrix — Revisions

Your scenario matrix is a valuable framework. However, scenarios 3 and 5 need revision based on the MID topology described above.

When the MID is open (islanded), all published signals measure the home side: lugs-upstream/active-power, power-flows/grid, and voltage measurements all reflect BESS-supplied power. Grid restoration on the utility side of the open MID does not change these readings.

# Sequence DPS (stale) Detectable via passive signals? Assessment
1 BESS comms drop while on-grid, grid stays up GRID N/A Stale value is coincidentally correct
2 BESS comms drop while off-grid, grid stays down BATTERY N/A Stale value is coincidentally correct
3 Grid restored, BESS comms still down BATTERY No — MID is open, home-side measurements show BESS power only Only correctable via /set
4 BESS comms drop while on-grid, then grid drops GRID Yes — MID is still closed, panel's own voltage monitoring detects the outage Panel self-corrects via voltage sag detection
5 BESS comms drop while off-grid, then grid restores BATTERY No — same as #3, MID is open Only correctable via /set
6 BESS itself fails (comms + battery), grid up BATTERY or GRID Yesbess/connected = false is a distinct signal Detectable, but DPS may still be stale

The key insight: scenario 4 self-corrects (the panel detects grid loss independently), but scenarios 3 and 5 do not (the panel cannot detect grid restoration while islanded). Your multi-signal derivation doesn't help for 3 and 5 because the signals themselves are measuring the home side of the open MID.

Where Your Multi-Signal Approach Does Help

Your integration's combined signal approach (bess/grid-state + DPS + power-flows/grid + lugs-upstream/active-power) adds genuine value for:

  • Transient inconsistencies during normal BESS communication
  • Scenario 4 (grid drops while on-grid with BESS comms already lost — MID still closed, power measurements reflect reality)
  • Defense-in-depth for edge cases not yet enumerated

But for the core stale-DPS scenarios (3 and 5 — grid restored while islanded, BESS comms lost, MID open) — passive signals cannot help. /set is the only path.

/set Risk by Direction

Your risk analysis on the asymmetry of /set directions is a useful framework. To restate it with the scope caveat at the top of this reply in mind:

  • GRIDBATTERY (start shedding): The more conservative direction — worst case is unnecessary shedding, which is disruptive but not harmful.
  • BATTERYGRID (stop shedding): The higher-risk direction — getting this wrong means unmanaged battery drain, and as you correctly noted, this could affect critical equipment. Should require user confirmation or high-confidence corroborating signal.

Configuration Matrix

You and others have asked for a configuration matrix mapping system configurations to expected DPS values. That's a reasonable request — we'll take it under consideration as we continue to develop the API documentation.

Schema Documentation

We agree the $description could better convey the grid-forming-entity semantics — thanks for the suggestion.

Reference Links

Note: The SPAN eBus/MQTT API discussed in this thread is currently available on the SPAN Panel MAIN 32 model.

You must be logged in to vote
0 replies
Comment options

Super clear now, thanks!

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants

AltStyle によって変換されたページ (->オリジナル) /