Remote Control Flows - CSMS Developer Guide
Based on OCPP 2.0.1 Edition 4 Specification (Part 2, Section F). This guide covers all remote control flows from the CSMS (Charging Station Management System) perspective.
1. Overview
IntroductionSection F describes remote control capabilities that allow the CSMS to control Charging Stations remotely. All flows in this section are CSMS-initiated - the CSMS sends the initial request to the Charging Station.
Remote Control Categories
Remote Transaction Control
Start and stop charging transactions remotely.
F01-F04
Unlock Connector
Remotely unlock a connector to help drivers who have problems unplugging their cable.
F05
Remote Trigger
Trigger the Charging Station to send specific messages on demand.
F06
OCPP Message Direction Convention
| Direction | Meaning |
|---|---|
CSMS → CS | CSMS sends a CALL (request) to the Charging Station |
CS → CSMS | Charging Station sends a CALL (request) to the CSMS |
Important: All flows in Section F are CSMS-initiated — the CSMS sends the initial request to the Charging Station. The CS responds and may send follow-up messages to confirm or report the results of the operation.
2. F01 — Remote Start Transaction: Cable Plugin First
F01Summary
The CSMS remotely requests a Charging Station to start a transaction after the EV driver has already plugged in the cable. The cable being plugged in is a prerequisite.
Use Cases
- Mobile app "start charging" button
- CSO helpdesk remote start
- Third-party integrations
Sequence Diagram
EV Driver Charging Station CSMS
| | |
|--- plug in cable ------->| |
| |-- StatusNotificationReq ------>| (connector = Occupied)
| |<- StatusNotificationResp ------|
| | |
| |-- TransactionEventReq -------->| (eventType=Started,
| | triggerReason=CablePluggedIn | chargingState=EVConnected,
| | transactionId=AB1234) | transactionId=AB1234)
| |<- TransactionEventResp --------|
| | |
| | ** External trigger ** | (e.g. mobile app)
| | |
| |<- RequestStartTransactionReq-- | (idToken, remoteStartId=123)
| |-- RequestStartTransactionResp> | (status=Accepted,
| | | transactionId=AB1234)
| | |
| | [CS matches remoteStartId |
| | with transactionId] |
| | |
| | [opt: AuthorizeRemoteStart=true]
| |-- AuthorizeReq --------------->| (idToken)
| |<- AuthorizeResp ---------------| (idTokenInfo)
| | |
| |-- TransactionEventReq -------->| (eventType=Updated,
| | chargingState=Charging, | triggerReason=RemoteStart,
| | remoteStartId=123) | remoteStartId=123)
| |<- TransactionEventResp --------|CSMS Actions
1. Send RequestStartTransactionRequest
The CSMS initiates the remote start by sending this message to the Charging Station.
| Field | Type | Required | Description |
|---|---|---|---|
| remoteStartId | integer | Yes | Unique ID for this start request |
| idToken | IdTokenType | Yes | Token to use for authorization |
| evseId | integer | No | EVSE to start on (if omitted, CS selects) |
| groupIdToken | IdTokenType | No | Group token for group-based authorization |
| chargingProfile | ChargingProfileType | No | Optional charging profile (purpose MUST be TxProfile) |
2. Handle RequestStartTransactionResponse
The CS responds indicating whether it accepted or rejected the request.
| Field | Type | Description |
|---|---|---|
| status | RequestStartStopStatusEnumType | Accepted or Rejected |
| transactionId | string (max 36) | Existing transaction ID if cable was already plugged in |
| statusInfo | StatusInfoType | Additional info (reasonCode + details) |
CSMS Handling Logic
- Accepted: The CS will attempt to start the transaction. If transactionId is returned, store the mapping: remoteStartId → transactionId
- Rejected: The CS cannot start. Check statusInfo for the reason (EVSE unavailable, occupied, reserved, invalid profile, etc.)
3. Handle TransactionEventRequest
After accepting, the CS sends TransactionEventRequest with triggerReason=RemoteStart and remoteStartId.
Important: The CSMS MUST check authorization status when processing this TransactionEventRequest. If authorization is not Accepted, the CS must stop energy transfer.
4. Handle AuthorizeRequest (Optional)
If AuthorizeRemoteStart is true, the CS will send AuthorizeRequest before starting energy transfer. The CSMS must respond with authorization status.
Rejection Conditions
| Condition | CS Response |
|---|---|
| EVSE is Unavailable or Faulted | status = Rejected |
| EVSE is Occupied with authorized transaction | status = Rejected |
| EVSE is reserved for different idToken | status = Rejected |
| No evseId and CS doesn't support arbitrary EVSE | status = Rejected |
| Invalid ChargingProfile | status = Rejected, reasonCode = InvalidProfile |
3. F02 — Remote Start Transaction: Remote Start First
F02Summary
The CSMS sends the remote start request before the EV driver plugs in the cable.
The CS must wait for the cable to be connected within the EVConnectionTimeOut period.
Use Cases
- Mobile app pre-authorization ("start charging, then plug in")
- Pre-authorized sessions
Sequence Diagram
External Trigger CSMS Charging Station
| | |
|-- remote start() ---->| |
| |-- RequestStartTransactionReq-->| (idToken=ABCD,
| | | remoteStartId=123)
| |<- RequestStartTransactionResp--| (status=Accepted)
| | |
| | [opt: AuthorizeRemoteStart=true]
| |<- AuthorizeReq ----------------| (idToken=ABCD)
| |-- AuthorizeResp -------------->| (idTokenInfo)
| | |
| |<- TransactionEventReq ---------| (eventType=Started,
| | transactionId=AB1234, | triggerReason=RemoteStart,
| | remoteStartId=123) | idToken=ABCD)
| |-- TransactionEventResp ------->|
| | |
| ** EV driver plugs in cable within ConnectionTimeOut **
| | |
| |<- StatusNotificationReq -------| (Occupied)
| |-- StatusNotificationResp ----->|
| | |
| |<- TransactionEventReq ---------| (eventType=Updated,
| | chargingState=EVConnected, | triggerReason=CablePluggedIn)
| |-- TransactionEventResp ------->|
| | |
| |<- TransactionEventReq ---------| (eventType=Updated,
| | chargingState=Charging, | triggerReason=ChargingStateChanged)
| |-- TransactionEventResp ------->|Timeout Handling
If the cable is NOT plugged in within EVConnectionTimeOut:
If TxStopPoint does NOT contain ParkingBayOccupancy
The CS ends the transaction and sends TransactionEventRequest(eventType=Ended, stoppedReason=Timeout, triggerReason=EVConnectTimeout)
If TxStopPoint contains ParkingBayOccupancy
The CS deauthorizes the transaction and sends TransactionEventRequest(triggerReason=EVConnectionTimeout). Transaction ends normally when the driver leaves.
CSMS Action: Process the TransactionEventRequest with eventType=Ended and update the transaction record accordingly.
Key Differences from F01
| Aspect | F01 (Cable First) | F02 (Remote Start First) |
|---|---|---|
| Cable state | Already plugged in | Not plugged in yet |
| Transaction exists at request time | Yes (usually) | No |
| transactionId in response | Often returned | Not returned |
| Timeout risk | No | Yes (EVConnectionTimeOut) |
| triggerReason on Started | RemoteStart | RemoteStart |
Note: The CSMS actions for F02 are the same as F01 (send RequestStartTransactionRequest, handle response, handle AuthorizeRequest if needed, handle TransactionEventRequest). The main difference is the timing and the timeout handling.
4. F03 — Remote Stop Transaction
F03Summary
The CSMS remotely requests a Charging Station to stop an ongoing transaction by sending a RequestStopTransactionRequest with the transactionId.
Use Cases
- Mobile app "stop charging" button
- CSO helpdesk remote stop
- Automated stop from billing system
Sequence Diagram
CSMS Charging Station
| |
|-- RequestStopTransactionReq--> | (transactionId="AB1234")
|<- RequestStopTransactionResp-- | (status=Accepted)
| |
| [CS stops energy transfer] |
| |
|<- TransactionEventReq ---------| (eventType=Ended,
| triggerReason=RemoteStop, | stoppedReason=Remote)
|-- TransactionEventResp ------->|CSMS Actions
1. Send RequestStopTransactionRequest
A very simple message with only one required field.
| Field | Type | Required | Description |
|---|---|---|---|
| transactionId | string (max 36) | Yes | The identifier of the transaction to stop |
2. Handle RequestStopTransactionResponse
| Field | Type | Description |
|---|---|---|
| status | RequestStartStopStatusEnumType | Accepted or Rejected |
| statusInfo | StatusInfoType | Additional info about the status |
CSMS Handling Logic
- Accepted: The CS will stop the transaction. Wait for TransactionEventRequest(eventType=Ended)
- Rejected: The CS cannot stop the transaction. Possible reason: the transactionId is unknown to the CS
3. Handle TransactionEventRequest (eventType=Ended)
After accepting the stop request, the CS will send a TransactionEventRequest with:
eventType = EndedtriggerReason = RemoteStopstoppedReason = Remote
The CSMS should:
- Process the final meter values if included
- Mark the transaction as ended in the database
- Initiate billing if applicable
Error Handling
- • If the CS responds with Rejected, verify the transactionId is correct
- • The CSMS may use GetTransactionStatusRequest (E14) to check if the transaction is still active before attempting a remote stop
5. F04 — Remote Stop ISO 15118 Charging from CSMS
F04Summary
The CSMS remotely stops an ISO 15118 charging session. This flow is identical to F03 from the CSMS perspective — the only difference is in how the Charging Station handles the ISO 15118 protocol internally.
Use Cases
Same as F03, but specifically for ISO 15118 sessions.
Sequence Diagram
CSMS Charging Station EV
| | |
|-- RequestStopTransactionReq--->| (transactionId) |
|<- RequestStopTransactionResp---| (status=Accepted) |
| | |
| | [ISO 15118 session |
| | termination between |
| | CS and EV] |
| | |
|<- TransactionEventReq ---------| (eventType=Ended, |
| triggerReason=RemoteStop, | stoppedReason=Remote) |
|-- TransactionEventResp ------->| |CSMS Actions
Identical to F03. The CSMS sends the same RequestStopTransactionRequest and handles the same response. The ISO 15118 protocol negotiation (power delivery, session stop) happens internally between the CS and the EV — the CSMS does not need to be aware of these details.
The Charging Station is responsible for gracefully stopping the ISO 15118 session and including signed meter values if configured.
6. F05 — Remotely Unlock Connector
F05Summary
The CSMS sends an UnlockConnectorRequest to unlock a specific connector on a specific EVSE. This is used to help EV drivers who have problems
unplugging their cable.
Use Cases
- Customer support (driver can't unplug)
- Automated unlock after session end
- Remote maintenance
Sequence Diagrams
Basic unlock (no ongoing transaction):
CSMS Charging Station
| |
|-- UnlockConnectorReq -------->| (evseId=1, connectorId=1)
|<- UnlockConnectorResp --------| (status=Unlocked)
| |Unlock with ongoing transaction:
CSMS Charging Station
| |
|-- UnlockConnectorReq -------->| (evseId=1, connectorId=1)
| |
| | [CS stops transaction]
| |
|<- TransactionEventReq --------| (eventType=Ended,
| triggerReason=UnlockCommand)| stoppedReason=Remote)
|-- TransactionEventResp ------>|
| |
|<- UnlockConnectorResp --------| (status=Unlocked)Response Handling
UnlockConnectorRequest
| Field | Type | Description |
|---|---|---|
| evseId | integer | The EVSE identifier containing the connector to unlock |
| connectorId | integer | The connector identifier to unlock |
UnlockConnectorResponse
| Value | Meaning | CSMS Action |
|---|---|---|
| Unlocked | Connector was successfully unlocked | Success — inform the user/operator |
| UnlockFailed | Failed to unlock (mechanical failure, etc.) | Report failure — may need on-site assistance |
| OngoingAuthorizedTransaction | Cannot unlock due to ongoing authorized transaction | May need to stop transaction first (F03) before retrying |
| UnknownConnector | The evseId/connectorId is not recognized | Verify evseId and connectorId are correct |
Workflow Decision Tree
Want to unlock connector?
├── Send UnlockConnectorRequest(evseId, connectorId)
│ ├── Response: Unlocked → Success
│ ├── Response: UnlockFailed → Report failure, may need on-site help
│ ├── Response: OngoingAuthorizedTransaction
│ │ ├── Send RequestStopTransactionRequest first
│ │ ├── Wait for TransactionEventRequest(Ended)
│ │ └── Retry UnlockConnectorRequest
│ └── Response: UnknownConnector → Check evseId/connectorIdKey Requirements
- If an ongoing unauthorized transaction exists, CS SHALL stop it and unlock
- If an ongoing authorized transaction exists, CS SHALL respond OngoingAuthorizedTransaction
- If the connector is successfully unlocked and a transaction was stopped, CS SHALL send TransactionEventRequest(eventType=Ended, triggerReason=UnlockCommand)
7. F06 — Trigger Message
F06Summary
The CSMS sends a TriggerMessageRequest to ask the Charging Station to send a specific message immediately (outside of its normal schedule).
This is useful for on-demand diagnostics, status polling, and refreshing stale data.
Use Cases
- Request current meter values
- Force a status update
- Request a new BootNotification
- Request firmware status
Sequence Diagram
CSMS Charging Station
| |
|-- TriggerMessageReq --------->| (requestedMessage=StatusNotification,
| | evse={id: 1})
|<- TriggerMessageResp ---------| (status=Accepted)
| |
|<- StatusNotificationReq ------| (triggered message)
|-- StatusNotificationResp ---->|Message Types
The requestedMessage parameter
supports the following values:
| Value | Triggered Message | EVSE-specific? | Description |
|---|---|---|---|
| BootNotification | BootNotificationRequest | No | Request CS to resend boot info |
| LogStatusNotification | LogStatusNotificationRequest | No | Request current log upload status |
| FirmwareStatusNotification | FirmwareStatusNotificationRequest | No | Request firmware update status |
| Heartbeat | HeartbeatRequest | No | Request immediate heartbeat |
| MeterValues | MeterValuesRequest | Yes | Request current meter readings for an EVSE |
| StatusNotification | StatusNotificationRequest | Yes | Request connector status for an EVSE |
| TransactionEvent | TransactionEventRequest | Yes | Request updated transaction info for an EVSE |
| SignChargingStationCertificate | SignCertificateRequest | No | Trigger CS to request CSMS certificate |
| SignV2GCertificate | SignCertificateRequest | No | Trigger CS to request V2G certificate |
Note: For EVSE-specific messages (marked "Yes"), you MUST provide the evse parameter with the EVSE ID. If required but not provided, the CS will respond with Rejected.
Common Use Cases
| Scenario | requestedMessage | evse |
|---|---|---|
| Check if CS is alive | Heartbeat | — |
| Get current connector status | StatusNotification | {id: 1} |
| Get current meter readings | MeterValues | {id: 1} |
| Force re-registration | BootNotification | — |
| Check firmware update progress | FirmwareStatusNotification | — |
| Request latest transaction data | TransactionEvent | {id: 1} |
Response Handling
Accepted: The CS will send the requested message. Wait for the corresponding incoming message from CS.
Rejected: The CS will not send the message (e.g., wrong EVSE, conditions not met). Log the rejection.
NotImplemented: The requested message type is not supported by this CS. Do not retry.
8. Message Schema Reference
SchemasComplete message schemas with JSON examples for all remote control operations.
RequestStartTransaction
Request Example
{
"remoteStartId": 123,
"idToken": {
"idToken": "ABCD1234",
"type": "ISO14443"
},
"evseId": 1,
"groupIdToken": {
"idToken": "GROUP001",
"type": "Central"
},
"chargingProfile": {
"id": 1,
"stackLevel": 0,
"chargingProfilePurpose": "TxProfile",
"chargingProfileKind": "Relative",
"chargingSchedule": [
{
"id": 1,
"chargingRateUnit": "W",
"chargingSchedulePeriod": [
{
"startPeriod": 0,
"limit": 11000.0
}
]
}
]
}
}Required fields: remoteStartId, idToken
Response Example
{
"status": "Accepted",
"transactionId": "AB1234-5678",
"statusInfo": {
"reasonCode": "NoError"
}
}Required fields: status
IdTokenEnumType Values
Central — Authorization by CSMSeMAID — Electro-Mobility Account IDISO14443 — RFID tag (ISO 14443)ISO15693 — RFID tag (ISO 15693)KeyCode — PIN codeLocal — Locally-issued IDMacAddress — MAC addressNoAuthorization — No auth neededRequestStopTransaction
Request Example
{
"transactionId": "AB1234-5678"
}Required fields: transactionId
Response Example
{
"status": "Accepted",
"statusInfo": {
"reasonCode": "NoError"
}
}Required fields: status
UnlockConnector
Request Example
{
"evseId": 1,
"connectorId": 1
}Required fields: evseId, connectorId
Response Example
{
"status": "Unlocked",
"statusInfo": {
"reasonCode": "NoError"
}
}Required fields: status
Possible Status Values
Unlocked — Successfully unlockedUnlockFailed — Mechanical failureOngoingAuthorizedTransaction — Cannot unlockUnknownConnector — Invalid evseId/connectorIdTriggerMessage
Request Example
{
"requestedMessage": "StatusNotification",
"evse": {
"id": 1,
"connectorId": 1
}
}Required fields: requestedMessage
Response Example
{
"status": "Accepted",
"statusInfo": {
"reasonCode": "NoError"
}
}Required fields: status
Possible Status Values
Accepted — CS will send the requested messageRejected — CS will not send (wrong EVSE, conditions not met)NotImplemented — Message type not supported by this CSOCPP-J Wire Format
All messages use the OCPP-J (JSON over WebSocket) format:
CALL (Request)
[2, "msg-001", "RequestStartTransaction", {
"remoteStartId": 123,
"idToken": {
"idToken": "ABCD",
"type": "ISO14443"
}
}]CALLRESULT (Response)
[3, "msg-001", {
"status": "Accepted",
"transactionId": "TX-001"
}]CALLERROR (Error)
[4, "msg-001", "InternalError", "Unable to process request", {}]Shared Types Reference
StatusInfoType
Present in most responses for additional context.
| Field | Type | Required | Description |
|---|---|---|---|
| reasonCode | string (max 20) | Yes | Predefined code (case-insensitive) |
| additionalInfo | string (max 512) | No | Human-readable details |
ChargingProfile Constraints
When including a ChargingProfile in RequestStartTransactionRequest:
| Constraint | Rule |
|---|---|
| chargingProfilePurpose | MUST be TxProfile |
| transactionId | MUST NOT be set (CS will associate it) |
| chargingSchedule | 1–3 schedules allowed |
| chargingSchedulePeriod | 1–1024 periods per schedule |
| chargingRateUnit | W (Watts) or A (Amperes) |