Implementing EV Charging Station Monitoring via Mobile Applications
EV charging stations operate under OCPP — Open Charge Point Protocol. OCPP 1.6 is JSON over WebSocket; OCPP 2.0.1 is more complex with enhanced security. Mobile applications don't communicate with the charger directly: between them sits a Central System (CSMS) that manages sessions and stores history. The developer's task: integrate with CSMS via REST API or WebSocket, plus optionally work with OCPI for roaming between networks.
Architecture: OCPP and CSMS
Electric Vehicle
↓ CCS / CHAdeMO / Type 2
Charging Station (Charge Point)
↓ OCPP 1.6/2.0.1 WebSocket
Central System (CSMS) — Everest, ChargePoint, EVCC, custom
↓ REST API / WebSocket
Mobile Application
Most common open-source CSMS: EVCC (German, Go, focus on home charging), Everest (Linux Foundation EV Charging, C++), SteVe (Java, for public networks). For commercial — ChargePoint, Driivz, Ampeco.
Session Monitoring
Key session data: connector status (Available/Occupied/Charging/Faulted), charging power (kW), energy delivered (kWh), duration, vehicle SoC (if OCPP 2.0.1 and vehicle supports it).
WebSocket subscription to updates via CSMS API:
class ChargingSessionRepository(
private val wsClient: OkHttpClient,
private val restApi: CsmsApi,
) {
private var webSocket: WebSocket? = null
private val _sessionFlow = MutableStateFlow<ChargingSession?>(null)
val sessionFlow: StateFlow<ChargingSession?> = _sessionFlow.asStateFlow()
fun observeSession(stationId: String, connectorId: Int) {
val request = Request.Builder()
.url("wss://csms.example.com/api/v1/stations/$stationId/events")
.header("Authorization", "Bearer $accessToken")
.build()
webSocket = wsClient.newWebSocket(request, object : WebSocketListener() {
override fun onMessage(webSocket: WebSocket, text: String) {
val event = json.decodeFromString<StationEvent>(text)
when (event.type) {
"MeterValues" -> _sessionFlow.update { current ->
current?.copy(
currentPowerKw = event.payload.activePower,
energyDeliveredKwh = event.payload.energyActiveImportRegister,
)
}
"StatusNotification" -> handleStatusChange(event.payload.status)
"TransactionEvent" -> handleTransactionEvent(event.payload)
}
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
// Exponential backoff for reconnection
scheduleReconnect(stationId, connectorId, t)
}
})
}
}
Remote Charging Start
Remote Start Transaction via CSMS API is one of the basic scenarios. User scans QR-code on the station (with stationId and connectorId encoded), application authorizes the transaction:
// iOS
func startCharging(stationId: String, connectorId: Int) async throws -> Transaction {
let request = RemoteStartRequest(
connectorId: connectorId,
idTag: currentUser.rfidToken, // user token for station authorization
chargingProfile: ChargingProfile(
chargingProfilePurpose: .txProfile,
chargingSchedule: ChargingSchedule(
chargingRateUnit: .watts,
chargingSchedulePeriod: [
ChargingSchedulePeriod(startPeriod: 0, limit: 11000) // 11 kW
]
)
)
)
return try await csmsClient.remoteStart(stationId: stationId, request: request)
}
OCPP 1.6 RemoteStartTransaction.conf returns Accepted or Rejected — this only confirms the station accepted the command, not that charging started. Actual session start is a separate StartTransaction.req from the station to CSMS. Status must be tracked via WebSocket or polling.
Charging Station Map
For public networks — map with clustering, filtering by connector type (CCS, CHAdeMO, Type 2) and power. OCPI (Open Charge Point Interface) is the roaming protocol between operators, allowing display of stations from different networks.
On Flutter with Google Maps SDK or MapLibre:
Future<List<ChargingStation>> loadNearbyStations(LatLng center) async {
return _ocpiClient.getLocations(
latitude: center.latitude,
longitude: center.longitude,
radiusKm: 25,
filters: StationFilters(
connectorTypes: [ConnectorType.ccs2, ConnectorType.type2],
minPowerKw: 11,
availableOnly: true,
),
);
}
Clustering via google_maps_cluster_manager for large lists — without it, 500+ points cause lag during zoom.
Payment and Tarification
Tarification in EV applications is complex. The station can tarify by kWh, by time, with minimum session amount, or by combination. OCPI TariffElement describes all variants. Payment is via Stripe or local payment gateway integrated with CSMS.
Developing an application for monitoring and managing charging stations with integration into existing CSMS: 4-6 weeks. Development from scratch including CSMS integration, map, payment, and roaming via OCPI: 3-4 months. Cost is calculated after analyzing the stack and requirements.







