Read and change charger settings
OCPP functional block B — Provisioning.
Every station carries settings: how often to send meter values, what to measure, how long to wait before giving up on a connection. OCPP 1.6 models these as flat configuration keys; OCPP 2.x replaces them with a structured device model. Both are reachable here, and which one applies depends on what the station negotiated.
Cached reads and live round-trips#
There are two ways to read a setting, and the difference matters.
Cached — fast, no round-trip, possibly stale:
curl "https://api.flowion.io/v1/chargers/$CHARGER/configuration?per_page=100" \
-H "Authorization: Bearer $TOKEN"
This returns what we last saw, backed by the most recent successful
get-configuration or change-configuration. It answers immediately and
works while the station is offline.
Live — a real command, blocking until the station answers:
curl -X POST https://api.flowion.io/v1/chargers/$CHARGER/commands/get-configuration \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"keys": ["MeterValueSampleInterval", "HeartbeatInterval"]}'
Omitting keys — or passing an empty array — asks for every setting the
station has, which is also how the cache gets refreshed. That refresh happens
on a timer anyway, so the cached read is rarely badly out of date.
Use the cache for display and inventory. Use the command when you are about to act on the value.
Changing a 1.6 setting#
curl -X POST https://api.flowion.io/v1/chargers/$CHARGER/commands/change-configuration \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"key": "MeterValueSampleInterval", "value": "60"}'
Both fields are strings — OCPP 1.6 has no types here. "60", not 60.
A 200 means the station answered, which is not the same as saying yes. The
answer can be Rejected (it will not), NotSupported (it does not have that
key), or RebootRequired (accepted, but not in effect until it restarts).
RebootRequired is easy to miss. The change is stored, the response is
successful, and nothing takes effect. If a setting change appears to do
nothing, check whether the station asked for a reboot and give it
a reset.
The 2.x device model#
OCPP 2.x replaces flat keys with components and variables. A component
is a part of the station — a connector, a meter, the controller. A variable is
a named value on that component, with attributes such as Actual and
Target.
Read the cached model:
curl "https://api.flowion.io/v1/chargers/$CHARGER/device-model?q=heartbeat" \
-H "Authorization: Bearer $TOKEN"
q filters over component name, component instance and variable name, which
is how you find anything in a model that can run to hundreds of entries.
Read and write live:
curl -X POST https://api.flowion.io/v1/chargers/$CHARGER/commands/get-variables \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"variables": [{"component": {"name": "OCPPCommCtrlr"},
"variable": {"name": "HeartbeatInterval"}}]}'
curl -X POST https://api.flowion.io/v1/chargers/$CHARGER/commands/set-variables \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"variables": [{"component": {"name": "OCPPCommCtrlr"},
"variable": {"name": "HeartbeatInterval"},
"value": "300"}]}'
Both requests are checked against the station's known device model before
being relayed, so a typo'd component or variable fails fast instead of
travelling to the station and coming back rejected. Pass
"skip_device_model_check": true to bypass that — useful when the cached
model is incomplete and you are certain the target exists.
Which one applies?#
The station's negotiated version decides. A 1.6 station has configuration keys
and no device model; a 2.x station has a device model. Check ocpp_version on
the charger before choosing an endpoint, or you will get a 422 telling you
the request is not expressible in that station's OCPP version.
Settings worth getting right#
| Concern | 1.6 key | Why |
|---|---|---|
| Telemetry frequency | MeterValueSampleInterval | Too long and sessions look empty; too short and you pay for traffic |
| What is measured | MeterValuesSampledData | Without an energy register you get transactions with no consumption |
| Session boundaries | StopTransactionOnEVSideDisconnect | Decides whether unplugging ends the session |
| Cable release | UnlockConnectorOnEVSideDisconnect | Decides whether a cable frees itself |
| Status noise | MinimumStatusDuration | Suppresses very short-lived status changes |
The last one is worth knowing about even if you never set it: a station may
legitimately omit status changes that lasted less than this, so a connector
can move from Preparing to Charging with nothing in between.
Asking a station to report#
Sometimes you do not want to change anything — you want the station to tell you something now:
curl -X POST https://api.flowion.io/v1/chargers/$CHARGER/commands/trigger-message \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"requested_message": "boot_notification"}'
Available triggers: boot_notification, heartbeat, meter_values,
status_notification, transaction_event, and custom on 2.1 with a
custom_trigger name.
Two things to know. Adding connector_id asks about one connector —
omitting it is not the same as asking about all of them, and 1.6 forbids
naming connector 0 here, so that request comes back 422 rather than
travelling.
And the accepted answer only means the station intends to send the message. Nothing correlates the triggered message with your request when it arrives, and nothing tracks whether an accepted trigger was ever honoured. Treat it as a nudge, not a request/response.
What the status codes mean#
Every command endpoint shares these:
| Code | Meaning |
|---|---|
200 | The station answered — including answering "no" |
409 | The station is not connected |
422 | Not expressible in this station's OCPP version, or not permitted |
502 | The station answered with something unusable |
503 | The command could not be sent |
504 | The station did not answer in time |