Charging Control
Endpoints for controlling the charging process — set current limits, pause/resume charging, switch charge modes, and manage current allocation.
Current limit composition
The station does not have a single current-limit input. Instead, the offered current is computed as the minimum across three independent lanes, each owned by a different source:
| Lane | Topic | Written by | Active when |
|---|---|---|---|
| External | salia/extctrl_limit (alias: grid_current_limit) | External controllers — EMS / FEMS / OCPP / home-automation | Always |
| Internal | salia/intctrl_limit | The station's own charge controller (eco solar tracking, heartbeat fallback, phase-switch cooldown, etc.) | Always |
| Manual | salia/manctrl_limit | The built-in web UI in manual charge mode | Always |
| LMD | ci/global/dyn_current_limit/lmd_limit (set via salia/LM/internal/max_amp) | Internal Load Management, when enabled | Only when Internal LM is active (see Load Management tag) |
Each lane fans out to ci/global/dyn_current_limit/{external,internal,manual,lmd}_limit
and the effective limit is the minimum across all active lanes.
Additional bounds (physical hardware limit, configured max_amp,
configured socketmaxamp, cable current limit) further cap the result.
Troubleshooting tip: If raising grid_current_limit does not raise
the actually offered current, one of the other lanes is lower. The most
common culprit is intctrl_limit, which the internal regulator may have
pushed down. Read all three topics to see which one is binding; if
needed, override intctrl_limit directly (see its PUT endpoint).
Get current charge mode
Returns the active charge mode. See ChargeMode schema for possible values.
Get current charge mode › Responses
Charge mode retrieved
High-level behavior profile of the charging station. Determines how the station's internal regulator sets the offered current and how it interacts with solar/battery data, phase switching, and the configured min/max Amperes. See each value for the concrete side effects applied when switching into that mode.
Selecting a mode is persistent — the choice survives a reboot. Switching to an unknown value is silently ignored.
eco — Solar-surplus charging
The station tracks available PV / grid surplus and modulates the
internal-lane current so the vehicle consumes (approximately) only
what the PV system is exporting. It targets the configured min_amp
as a floor and uses metering data (salia/mains/...) to decide how
much headroom is available. With Power+ (salia/ecoplus) enabled,
the station is allowed to supplement insufficient surplus with grid
power; with Power+ disabled (default), it will pause rather than
pull from the grid.
Side effects on switching into eco:
salia/manctrl_limitis reset tomax_amp(as on every mode change).- Internal limit (
ci/global/dyn_current_limit/internal_limit) is set to:min_ampif the EV is currently charging (CP state C or D) — so the solar-surplus regulator can take over from a known-low floor.max_ampotherwise.
- No automatic phase switch.
ecoplusis not changed; whatever was previously configured remains.
power — Maximum-power charging
The station ignores solar surplus and delivers the highest current the
hardware and configuration allow. This is the right mode for integrators
that want a deterministic "charge as fast as possible" baseline on top of
which an external controller can lower the current via grid_current_limit.
Side effects on switching into power:
salia/manctrl_limitis reset tomax_amp.- Internal limit (
ci/global/dyn_current_limit/internal_limit) is set tomax_amp. salia/ecoplusis forced to"0"(Power+/Eco+ is disabled, because it is a feature of eco mode and has no meaning here).- If phase switching is supported on the hardware
(
phase_switch_enabled), an automatic switch to 3-phase is triggered by publishingsalia/phase_switching/setphase = "3". If phase switching is not supported, the station stays on whatever phase configuration it is wired for.
manual — Manual current control
The station does not run solar-surplus logic and does not force any
phase change. The offered current is whatever the manual lane
(salia/manctrl_limit) is set to — typically by the built-in web UI's
current slider. External integrators writing to grid_current_limit
still apply, since the effective offered current remains the minimum
across the external / internal / manual lanes.
Side effects on switching into manual:
salia/manctrl_limitis reset tomax_amp(same as on every mode change).- No change to phase, ecoplus, or the internal lane.
Choosing a mode as an integrator
- To control current from an external EMS / FEMS: use
power(ormanual) and then drivegrid_current_limit.ecois unsuitable because the internal regulator will keep adjusting the internal lane based on its own solar-surplus view, potentially overriding your setpoint. - If the offered current is not rising when you raise
grid_current_limit, check the internal lane (salia/intctrl_limit) — see Current limit composition.
Set charge mode
Sets the charging mode. The accepted values and their full behavior
(including side effects applied on switching — phase switch, ecoplus,
internal-limit reset, manctrl_limit reset) are documented on the
ChargeMode schema.
Quick reference:
eco— solar-surplus charging; internal regulator adjusts current.power— maximum-power charging; auto-switches to 3-phase if supported; disables ecoplus.manual— current followsmanctrl_limit(typically the web UI slider); no auto-adjust, no automatic phase change.
The new mode is persisted across reboots. Unknown values are silently ignored (no error returned).
Set charge mode › Request Body
salia/chargemodeHigh-level behavior profile of the charging station. Determines how the station's internal regulator sets the offered current and how it interacts with solar/battery data, phase switching, and the configured min/max Amperes. See each value for the concrete side effects applied when switching into that mode.
Selecting a mode is persistent — the choice survives a reboot. Switching to an unknown value is silently ignored.
eco — Solar-surplus charging
The station tracks available PV / grid surplus and modulates the
internal-lane current so the vehicle consumes (approximately) only
what the PV system is exporting. It targets the configured min_amp
as a floor and uses metering data (salia/mains/...) to decide how
much headroom is available. With Power+ (salia/ecoplus) enabled,
the station is allowed to supplement insufficient surplus with grid
power; with Power+ disabled (default), it will pause rather than
pull from the grid.
Side effects on switching into eco:
salia/manctrl_limitis reset tomax_amp(as on every mode change).- Internal limit (
ci/global/dyn_current_limit/internal_limit) is set to:min_ampif the EV is currently charging (CP state C or D) — so the solar-surplus regulator can take over from a known-low floor.max_ampotherwise.
- No automatic phase switch.
ecoplusis not changed; whatever was previously configured remains.
power — Maximum-power charging
The station ignores solar surplus and delivers the highest current the
hardware and configuration allow. This is the right mode for integrators
that want a deterministic "charge as fast as possible" baseline on top of
which an external controller can lower the current via grid_current_limit.
Side effects on switching into power:
salia/manctrl_limitis reset tomax_amp.- Internal limit (
ci/global/dyn_current_limit/internal_limit) is set tomax_amp. salia/ecoplusis forced to"0"(Power+/Eco+ is disabled, because it is a feature of eco mode and has no meaning here).- If phase switching is supported on the hardware
(
phase_switch_enabled), an automatic switch to 3-phase is triggered by publishingsalia/phase_switching/setphase = "3". If phase switching is not supported, the station stays on whatever phase configuration it is wired for.
manual — Manual current control
The station does not run solar-surplus logic and does not force any
phase change. The offered current is whatever the manual lane
(salia/manctrl_limit) is set to — typically by the built-in web UI's
current slider. External integrators writing to grid_current_limit
still apply, since the effective offered current remains the minimum
across the external / internal / manual lanes.
Side effects on switching into manual:
salia/manctrl_limitis reset tomax_amp(same as on every mode change).- No change to phase, ecoplus, or the internal lane.
Choosing a mode as an integrator
- To control current from an external EMS / FEMS: use
power(ormanual) and then drivegrid_current_limit.ecois unsuitable because the internal regulator will keep adjusting the internal lane based on its own solar-surplus view, potentially overriding your setpoint. - If the offered current is not rising when you raise
grid_current_limit, check the internal lane (salia/intctrl_limit) — see Current limit composition.
Set charge mode › Responses
Charge mode set successfully
resultGet grid current limit
Returns the current value of the external-lane current limit in Amperes.
This is a read-back of what grid_current_limit / salia/extctrl_limit
was last set to — not necessarily the current actually being offered to
the EV. The offered current is the minimum across all three lanes (see
Current limit composition); to see the
effective offered value, read ci/evse/basic/offered_current_limit.
Get grid current limit › Responses
Grid current limit retrieved
Set grid current limit (external-lane setpoint)
Sets the external-lane current limit in Amperes. This is the primary endpoint for external controllers (EMS, FEMS, OCPP backends, home-automation) to request a charging current.
- Body key is literally
grid_current_limit(nosalia/orport0/prefix), per server convention. - The value is clamped on the server to the station's configured
min_current/max_currentrange (typically 6–32 A). Writing0bypasses the clamp and effectively stops charging (no current offered). - Internally maps to
salia/extctrl_limit(external lane of Current limit composition).
Important — limit is a maximum, not a setpoint. The effective
offered current is min(external, internal, manual, <hardware bounds>).
If raising this value does not raise the actually offered current,
another lane is binding. See the troubleshooting note under
Current limit composition; if the
internal lane (salia/intctrl_limit) is the constraint, you may need
to override it directly.
Sequencing after phase switch: Wait until phase_switching/status
returns "idle" before calling this endpoint. See Phase Switching
documentation.
Set grid current limit (external-lane setpoint) › Request Body
grid_current_limitCurrent limit in Amperes (0 to stop, 6–32 typical range)
Set grid current limit (external-lane setpoint) › Responses
Grid current limit set successfully
resultPause charging
Pauses the active charging session. The EV remains connected but no current
is offered. Use resumecharging to resume.
Pause charging › Request Body
salia/pausechargingSet to "1" to pause charging
Pause charging › Responses
Charging paused successfully
resultResume charging
Get external control current limit
Current value of the external-lane limit in Amperes — the limit set by external controllers (EMS / OCPP / home-automation).
salia/extctrl_limit and grid_current_limit represent the same lane.
Writing either topic updates this value; the only differences are the
server-side clamping applied to grid_current_limit and the difference
in body key.
See Current limit composition for how this lane combines with the internal and manual lanes.
Get external control current limit › Responses
External control limit retrieved
Set external control current limit
Sets the external-lane limit in Amperes (0 to stop, 6–32 typical
range). Writes the same lane as grid_current_limit, but uses the raw
salia/extctrl_limit topic key and does not apply the server-side
min/max clamping that grid_current_limit does. Pass a value you have
already validated against the configured min_current / max_current
range.
See Current limit composition — setting this alone is not enough to guarantee the offered current actually rises; the internal and manual lanes can still be lower.
Set external control current limit › Responses
Limit set successfully
resultGet internal control current limit
Current value of the internal regulator limit, in Amperes.
This is the "internal" lane of the effective current limit (see the
Current limit composition note on the
Charging Control tag). Under normal operation the station's own charge
controller writes this value itself — for example when dropping to
minimum during a heartbeat timeout, when throttling during a
phase-switching cooldown, or when adjusting to available solar surplus
in eco mode.
Reading this endpoint shows the current value the internal regulator has decided on. It can (and does) change without client action.
Get internal control current limit › Responses
Internal control limit retrieved
Override internal control current limit
Directly sets the internal regulator limit in Amperes. Use this endpoint only when you need to bypass the station's internal current-setpoint logic.
When to use this instead of grid_current_limit / extctrl_limit
Most external controllers (energy management systems, FEMS, OCPP
backends) should set grid_current_limit (alias: salia/extctrl_limit),
which represents the external limit lane.
However, the effective offered current is the minimum across three
independent lanes — external, internal, and manual. If the internal
regulator has set its lane below your external setpoint (e.g. because
of a stale value, a recent phase switch, or an eco-mode adjustment),
raising only grid_current_limit will have no effect: the internal
lane is still the binding constraint.
In those cases, writing intctrl_limit directly raises the internal
lane so your external setpoint can actually take effect. This is the
workaround recommended by the vendor when grid_current_limit alone
does not reliably propagate through to the offered current.
Caveats
- The station's internal charge controller will overwrite this
value on the next regulation cycle if it has its own opinion (for
example after a heartbeat timeout, an eco-mode recompute, or a
phase-switch event). Writing
intctrl_limitis not a persistent override — it holds only until the controller decides otherwise. Clients that need a lasting override typically have to re-write it on a timer. - This write does not go through the min/max clamping applied to
grid_current_limit(which uses the station's configuredmin_current/max_current). You are responsible for passing a value within the configured range. - Integer Amperes, as a string (e.g.
"16").
Override internal control current limit › Request Body
salia/intctrl_limitInternal-lane current limit in Amperes (integer, e.g. "16").
Override internal control current limit › Responses
Internal control limit set successfully
resultGet manual control current limit
Current value of the manual-lane limit in Amperes. This lane is
driven by the built-in web UI's current slider in manual charge
mode; the station also resets this value to max_amp on every
charge-mode change. External integrators do not normally write to this
lane.
Get manual control current limit › Responses
Manual control limit retrieved
Set charging current
Get Eco+ / Power+ mode status
Returns whether Eco+ (also labelled Power+ in some UIs) is currently enabled.
"0"— disabled (default). Inecocharge mode, if PV / surplus becomes insufficient to sustain charging atmin_amp, the station pauses charging after the configuredecoplus_timeout(see below) and waits for surplus to return."1"— enabled. Inecocharge mode, if surplus becomes insufficient, the station keeps charging by drawing supplementary power from the grid rather than pausing. This is the behavior historically labeled "Power+".
Eco+ is only meaningful in eco charge mode. In power and manual
modes the flag is stored but has no runtime effect. Switching the
station into power mode automatically resets this flag to "0"
(see the ChargeMode schema for that side effect).
Related configuration:
- Eco+ pause delay — delay in seconds (range 0–300, default 30) before Eco+ pauses charging on insufficient surplus. Not exposed as a REST endpoint in this spec; configurable via the web UI under Mains → Eco+ pause delay.
mains.battprio(Battery Priority) — a related Eco+ feature that lets the station start/stop charging based on a home-battery SoC threshold. Also configured via the web UI, not this API.
Get Eco+ / Power+ mode status › Responses
Eco+ status retrieved
Enable or disable Eco+ / Power+ mode
Enables or disables Eco+ (aka Power+) — see the GET description for full behavior.
Effect of writing
- The value is persisted across reboots (internally stored under
the legacy name
mains.overcurrent, which refers to the same flag). - No further MQTT side effects are triggered by the write itself; the flag is consulted by the charge controller on its next regulation cycle.
- The flag is only meaningful while the station is in
ecocharge mode. Writing it inpowerormanualhas no immediate effect on the charging session — and, because switching topowermode auto-resets the flag to"0", setting Eco+ "on" before switching to power will be silently overridden.
Accepted values
The canonical values are "0" (disable) and "1" (enable). The
server additionally accepts "on", "enable", "true" as synonyms
for "1" (anything else is treated as disable). Clients should
stick to "0" / "1" for forward compatibility.
Enable or disable Eco+ / Power+ mode › Request Body
salia/ecoplus"1" to enable Eco+ / Power+, "0" to disable.
Enable or disable Eco+ / Power+ mode › Responses
Eco+ mode updated
resultEnable/disable or refresh the heartbeat watchdog
Controls the heartbeat watchdog, a safety feature for external controllers (energy management systems, OCPP backends, custom integrations) that are driving charging via the API.
What it does
When the watchdog is enabled and the station has not received any
heartbeat write in the last 60 seconds, the charge controller
forcibly lowers the offered current to the configured minimum
(min_amp, typically 6 A) until a new write arrives. This prevents a
runaway charging session if the controlling client crashes, loses
network, or hangs.
When disabled (default), the absence of heartbeat writes has no effect.
Writing to this endpoint has two effects
- Resets the watchdog timer, regardless of the value sent. Any write
— even
"off"or"saveconfig"— is treated as a ping. - Applies the value's semantics:
"on"— Enable the watchdog. In-memory only; lost on reboot unless followed by"saveconfig"."off"— Disable the watchdog. In-memory only."saveconfig"— Persist the current enabled/disabled state so it survives a reboot. Does not itself toggle the state.
Typical usage pattern for an external controller:
Code
Side effects and caveats
- While the watchdog has timed out, charging is not paused — current is
dropped to
min_amp(≈ 6 A). The EV keeps charging at reduced power. - The 60-second window is measured from the last write on this topic, not from any other API activity. A busy client must still ping this topic specifically.
- The persisted value (
saveconfig) is only re-read at daemon start. - There is no GET endpoint for the current watchdog state; it is not exposed on any readable MQTT topic.
Enable/disable or refresh the heartbeat watchdog › Request Body
salia/heartbeaton— enable watchdog (and reset timer)off— disable watchdog (and reset timer)saveconfig— persist current enabled/disabled state (and reset timer)
Enable/disable or refresh the heartbeat watchdog › Responses
Heartbeat updated
result
