The message
// CSMS -> charge point
[2, "19223215", "RemoteStopTransaction", { "transactionId": 770142 }]
// Charge point -> CSMS
[3, "19223215", { "status": "Accepted" }]One field in, one field out. Accepted or Rejected.
Accepted means the charger recognised the transaction and will attempt to stop it. It does not mean power has stopped. The confirmation is the StopTransaction that follows, typically within seconds but occasionally much longer on a DC unit ramping down. Showing a driver “charging stopped” on the acknowledgement is the standard bug.Why Rejected happens
| Cause | Is it a problem? |
|---|---|
| Transaction already ended naturally | No — the driver's goal is met |
Unknown transactionId | Sometimes — check whether your ID mapping is stale |
| Charger is mid-reboot | Transient; the session will close on its own |
| Firmware does not support it | Configuration — the charger cannot be stopped remotely at all |
The first row is the common case and it is not a failure. By the time your command arrives the driver may have unplugged. From their perspective everything worked.
The race, and how to resolve it
Charging sessions end on their own constantly. The command and the natural end race, and the outcomes look like failures:
- Send the command. Show stopping, never stopped.
- Wait for the StopTransaction, not for the acknowledgement.
- On
Rejected, check transaction state before reporting anything. An already-closed transaction is success. - On no response, do not retry blindly. Check whether a StopTransaction arrived; the charger may have stopped and failed to answer.
- Set a hard fallback. If nothing resolves within a minute or two, tell the driver to unplug manually rather than leaving a spinner running.
Retrying is close to harmless here — unlike remote start, a duplicate stop cannot create a second session. But it is still pointless if the charger is unreachable, and it delays telling the driver something useful.
The chain from OCPI
On a roaming platform this is the last hop of a longer chain. A driver taps stop in an eMSP app they got from a company that owns no chargers:
Driver app (eMSP)
│ OCPI STOP_SESSION { session_id }
▼
CPO / CSMS
│ map session_id → transactionId
│ OCPP RemoteStopTransaction { transactionId }
▼
Charge point
│ stops delivering power
│ OCPP StopTransaction
▼
CPO ──► OCPI CommandResult ──► eMSP
──► OCPI Session → COMPLETED
──► OCPI CDR (once metering finalised)Every hop can fail independently, and the mapping step in the middle is where platforms most often break: an OCPI session_id that no longer resolves to a live transactionId produces a stop request the CSMS cannot route. Keep that mapping authoritative and current.
The OCPI STOP_SESSION CommandResult should be sent once the charger has actually stopped — not on the OCPP acknowledgement. Forwarding the acknowledgement as a result propagates the same false confirmation one layer up.
Production lessons
- Never report success on
Accepted. Wait for StopTransaction. - Treat
Rejectedon an already-ended session as success. - Keep the session-to-transaction mapping current, or roaming stops fail to route.
- Debounce driver taps. One command, pending state until resolved.
- Give the driver a manual fallback after a bounded wait.
- Measure command-to-StopTransaction latency per charger model. A model that consistently takes 30 seconds is a product decision you need to design copy around.
Frequently asked questions
No. It means the charger recognised the transaction and will attempt to stop it. Confirmation comes only from the StopTransaction that follows, which is usually seconds later but can be longer on DC units ramping down.
Most often because the transaction already ended naturally — the driver unplugged before the command arrived. It can also mean an unknown transaction ID, a charger mid-reboot, or firmware that does not support remote stop.
Largely yes — unlike remote start, a duplicate stop cannot create a second session. But retrying blindly is pointless if the charger is unreachable, so check whether a StopTransaction has arrived before retrying.
Through OCPI STOP_SESSION to the CPO, which maps the OCPI session_id to its internal OCPP transactionId and issues RemoteStopTransaction to the charge point. The OCPI CommandResult should be sent once the charger actually stops, not on the OCPP acknowledgement.