Commands¶
This tutorial demonstrates how to send commands to charge points in an OCPI application.
Overview¶
Commands allow an EMSP to control charging sessions at a CPO's charge points: - START_SESSION - Start a charging session - STOP_SESSION - Stop an active session - RESERVE_NOW - Reserve a connector - UNLOCK_CONNECTOR - Unlock a connector
Setup¶
Include the commands module:
from ocpi import get_application
from ocpi.core.enums import ModuleID, RoleEnum
from ocpi.modules.versions.enums import VersionNumber
app = get_application(
version_numbers=[VersionNumber.v_2_3_0],
roles=[RoleEnum.cpo, RoleEnum.emsp],
modules=[ModuleID.commands],
authenticator=YourAuthenticator,
crud=YourCrud,
)
Command Types¶
START_SESSION¶
Start a charging session:
command_data = {
"response_url": "https://emsp.example.com/commands/response",
"token": {
"uid": "TOKEN123",
"type": "RFID",
"contract_id": "CONTRACT001"
},
"location_id": "LOC001",
"evse_uid": "EVSE001",
"connector_id": "CONN001",
"authorization_reference": "AUTH_REF_123"
}
STOP_SESSION¶
Stop an active session:
command_data = {
"response_url": "https://emsp.example.com/commands/response",
"session_id": "SESS001"
}
RESERVE_NOW¶
Reserve a connector:
command_data = {
"response_url": "https://emsp.example.com/commands/response",
"token": {
"uid": "TOKEN123",
"type": "RFID",
"contract_id": "CONTRACT001"
},
"expiry_date": "2024-01-01T12:00:00Z",
"reservation_id": "RES001",
"location_id": "LOC001",
"evse_id": "EVSE001",
"connector_id": "CONN001",
"authorization_reference": "AUTH_REF_123"
}
UNLOCK_CONNECTOR¶
Unlock a connector:
command_data = {
"response_url": "https://emsp.example.com/commands/response",
"location_id": "LOC001",
"evse_id": "EVSE001",
"connector_id": "CONN001"
}
Implementing Command Handling¶
from ocpi.core.enums import Action, ModuleID, RoleEnum
class YourCrud(Crud):
@classmethod
async def do(
cls,
module: ModuleID,
role: RoleEnum | None,
action: Action,
*args,
data: dict | None = None,
**kwargs,
) -> dict:
"""Handle command execution."""
if module == ModuleID.commands:
command = kwargs.get("command")
response_url = data.get("response_url") if data else None
# Send command to charge point via OCPP
# This is a simplified example
if command == "START_SESSION":
# Send OCPP RemoteStartTransaction
result = await send_ocpp_command("RemoteStartTransaction", {
"idTag": data.get("token", {}).get("uid"),
"connectorId": data.get("connector_id")
})
return {
"result": "ACCEPTED" if result else "REJECTED",
"timeout": 30
}
elif command == "STOP_SESSION":
# Send OCPP RemoteStopTransaction
result = await send_ocpp_command("RemoteStopTransaction", {
"transactionId": data.get("session_id")
})
return {
"result": "ACCEPTED" if result else "REJECTED",
"timeout": 30
}
# ... handle other commands ...
return {}
Command Response¶
After executing a command, send the result to the response_url:
async def send_command_response(response_url: str, result: dict):
"""Send command result to EMSP."""
async with httpx.AsyncClient() as client:
await client.post(response_url, json={
"result": result.get("result"),
"timeout": result.get("timeout")
})
Command Results¶
Possible command results:
- ACCEPTED - Command was accepted
- CANCELED_RESERVATION - Reservation was canceled
- EVSE_OCCUPIED - EVSE is occupied
- FAILED - Command failed
- NOT_SUPPORTED - Command not supported
- REJECTED - Command was rejected
- TIMEOUT - Command timed out
- UNKNOWN_RESERVATION - Reservation not found
API Usage¶
Send START_SESSION Command¶
curl -X POST 'http://127.0.0.1:8000/ocpi/emsp/2.3.0/commands/START_SESSION' \
-H 'Authorization: Token your-token' \
-H 'Content-Type: application/json' \
-d '{
"response_url": "https://emsp.example.com/commands/response",
"token": {
"uid": "TOKEN123",
"type": "RFID"
},
"location_id": "LOC001",
"evse_uid": "EVSE001",
"connector_id": "CONN001"
}'
Send STOP_SESSION Command¶
curl -X POST 'http://127.0.0.1:8000/ocpi/emsp/2.3.0/commands/STOP_SESSION' \
-H 'Authorization: Token your-token' \
-H 'Content-Type: application/json' \
-d '{
"response_url": "https://emsp.example.com/commands/response",
"session_id": "SESS001"
}'
Best Practices¶
- Validate commands - Check command parameters before execution
- Handle timeouts - Set appropriate timeout values
- Send responses - Always send command results to response_url
- Error handling - Handle OCPP communication errors gracefully
- Log commands - Log all command attempts and results
- Check EVSE status - Verify EVSE availability before commands
Complete Example¶
See the Full CPO Example which includes command handling.