Plan States and Status Lines
This document describes how the Overview tab derives device state and the status text shown per device. Only managed devices are included in the plan snapshot; unmanaged devices are hidden from the Overview tab.
Core State Fields (per device)
- currentState: "on" | "off" | "unknown" | "not_applicable"
- Derived from device on/off state when available.
not_applicableis used for temperature-only devices withoutonoff.
- Derived from device on/off state when available.
- plannedState: "keep" | "shed" | "inactive"
- "keep" means allow device to stay in its current state or restore if off.
- "shed" means device should be off or set to its shed temperature because PELS is actively suppressing it for capacity reasons.
- "inactive" means the device is not currently activatable, but PELS is not suppressing it. This is used for EV chargers that are unplugged, discharging, missing a usable state, or missing a usable power estimate.
- shedAction: "turn_off" | "set_temperature"
- shedTemperature: number | null
- plannedTarget: number | null (target temperature if applicable)
- reason: string (shown as the Status line in the Overview tab)
State Transitions (high level)
- Normal active (plannedState = "keep"):
- plannedState = "keep"
- reason = "keep" (or "keep (recently restored)")
- Shedding due to overshoot:
- If headroom < 0, lowest-priority devices are added to shedSet.
- plannedState = "shed", reason reflects the active cap:
- "shed due to capacity"
- "shed due to daily budget"
- When both constraints are effectively aligned, reason is still reported as "shed due to capacity".
- Hourly budget exhausted:
- plannedState = "shed"
- reason = "shed due to hourly budget"
- Device is off and can be restored:
- If not in shortfall and enough headroom:
- plannedState = "keep"
- reason = "restore (need XkW, headroom YkW)"
- If in shortfall:
- plannedState = "shed"
- reason = "shortfall (need XkW, headroom YkW)"
- Note: this headroom is operational plan headroom (effective soft limit context), while shortfall entry itself is based on projected hourly hard-cap budget breach.
- If not in shortfall and enough headroom:
- Cooldown / stabilization:
- After shedding or restoring, restoration is throttled.
- plannedState = "shed"
- reason = cooldown or stabilization messages (see list below).
- EV unavailable / not resumable:
- If an EV charger is unplugged, discharging, has an unknown charging state, or lacks a usable power estimate:
- plannedState = "inactive"
- reason reflects the availability issue, for example:
- "inactive (charger is unplugged)"
- "inactive (charger is discharging)"
- "inactive (charger state unknown)"
- "inactive (charger power unknown)"
- If an EV charger is unplugged, discharging, has an unknown charging state, or lacks a usable power estimate:
- Swap-based restore:
- If a higher-priority device needs restore but headroom is insufficient:
- Lower-priority on devices are marked "shed" to free headroom.
- The higher-priority device becomes a pending swap target until restored.
- If a higher-priority device needs restore but headroom is insufficient:
Overview Tab "State" Line (UI)
The Overview tab shows a State line derived from plannedState and currentState:
- Shed (powered off): plannedState === "shed" and shedAction === "turn_off"
- Shed (lowered temperature): plannedState === "shed" and shedAction === "set_temperature"
- Inactive: plannedState === "inactive"
- Restoring: plannedState === "keep" and currentState is "off" or "unknown"
- Active: plannedState === "keep" and currentState is "on"
- Active (temperature-managed): plannedState === "keep" and currentState is "not_applicable"
- Capacity control off: controllable === false
- Unknown: fallback if state is not clear
Overview Tab "Status" Line (reason values)
These are the main reason strings generated by the planner. The UI shows reason or "Waiting for headroom". Parentheses indicate dynamic values.
- keep
- keep (recently restored)
- capacity control off
- restore (need XkW, headroom YkW)
- shed due to capacity
- shed due to daily budget
- shed due to hourly budget
- shortfall (need XkW, headroom YkW)
- cooldown (shedding, Ss remaining)
- cooldown (restore, Ss remaining)
- headroom cooldown (Ss remaining; usage X -> YkW)
- headroom cooldown (Ss remaining; recent PELS shed)
- headroom cooldown (Ss remaining; recent PELS restore)
- swap pending
- swap pending (NAME)
- swapped out for NAME
- insufficient headroom (need XkW, headroom YkW)
- shedding active
- restore throttled
- inactive (charger is unplugged)
- inactive (charger is discharging)
- inactive (charger state unknown)
- inactive (unknown charging state 'VALUE')
- inactive (charger power unknown; configure expected power or let PELS observe a charging peak)
State vs Status
The State line carries the on/off vs shed distinction (including "Shed (powered off)" vs "Shed (lowered temperature)"). Status lines are now simplified and avoid repeating the state, focusing on why the device is blocked or changing.
shed is reserved for capacity suppression and its short stabilization/cooldown period. inactive is neutral and means the device is not currently available for restoration, but not because PELS is suppressing it.
Notes on min-temperature shedding
Devices configured with shedAction "set_temperature" are still marked as plannedState "shed". They share the same reason strings as turn-off shedding, including "shortfall (need XkW, headroom YkW)" when in shortfall.