AOS Simulator
1. Architecture Overview
AOS Simulator는 충전 인프라 테스트를 위한 통합 플랫폼입니다. CSMS(Charging Station Management System), 충전기 시뮬레이터, 테스트 자동화 엔진이 하나의 서버에 통합되어 있습니다. AOS Simulator is an integrated platform for EV charging infrastructure testing. It combines a CSMS (Charging Station Management System), charger simulator, and test automation engine into a single server.
Core Components
| Component | File | DescriptionDescription |
|---|---|---|
| CSMS Server | server/csms-server.js | WebSocket 서버. 충전기 연결 수신, 프록시 모드, 메시지 전송WebSocket server. Accepts charger connections, proxy mode, message dispatch |
| OCPP Handler | server/ocpp-handler.js | 메시지 처리, 상태 관리, 이벤트 시스템Message processing, state management, event system |
| Test Runner | server/test-runner.js | 테스트 시나리오 실행 엔진, 배치 처리Test scenario execution engine, batch processing |
| Charger Client | server/charger-client.js | 스마트 충전기 시뮬레이터 (CS 역할)Smart charger simulator (acts as CS) |
| Backend Client | server/csms-backend-client.js | CSMS 백엔드 API 연동CSMS backend API integration |
| OCPP Schemas | server/ocpp-schemas.js | OCPP 2.0.1 메시지 템플릿 (29+11 actions)OCPP 2.0.1 message templates (29+11 actions) |
2. Operating Modes
시뮬레이터는 3가지 모드로 동작합니다: The simulator operates in 3 modes:
Test용 CSMS API Server
시뮬레이터가 CSMS 역할. 충전기가 직접 연결하여 메시지를 처리.Simulator acts as CSMS. Chargers connect directly and messages are processed locally.
Proxy (AOS)
AOS와 CSMS 사이에 투명 프록시로 동작. 트래픽을 관찰하면서 CSMS 명령 주입(역제어) 가능. 환경변수 또는 Web UI에서 동적으로 Upstream URL을 설정/해제할 수 있습니다.Transparent proxy between AOS and CSMS. Observes traffic while injecting CSMS commands (remote control). Upstream URL can be set/cleared dynamically via environment variable or Web UI.
Standalone CS
시뮬레이터가 충전기(CS) 역할로 CSMS에 직접 연결. AOS 없이 독립 테스트 가능.Simulator connects to CSMS as a charger (CS). Independent testing without AOS.
Mode Comparison
| Feature | Local | Proxy (AOS) | Standalone |
|---|---|---|---|
| AOS 필요Requires AOS | No | Yes | No |
| CSMS 필요Requires CSMS | No | Yes | Yes |
| 시뮬레이터 역할Simulator Role | CSMS | Proxy + Observer | CS (Charger) |
| 활성화 조건Activation | Proxy OFFProxy OFF | UPSTREAM_CSMS_URL 또는 UI에서 Proxy URL 설정or set Proxy URL via UI | connectMode: "standalone" |
| 역제어 (Remote Control)Remote Control | 가능Yes | 가능Yes | 불가 (CS 역할)No (CS role) |
| Test Step Types | send, wait | send, wait | cs_send, wait |
Proxy Mode Flow
Standalone Mode Flow
OCPP Protocol Versions (1.6 / 2.0.1 Dual Support)
시뮬레이터의 모든 모드(LOCAL/Proxy/Standalone)가 OCPP 1.6 과 2.0.1 을 듀얼 지원합니다. SIM connect 시 protocol 옵션으로 선택 (default 2.0.1). All modes (LOCAL/Proxy/Standalone) support both OCPP 1.6 and 2.0.1. Select via the protocol option when connecting (default 2.0.1).
| Action / 항목 | OCPP 1.6 | OCPP 2.0.1 |
|---|---|---|
| Subprotocol | ocpp1.6 | ocpp2.0.1 |
| BootNotification | chargePointVendor / chargePointModel / chargePointSerialNumber (flat) | chargingStation.{vendorName, model, serialNumber} (nested) |
| StatusNotification | connectorId, errorCode, status · 9종 enum (Available/Preparing/Charging/SuspendedEV/SuspendedEVSE/Finishing/Reserved/Unavailable/Faulted) | evse{id,connectorId}, connectorStatus · 5종 enum |
| Authorize | idTag (string) | idToken{idToken,type} |
| Transaction 시작/종료 | StartTransaction / StopTransaction (transactionId 정수, CSMS 발급) | TransactionEvent (Started/Updated/Ended) (transactionId 문자열, CS 발급) |
| MeterValues sampledValue | {value, measurand, unit} 평탄 | {value, measurand, unitOfMeasure:{unit}} 중첩 |
| TriggerMessage 가능 액션 | 6종 (Boot/Diag/Firmware/Heartbeat/Meter/Status) | 14종+ |
| UI 선택 위치 | Charger Simulator 페이지 → OCPP Version 셀렉트 (선택값은 localStorage 보존) | |
| API 옵션 | POST /api/sim/connect { ..., protocol: "1.6" | "2.0.1" } | |
| Test scenario 메타 | "ocppVersion": "1.6" | "2.0.1" (시나리오 JSON 의 top-level 키). v16/ 디렉토리는 default 1.6. | |
/ocpp, 2.0.1 → /ocpp201). path 가 이미 있으면 그대로 + chargerId 만 append.
PROXY upstream path auto-append: If proxy upstream URL has no path, default is auto-added per subprotocol (1.6 → /ocpp, 2.0.1 → /ocpp201). If a path is present, it is used as-is + /{chargerId}.
3. Quick Start
Local Development
# Install dependencies
npm install
# Run in local CSMS mode
node server.js
# Run in proxy mode (upstream CSMS required)
UPSTREAM_CSMS_URL=ws://cpos-websocket:8080 node server.js
서버가 시작되면 http://localhost:3000에서 Web UI에 접속할 수 있습니다.
Once the server starts, access the Web UI at http://localhost:3000.
테스트 시나리오 실행Run a Test Scenario
# Run a single test scenario
curl -X POST 'http://localhost:3000/api/test/run' \
-H 'Content-Type: application/json' \
-d '{"scenarioId":"TC_B_01","chargerId":"CP001"}'
# Response: {"runId":"run-...","status":"passed"}
4. Configuration
Environment Variables
| Variable | Default | Description |
|---|---|---|
PORT | 3000 | HTTP/WebSocket 서버 포트HTTP/WebSocket server port |
UPSTREAM_CSMS_URL | (empty) | Upstream CSMS WebSocket URL. 설정 시 Proxy 모드 활성화. Web UI(Chargers 페이지) 또는 POST /api/csms/proxy로 런타임 변경 가능Upstream CSMS WebSocket URL. Enables Proxy mode when set. Can be changed at runtime via Web UI (Chargers page) or POST /api/csms/proxy |
UPSTREAM_REDIS_URL | (empty) | Upstream Redis URL (stale connection 정리용)Upstream Redis URL (for stale connection cleanup) |
UPSTREAM_REDIS_KEY_PREFIX | cpos:conn: | Redis 연결 키 prefixRedis connection key prefix |
PENDING_MSG_KEY_PREFIX | ocpp:message:pending:test:TD: | Redis 펜딩 메시지 키 prefixRedis pending message key prefix |
BACKEND_RELAY_TIMEOUT | 8000 | Backend relay 응답 대기 (ms)Backend relay response timeout (ms) |
CSMS_BACKEND_URL | (empty) | csms-backend REST API URLcsms-backend REST API URL |
BASE_PATH | / | Web UI base path (reverse proxy 환경)Web UI base path (for reverse proxy) |
5. Web UI Guide
AOS의 Web UI는 3개 섹션으로 구성됩니다: AOS Web UI consists of 3 sections:
CSMS Section
OCPP 2.0.1 표준 기능을 제공하는 기본 제품 영역입니다. Core product area providing OCPP 2.0.1 standard features.
- Dashboard — 연결된 충전기, 트랜잭션, 시스템 상태 실시간 모니터링Real-time monitoring of chargers, transactions, system status
- Chargers — 충전기 목록/상태 관리, Proxy Mode 동적 설정 (외부 CSMS 연결 → 역제어), Auto Discovery(Redis), CSMS/SIM/Backend 소스 구분Charger list/status, dynamic Proxy Mode (connect to external CSMS for remote control), Auto Discovery via Redis, CSMS/SIM/Backend source badges
- Remote Control — Simulator/Backend 탭으로 29가지 OCPP 명령 실행Execute 29 OCPP commands via Simulator/Backend tabs
- Smart Charging — 충전 프로파일, 전력 분배(DLM)Charging profiles, power distribution (DLM)
- Authorization — 인증 토큰 관리, Local Authorization ListToken management, Local Authorization List
- Reservations — 충전기 예약 관리Charger reservation management
- Configuration — GetVariables, SetVariables, GetBaseReportGetVariables, SetVariables, GetBaseReport
- Security — 인증서 관리, Basic Auth 설정Certificate management, Basic Auth settings
- Firmware — 펌웨어 업데이트 관리Firmware update management
- Meter Values — 실시간 미터 데이터 (에너지, 전력, 전압, 전류, SoC)Real-time meter data (energy, power, voltage, current, SoC)
- Diagnostics — 변수 모니터링, 진단Variable monitoring, diagnostics
- Display Messages / Tariff & Cost / Data Transfer
AOS Testing Section
충전기 시뮬레이션 및 테스트 자동화 도구입니다. Charger simulation and test automation tools.
- Virtual Chargers — 사내 서버에 영구 저장되는 가상 충전기 프로필 (chargerId, csmsUrl, OCPP 버전, 자격증명). 한 번 등록하면 SIM/Test Runner에서 즉시 재사용.
data/charger-profiles.json공유.Persistent virtual charger profiles stored on internal server (chargerId, csmsUrl, OCPP version, credentials). Register once and reuse from SIM/Test Runner. Shared viadata/charger-profiles.json. - Charger Simulator — 단일 충전기 수동 테스트 (WebSocket 연결, Quick Actions, Transaction Events). OCPP 1.6/2.0.1 토글 + 프로필 즉시 불러오기/저장.Single charger manual testing (WebSocket, Quick Actions, Transaction Events). OCPP 1.6/2.0.1 toggle + instant load/save profile.
- Test Runner — 테스트 시나리오 자동 실행 (개별/배치), 카테고리 필터링. 혼용 batch 자동 분할: OCPP 1.6과 2.0.1 시나리오가 섞여 있으면 버전별 그룹으로 자동 분리해 순차 실행 (그룹 경계에서 disconnect → reconnect로 protocol 전환).Test scenario automation (individual/batch), category filtering. Mixed-version batch auto-split: when OCPP 1.6 and 2.0.1 scenarios are mixed, auto-split into per-version groups and run sequentially (protocol switches via disconnect → reconnect at group boundaries).
- AOS Console — OCPP 메시지 편집/전송, 실시간 로그 뷰어, 방향/소스별 필터링OCPP message composer, real-time log viewer, direction/source filtering
AOS Demo Section
데모 시연 및 시각화 도구입니다. Demo and visualization tools.
- Demo Dashboard — 1~500대 다중 충전기 시뮬레이션, 9가지 시나리오 자동 실행1-500 multi-charger simulation, 9 scenario types
- Scenario Flowchart — 충전 시나리오 Swimlane 흐름도Charging scenario Swimlane diagrams
- Mobile App Mock — 모바일 앱 시뮬레이터 (미오픈)Mobile app simulator (not yet available)
6. Standalone CS Mode
How It Works
- Test Runner가
connectMode: "standalone"으로 시나리오 시작Test Runner starts a scenario withconnectMode: "standalone" - 시뮬레이터가
ws://cpos-websocket:8080/ocpp201/{chargerId}에 WebSocket 클라이언트로 연결Simulator connects as WebSocket client tows://cpos-websocket:8080/ocpp201/{chargerId} - Basic Auth 헤더 자동 첨부 (사전 설정된 비밀번호 사용)Basic Auth header automatically attached (using pre-configured password)
cs_send스텝으로 CS→CSMS 메시지 전송 (BootNotification, StatusNotification 등)cs_sendsteps send CS→CSMS messages (BootNotification, StatusNotification, etc.)- CSMS 응답 수신 및 검증Receive and validate CSMS responses
- CSMS에서 보내는 명령 (TriggerMessage 등)에 자동 응답Auto-respond to CSMS commands (TriggerMessage, etc.)
- 시나리오 완료 후 자동 연결 해제Automatic disconnection after scenario completion
cs_send Step Type
cs_send는 충전기(CS)가 CSMS에 보내는 메시지를 시뮬레이션합니다.
cs_send simulates messages sent from charger (CS) to CSMS.
{
"type": "cs_send",
"description": "Send BootNotification to CSMS",
"action": "BootNotification",
"params": {
"model": "OCPP-Simulator",
"vendorName": "Autocrypt",
"serialNumber": "SIM-001",
"firmwareVersion": "1.0.0"
},
"validate": { "status": "Accepted" },
"storeAs": "bootResult"
}
Supported CS→CSMS Actions
| Action | Key Params | Expected Response |
|---|---|---|
| BootNotification | model, vendorName, serialNumber, firmwareVersion | status, interval, currentTime |
| Heartbeat | (none) | currentTime |
| StatusNotification | status, evseId, connectorId | {} |
| Authorize | idToken, type | idTokenInfo.status |
| TransactionEvent | eventType, triggerReason, evseId, idToken | idTokenInfo |
| MeterValues | evseId, meterValue | {} |
| NotifyReport | reportData | {} |
| FirmwareStatusNotification | status | {} |
| LogStatusNotification | status | {} |
Standalone Scenario Example
Standalone 시나리오는 connectMode: "standalone"을 지정하고 cs_send 스텝으로 CS→CSMS 메시지를 전송합니다.
Standalone scenarios specify connectMode: "standalone" and use cs_send steps to send CS→CSMS messages.
{
"id": "TC_CUSTOM_01",
"name": "Custom Standalone Test",
"category": "Custom",
"connectMode": "standalone",
"steps": [
{
"type": "cs_send",
"action": "BootNotification",
"params": { "model": "Simulator", "vendorName": "Autocrypt" },
"validate": { "status": "Accepted" }
},
{
"type": "cs_send",
"action": "StatusNotification",
"params": { "status": "Available", "evseId": 1 }
}
]
}
7. API Reference - CSMS
GET /api/csms/chargers
연결된 충전기 목록 조회List connected chargers
POST /api/csms/send/:chargerId
CSMS→CS 명령 전송Send CSMS→CS command
// Request Body
{ "action": "TriggerMessage", "params": { "requestedMessage": "BootNotification" } }
// Response
{ "success": true, "response": { "status": "Accepted" } }
POST /api/csms/auth/password/:chargerId
충전기 Basic Auth 비밀번호 설정Set charger Basic Auth password
{ "password": "your-secret" }
POST /api/csms/disconnect/:chargerId
충전기 연결 강제 해제Force disconnect charger
GET /api/csms/proxy
현재 프록시 모드 상태 조회 (default upstream + per-charger routes 포함)Get current proxy mode status (includes default upstream and per-charger routes)
// Response
{
"proxyMode": true,
"upstreamUrl": "wss://default-csms-host",
"routes": [
{ "chargerId": "CP001", "upstreamUrl": "wss://customer-a-csms" },
{ "chargerId": "CP002", "upstreamUrl": "wss://customer-b-csms" }
]
}
POST /api/csms/proxy
Default upstream CSMS URL 동적 설정/해제. 매핑되지 않은 충전기는 이 URL로 fallback.Set/clear the default upstream CSMS URL. Unmapped chargers fall back to this URL.
// Set default upstream
{ "upstreamUrl": "wss://default-csms-host" }
// Clear default (mapped chargers still proxy via their routes)
{ "upstreamUrl": "" }
GET /api/csms/proxy/routes
충전기별 라우팅 매핑 전체 조회List all per-charger upstream routes
// Response
{ "routes": [
{ "chargerId": "CP001", "upstreamUrl": "wss://customer-a-csms" }
] }
POST /api/csms/proxy/routes
충전기별 라우팅 추가/갱신. 해당 chargerId가 접속하면 default 대신 이 URL로 forward됨.Add or update a per-charger route. The given chargerId will be forwarded to this URL instead of the default upstream.
// Request
{ "chargerId": "CP001", "upstreamUrl": "wss://customer-a-csms" }
// Response
{ "success": true, "chargerId": "CP001", "upstreamUrl": "wss://customer-a-csms" }
DELETE /api/csms/proxy/routes/:chargerId
특정 chargerId 라우팅 매핑 제거. 이후 default upstream으로 fallback.Remove a per-charger route. The chargerId will fall back to the default upstream.
// Response
{ "success": true, "chargerId": "CP001", "deleted": true }
upstreamUrl로 fallback → ③ 둘 다 없으면 LOCAL 모드(시뮬레이터 자체 CSMS)로 동작. 변경은 이후 새로 connect하는 충전기에만 적용됩니다 (기존 연결 유지).
Routing priority: ① per-charger route → ② default upstreamUrl fallback → ③ LOCAL (simulator's own CSMS) if neither is set. Changes apply only to new connections (existing sessions stay routed as-is).
8. API Reference - Test Runner
GET /api/test/scenarios
전체 시나리오 목록 조회 (카테고리별 그룹)List all scenarios (grouped by category)
POST /api/test/run
단일 시나리오 실행Run a single scenario
{
"scenarioId": "TC_B_01",
"chargerId": "CP001",
"connectMode": "proxy" // "proxy" (default) or "standalone"
}
// Response
{ "runId": "run-1770886031263", "status": "passed" }
GET /api/test/run
현재 실행 중인 테스트 상태 조회 (스텝별 결과 포함)Get current test execution status (includes per-step results)
POST /api/test/run/abort
실행 중인 테스트 중단Abort running test
GET /api/test/history
최근 50건 테스트 실행 이력Last 50 test execution history
9. API Reference - Standalone
POST /api/csms/standalone/connect
수동으로 upstream CSMS에 충전기로 연결Manually connect as charger to upstream CSMS
{
"chargerId": "CP001",
"password": "your-password", // optional (uses saved password if not provided)
"upstreamUrl": "ws://cpos-websocket:8080" // optional (uses UPSTREAM_CSMS_URL)
}
POST /api/csms/standalone/disconnect
standalone 연결 해제Disconnect standalone connection
{ "chargerId": "CP001" }
POST /api/csms/standalone/send
수동으로 CS→CSMS 메시지 전송Manually send CS→CSMS message
{
"chargerId": "CP001",
"action": "BootNotification",
"params": { "model": "Test", "vendorName": "Autocrypt" }
}
// Response
{ "success": true, "response": { "status": "Accepted", "interval": 300 } }
10. API Reference - Batch
POST /api/test/batch
여러 시나리오 순차 실행 (배치)Run multiple scenarios sequentially (batch)
{
"scenarioIds": ["TC_B_01", "TC_B_02", "TC_B_03"],
"chargerId": "CP001",
"options": {
"connectMode": "proxy",
"stopOnFail": false,
"resetBetween": true
}
}
resetBetween: true로 설정하면 각 시나리오 사이에 Smart Charger 상태를 초기화합니다. stopOnFail: true로 설정하면 첫 실패 시 배치가 중단됩니다.
Batch Options: Set resetBetween: true to reset Smart Charger state between scenarios. Set stopOnFail: true to abort the batch on first failure.
GET /api/test/batch
현재 배치 실행 상태 (시나리오별 결과, 진행률)Current batch execution status (per-scenario results, progress)
POST /api/test/batch/abort
배치 실행 중단Abort batch execution
11. Scenario Format
테스트 시나리오는 test-scenarios/ 디렉토리에 JSON 파일로 저장됩니다.
Test scenarios are stored as JSON files in the test-scenarios/ directory.
{
"id": "TC_X_01", // Unique ID (filename without .json)
"name": "Test Case Name", // Display name
"category": "X", // Category letter (A-P)
"categoryName": "Category", // Category display name
"description": "...", // Description
"connectMode": "standalone", // Optional: "proxy" (default) or "standalone"
"steps": [ ... ] // Array of step objects
}
12. Step Types
send - CSMS→CS Command
CSMS에서 충전기로 명령 전송. Proxy/Local 모드에서 사용. Send command from CSMS to charger. Used in Proxy/Local modes.
{
"type": "send",
"action": "RequestStartTransaction",
"params": { "idToken": "AABBCCDD", "evseId": 1 },
"validate": { "status": "Accepted" },
"viaBackend": true, // Optional: route through csms-backend API
"storeAs": "startResult"
}
cs_send - CS→CSMS Message
충전기에서 CSMS로 메시지 전송. Standalone 모드 전용. Send message from charger to CSMS. Standalone mode only.
{
"type": "cs_send",
"action": "BootNotification",
"params": { "model": "Sim", "vendorName": "Test" },
"validate": { "status": "Accepted" },
"storeAs": "bootResult"
}
wait - Wait for Message
특정 메시지 수신 대기. 양쪽 모드 모두 사용 가능. Wait for a specific message. Available in all modes.
{
"type": "wait",
"match": {
"action": "StatusNotification",
"payload": { "connectorStatus": "Available" } // partial match
},
"timeout": 30000,
"triggerMessage": "StatusNotification", // Optional: send TriggerMessage to prompt CS
"triggerDelay": 10000, // Optional: delay before TriggerMessage (default: 10s proxy, 0s local)
"storeAs": "statusAvailable"
}
triggerMessage Mechanism
triggerMessage가 설정되면, 먼저 wait 리스너를 등록한 후 TriggerMessage 명령을 CSMS→CS로 발송하여 충전기가 해당 메시지를 보내도록 유도합니다.
When triggerMessage is set, a wait listener is registered first, then a TriggerMessage command is sent CSMS→CS to prompt the charger to send the expected message.
- wait 리스너 등록 (레이스 컨디션 방지를 위해 먼저 등록)Register wait listener first (to prevent race conditions)
triggerDelay만큼 대기 (프록시 모드 기본 10초 — 자연 발생 기회 부여)Wait fortriggerDelay(default 10s in proxy mode — allows natural occurrence)- TriggerMessage(requestedMessage) CSMS→CS 전송Send TriggerMessage(requestedMessage) CSMS→CS
- CS가 해당 메시지 발송 → wait 매칭 → 스텝 성공CS sends the message → wait matches → step passes
triggerMessage: "BootNotification"을 사용합니다. 배치 모드에서 이미 부팅된 충전기도 TriggerMessage를 통해 BootNotification을 발송하므로, 순차 실행 시 타임아웃 없이 정상 동작합니다. 프록시 모드에서는 10초간 자연 부팅을 먼저 기다리므로 실제 충전기의 Cold Boot도 정상 감지됩니다.
Batch Compatibility: Cold Boot scenarios (TC_B_02, B_03, B_11~B_13, E_19, E_20) use triggerMessage: "BootNotification". In batch mode, even already-booted chargers will send BootNotification via TriggerMessage, ensuring sequential execution without timeouts. In proxy mode, the 10-second delay allows natural boot detection from real chargers.
delay - Time Delay
{ "type": "delay", "duration": 2000 }
reusable_state - Expand Reusable State
{ "type": "reusable_state", "state": "BootedAndAvailable" }
13. Reusable States
test-scenarios/_reusable-states.json에 정의된 재사용 가능한 스텝 시퀀스:
Reusable step sequences defined in test-scenarios/_reusable-states.json:
| State | Mode | Description |
|---|---|---|
Booted | Proxy | BootNotification 대기Wait for BootNotification |
Available | Proxy | StatusNotification Available 대기Wait for StatusNotification Available |
BootedAndAvailable | Proxy | Boot + Available 대기Boot + Available wait |
EnergyTransferStarted | Proxy | 부팅 → RemoteStart → Transaction 전체 흐름Full boot → RemoteStart → Transaction flow |
Authorized | Proxy | Authorize 대기Wait for Authorize |
TransactionStarted | Proxy | TransactionEvent Started 대기Wait for TransactionEvent Started |
TransactionEnded | Proxy | TransactionEvent Ended 대기Wait for TransactionEvent Ended |
EVConnected | Proxy | StatusNotification Occupied 대기Wait for StatusNotification Occupied |
EVDisconnected | Proxy | StatusNotification Available 대기Wait for StatusNotification Available |
Reserved | Proxy | StatusNotification Reserved 대기Wait for StatusNotification Reserved |
Unavailable | Proxy | StatusNotification Unavailable 대기Wait for StatusNotification Unavailable |
14. Docker Build
# Build for Linux/AMD64 (AKS)
docker build --platform linux/amd64 \
-t csmsdevacr.azurecr.io/ocpp-simulator:latest .
# Login to ACR (if auth expired)
az acr login --name csmsdevacr
# Push image
docker push csmsdevacr.azurecr.io/ocpp-simulator:latest
COPY test-scenarios/ ./test-scenarios/가 포함되어 있어야 합니다. 누락 시 테스트 시나리오가 로드되지 않습니다.
Dockerfile Note: Must include COPY test-scenarios/ ./test-scenarios/. Missing this will prevent test scenarios from loading.
15. AKS Deployment
# Rolling restart
kubectl rollout restart deployment/ocpp-simulator -n ceer-ocpp
# Check status
kubectl rollout status deployment/ocpp-simulator -n ceer-ocpp
# View logs
kubectl logs deployment/ocpp-simulator -n ceer-ocpp --tail=50
# Verify scenarios loaded
kubectl logs deployment/ocpp-simulator -n ceer-ocpp | grep "Loaded"
# [TEST] Loaded 11 reusable states
# [TEST] Loaded 240 test scenarios (v2.0.1: 231, v1.6: 9)
K8s Environment (k8s-deploy.yaml)
env:
- name: UPSTREAM_CSMS_URL
value: "ws://cpos-websocket:8080"
- name: UPSTREAM_REDIS_URL
value: "rediss://:PASSWORD@redis-host:6380"
- name: CSMS_BACKEND_URL
value: "http://csms-backend.csms.svc.cluster.local:8000"
- name: BASE_PATH
value: "/simulator/"
Ingress Configuration
WebSocket 프록시를 위해 다음 Nginx Ingress 어노테이션이 필요합니다: The following Nginx Ingress annotations are required for WebSocket proxy:
annotations:
nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/websocket-services: ocpp-simulator
16. Scenario Compatibility
총 240개 시나리오 (OCPP 2.0.1: 231개 + OCPP 1.6: 9개)의 Smart Charger(로컬 CSMS 모드) 호환성 분류입니다. Total 240 scenarios (OCPP 2.0.1: 231, OCPP 1.6: 9). Smart Charger (Test용 CSMS API Server mode) compatibility breakdown.
물리적 한계 시나리오 (19개)Physical Limitation Scenarios (19)
CS 자율 Authorize 필요 (12개)CS-initiated Authorize Required (12)
RFID 카드 태그, PIN 입력, eMAID 등 사용자 물리 행위로 CS가 자발적으로 Authorize를 전송해야 합니다. OCPP 스펙에 TriggerMessage(Authorize)가 없어 CSMS에서 유도할 수 없습니다.
CS must autonomously send Authorize via physical user actions (RFID card tap, PIN input, eMAID). OCPP spec lacks TriggerMessage(Authorize), so CSMS cannot trigger it.
| ID | Name | LimitationLimitation |
|---|---|---|
TC_C_01 | EV Driver Auth RFID | 물리 RFID 카드 태그 필요Physical RFID card tap required |
TC_C_02 | Authorization - Invalid/Unknown | 물리 RFID 카드 태그 필요Physical RFID card tap required |
TC_C_03 | Authorization - Invalid Token | 물리 RFID 카드 태그 필요Physical RFID card tap required |
TC_C_04 | Authorization using PIN Code | PIN 코드 물리 입력 필요Physical PIN code input required |
TC_C_07 | Authorization using Contract Certificate | EV 차량 PLC 통신 (eMAID) 필요EV PLC communication (eMAID) required |
TC_C_08 | Authorization - Expired Token | 물리 카드 태그 필요Physical card tap required |
TC_C_09 | Authorization - No Credit | 물리 카드 태그 필요Physical card tap required |
TC_C_10 | Authorization - Not Allowed at Location | 물리 카드 태그 필요Physical card tap required |
TC_C_11 | Authorization with GroupIdToken | 물리 카드 태그 필요Physical card tap required |
TC_C_12 | Authorization Concurrent Transactions | 물리 카드 태그 필요Physical card tap required |
TC_C_13 | Authorization with Local List Fallback | 물리 카드 태그 필요Physical card tap required |
TC_C_14 | Authorization - Unknown Token | 물리 카드 태그 필요Physical card tap required |
기타 물리적 한계 (7개)Other Physical Limitations (7)
| ID | Name | LimitationLimitation |
|---|---|---|
TC_E_06 | Start Transaction - Id Not Accepted | CS 자율 Authorize 전송 필요 (물리 RFID 카드 태그)CS-initiated Authorize required (physical RFID card tap) |
TC_E_07 | Stop Transaction - Local | CS 자율 트랜잭션 로컬 정지 필요 (사용자 물리 행위)CS-initiated local transaction stop required (physical user action) |
TC_E_18 | Transaction - EVDisconnected Stop | EV 케이블 물리 분리 시뮬레이션 필요Physical EV cable disconnect simulation required |
TC_E_19 | Transaction PowerLoss | 전원 차단 후 트랜잭션 복구 (영속성)Transaction recovery after power loss (persistence) |
TC_E_21 | Remote Stop Transaction | CS 자율 트랜잭션 시작 필요CS-initiated transaction start required |
TC_F_04 | Remote Start Cable Timeout | 물리 케이블 미연결 시뮬레이션Physical cable not-connected simulation |
TC_G_12 | StatusNotification Faulted | 하드웨어 결함 자율 보고Hardware fault autonomous reporting |
Smart Charger 자동 동작Smart Charger Auto Behavior
Smart Charger(charger-client.js)는 CSMS 명령에 대해 자동으로 응답하고 후속 메시지를 전송합니다:
Smart Charger (charger-client.js) auto-responds to CSMS commands and sends follow-up messages:
| CSMS Command | Auto Response | Follow-up Messages |
|---|---|---|
| RequestStartTransaction | Accepted | Authorize → TransactionEvent(Started) → StatusNotification(Occupied) |
| RequestStopTransaction | Accepted | TransactionEvent(Ended) → StatusNotification(Available) |
| Reset | Accepted | [TransactionEvent(Ended)] → BootNotification → StatusNotification(Available) |
| TriggerMessage | Accepted / NotImplemented | 해당 메시지 전송 (Boot, Heartbeat, Status 등)Sends requested message (Boot, Heartbeat, Status, etc.) |
| ChangeAvailability | Accepted / Scheduled | StatusNotification(Available/Unavailable) |
| ReserveNow | Accepted | StatusNotification(Reserved) |
| UpdateFirmware | Accepted | FirmwareStatusNotification (Downloading → Installed) |
데모 시뮬레이션 Demo Simulation
구성 Architecture
각 충전기는 실제 OCPP 2.0.1 메시지를 전송합니다. CSMS WebSocket 서버를 거쳐 CSMS Backend에 트랜잭션, 미터값이 기록되므로 CSMS Frontend에서 세션 이력을 조회할 수 있습니다. Each charger sends real OCPP 2.0.1 messages. Transactions and meter values are recorded in CSMS Backend via CSMS WebSocket server, so session history is viewable in CSMS Frontend.
충전기 모델 분류 (20대 기준) Charger Model Distribution (20 units)
| 충전기Chargers | 모델Model | 전력Power | 타입Type |
|---|---|---|---|
| DEMO-001 ~ 008 | CEER-7kW-AC | 7 kW | AC Type2 |
| DEMO-009 ~ 015 | CEER-50kW-DC | 50 kW | DC CCS2 |
| DEMO-016 ~ 020 | CEER-150kW-DC | 150 kW | DC CCS2 |
9가지 충전 시나리오 9 Charging Scenarios
| 시나리오Scenario | 충전기Chargers | 대수Count | 설명Description |
|---|---|---|---|
| SC-01 RFID | DEMO-001~004 | 4 | RFID 카드 태그 인증 후 충전 시작/종료RFID card tap authentication, start/stop charging |
| SC-02 Plug & Charge | DEMO-005~007 | 3 | 케이블 연결 시 eMAID 자동 인증 (ISO 15118)Auto-auth via eMAID on cable plug (ISO 15118) |
| SC-03 VIN AutoCharge | DEMO-008~010 | 3 | 차량 VIN 기반 자동 인증 및 충전Vehicle VIN-based auto-authentication |
| SC-04 Remote Start/Stop | DEMO-011~013 | 3 | 모바일 앱에서 원격 충전 시작/종료Remote charge start/stop from mobile app |
| SC-05 User Stop | DEMO-014~015 | 2 | 충전 중 사용자가 직접 종료User manually stops charging mid-session |
| SC-06 Error | DEMO-016 | 1 | 충전 중 접지 오류(GroundFault) 감지 → 자동 복구GroundFault detected during charging → auto recovery |
| SC-07 Remote Reset | DEMO-017 | 1 | CSMS에서 충전기 원격 재부팅Remote reboot charger from CSMS |
| SC-08 Suspended EV | DEMO-018~019 | 2 | 차량 BMS가 충전 일시정지 → 자동 재개EV BMS pauses charging → auto resume |
| IDLE | DEMO-020 | 1 | 충전 요청 없이 대기 상태 유지Standby, no charging activity |
시나리오별 OCPP 메시지 흐름 OCPP Message Flow per Scenario
SC-01 RFID
SC-06 Error
SC-08 Suspended EV
데모 대시보드 사용법 Demo Dashboard Guide
시작하기Getting Started
사이드바 → Demo → Demo Dashboard에서 실행합니다. Navigate to Demo → Demo Dashboard in the sidebar.
| 설정Setting | 기본값Default | 설명Description |
|---|---|---|
| 충전기 수Charger Count | 20 | 시뮬레이션할 충전기 수 (최대 500)Number of chargers to simulate (max 500) |
| CSMS URL | wss://...alb.azure.com | 충전기가 접속할 CSMS 주소CSMS endpoint for charger connections |
| Rate Limit | 20 msg/s | 초당 최대 메시지 전송 수Max messages per second |
Start 버튼 클릭 → 충전기가 배치로 접속 → 시나리오 자동 실행 → Stop으로 중지. Click Start → chargers connect in batches → scenarios run automatically → Stop to halt.
대시보드 구성Dashboard Layout
| 영역Area | 내용Content |
|---|---|
| 상단 카운터Top Counters | 접속 / 충전중 / 대기 / 오류 / 미접속 / 시나리오 사이클 수Connected / Charging / Available / Faulted / Disconnected / Scenario cycles |
| 충전기 그리드Charger Grid | 타일 색상으로 상태 구분 (클릭 시 상세 정보)Color-coded tiles showing status (click for details) |
| 시나리오 분포Scenario Chart | SC-01~08별 충전기 비율 차트Distribution chart by scenario |
| 실시간 이벤트Event Feed | 충전 시작/종료, 오류 등 실시간 로그Real-time log of charge start/stop, errors |
| 충전기 상세Charger Detail | 선택한 충전기의 현재 상태, 에너지, SoCSelected charger's status, energy, SoC |
Demo API Reference Demo API Reference
POST /api/demo/start
데모 시뮬레이션 시작Start demo simulation
// Request body (all optional, defaults shown)
{
"count": 20,
"csmsUrl": "wss://your-csms-host/ocpp201",
"batchSize": 10,
"maxMsgPerSec": 20
}
POST /api/demo/stop
데모 중지 및 전체 충전기 접속 해제Stop demo and disconnect all chargers
GET /api/demo/status
현재 데모 상태 (running, 충전기 수, 시나리오 카운트 등)Current demo status (running, charger counts, scenario stats)
GET /api/demo/chargers
전체 충전기 상태 목록 (status, scenario, energy, power, SoC)All charger states (status, scenario, energy, power, SoC)
GET /api/demo/charger/{id}
개별 충전기 상세 상태Individual charger detail
POST /api/demo/remote-start
모바일 앱 Mock에서 원격 충전 시작Remote start from Mobile App Mock
{ "chargerId": "DEMO-011", "userId": "USER-001" }
POST /api/demo/remote-stop
원격 충전 종료Remote stop charging
{ "chargerId": "DEMO-011" }
GET /api/demo/users
생성된 데모 사용자 목록 (userId, name, rfidToken, emaId)Generated demo users list
GET /api/demo/nearby
위치 기반 주변 충전기 검색Location-based nearby charger search
// Query params
?lat=37.4979&lng=127.0276&radius=5
실기 충전기 접속 가이드 Real Charger Connection Guide
1. WebSocket 접속 정보 1. WebSocket Connection Details
| 항목Item | 값Value | 설명Description |
|---|---|---|
| Endpoint | wss://your-csms-host/ocpp/{stationId} |
{stationId}를 충전기 고유 ID로 교체Replace {stationId} with your charger's unique ID |
| Protocol | ocpp2.0.1 |
WebSocket Subprotocol 헤더에 설정Set in WebSocket Subprotocol header |
| TLS | WSS (TLS 1.2+) | 인증서 검증 필수Certificate validation required |
| 인증Auth | Basic Auth (선택optional) | 필요 시 사전 협의Coordinate in advance if needed |
| 대체 경로Alt Path | /ocpp201/{stationId} |
동일하게 동작Works identically |
2. 접속 예시 2. Connection Example
WebSocket 클라이언트 (Python)WebSocket Client (Python)
# pip install websockets
import asyncio, websockets, json
async def connect():
uri = "wss://your-csms-host/ocpp/MY_CHARGER_001"
async with websockets.connect(uri, subprotocols=["ocpp2.0.1"]) as ws:
# Send BootNotification
boot = [2, "msg001", "BootNotification", {
"chargingStation": {
"model": "ModelX",
"vendorName": "YourCompany"
},
"reason": "PowerUp"
}]
await ws.send(json.dumps(boot))
response = await ws.recv()
print("Boot response:", response)
# Send Heartbeat every 60s
while True:
hb = [2, "hb001", "Heartbeat", {}]
await ws.send(json.dumps(hb))
await asyncio.sleep(60)
asyncio.run(connect())
필수 메시지 시퀀스Required Message Sequence
3. 접속 확인 방법 3. Verifying Connection
충전기가 접속되면 시뮬레이터 웹 UI에서 확인할 수 있습니다. Once connected, you can verify via the simulator web UI.
| 방법Method | 경로Path | 설명Description |
|---|---|---|
| 웹 UIWeb UI | 사이드바 → Backend (실기) → 충전기 관리 → "자동 발견" 클릭Sidebar → Backend (실기) → 충전기 관리 → Click "자동 발견" | Redis에서 현재 접속 중인 충전기를 자동 검색하여 목록에 등록합니다Auto-discovers connected chargers from Redis and registers them |
| API | POST /api/backend/chargers/discover |
접속 중인 전체 충전기 목록 반환Returns list of all currently connected chargers |
| API | GET /api/backend/chargers/{id}/status |
개별 충전기 접속 상태 확인Check individual charger connection status |
자동 발견 API 응답 예시Auto-discovery API Response Example
// POST /api/backend/chargers/discover
{
"success": true,
"chargers": [
{
"chargerId": "TD_CHARGER_001",
"protocol_version": "2.0.1",
"connected_at": "2026-03-20T04:38:30.626Z",
"last_heartbeat": "2026-03-20T04:58:37.500Z",
"pod_name": "cpos-websocket-69896b7988-57v8b"
}
]
}
실기 충전기 역제어 (Remote Control) Real Charger Remote Control
접속이 확인된 충전기에 CSMS → 충전기 방향으로 OCPP 명령을 전송할 수 있습니다. You can send OCPP commands from CSMS to connected chargers.
웹 UI 사용법 Using Web UI
사이드바 → Backend (실기) → 역제어 페이지에서 직접 명령을 전송합니다. Navigate to Backend (실기) → 역제어 in the sidebar to send commands.
지원 명령 목록 Supported Commands
| Action | 용도Purpose | 주요 파라미터Key Parameters |
|---|---|---|
RequestStartTransaction |
원격 충전 시작Remote start charging | idToken, evseId |
RequestStopTransaction |
원격 충전 중지Remote stop charging | transactionId |
Reset |
충전기 재부팅Reboot charger | type: Immediate / OnIdle |
ChangeAvailability |
가용 상태 변경Change availability | operationalStatus: Operative / Inoperative |
TriggerMessage |
메시지 요청Request message | requestedMessage: StatusNotification, Heartbeat, etc. |
UnlockConnector |
커넥터 잠금 해제Unlock connector | evseId, connectorId |
GetVariables |
설정값 조회Read configuration | component, variable |
SetVariables |
설정값 변경Write configuration | component, variable, attributeValue |
GetBaseReport |
전체 설정 리포트Full config report | reportBase: ConfigurationInventory / FullInventory |
역제어 API 사용 예시 Remote Control API Examples
TriggerMessage (StatusNotification 요청)
# 충전기에 StatusNotification 전송 요청
curl -X POST http://20.2.210.133/api/backend/send/TD_CHARGER_001 \
-H "Content-Type: application/json" \
-d '{
"action": "TriggerMessage",
"params": { "requestedMessage": "StatusNotification" }
}'
# Response
{ "success": true, "data": "" }
RequestStartTransaction (원격 충전 시작Remote Start)
curl -X POST http://20.2.210.133/api/backend/send/TD_CHARGER_001 \
-H "Content-Type: application/json" \
-d '{
"action": "RequestStartTransaction",
"params": {
"idToken": { "idToken": "TESTCARD001", "type": "ISO14443" },
"remoteStartId": 12345,
"evseId": 1
}
}'
GetVariables (HeartbeatInterval 조회Read HeartbeatInterval)
curl -X POST http://20.2.210.133/api/backend/send/TD_CHARGER_001 \
-H "Content-Type: application/json" \
-d '{
"action": "GetVariables",
"params": {
"getVariableData": [{
"component": { "name": "OCPPCommCtrlr" },
"variable": { "name": "HeartbeatInterval" }
}]
}
}'
Reset (충전기 재부팅Reboot Charger)
curl -X POST http://20.2.210.133/api/backend/send/TD_CHARGER_001 \
-H "Content-Type: application/json" \
-d '{ "action": "Reset", "params": { "type": "Immediate" } }'
Backend API Reference Backend API Reference
실기 충전기 관리를 위한 REST API 목록입니다. REST API reference for real charger management.
충전기 관리Charger Management
GET /api/backend/config
Backend 설정 상태 조회 (CSMS WebSocket, Redis 연결 여부)Check backend configuration status (CSMS WebSocket, Redis connectivity)
POST /api/backend/chargers/discover
Redis에서 접속 중인 충전기 자동 발견 및 등록Auto-discover connected chargers from Redis and register them
// Response
{
"success": true,
"chargers": [
{ "chargerId": "TD_CHARGER_001", "connected_at": "...", "last_heartbeat": "..." }
]
}
GET /api/backend/chargers
등록된 충전기 목록 + 상태 조회List registered chargers with status
POST /api/backend/chargers
충전기 수동 등록Manually register chargers
// Request body
{ "chargerIds": ["CP001", "CP002"] }
GET /api/backend/chargers/{id}/status
개별 충전기 실시간 상태 조회 (CSMS WebSocket 서버 직접 확인)Check individual charger's real-time status via CSMS WebSocket server
DELETE /api/backend/chargers/{id}
충전기 등록 해제Unregister a charger
역제어 (명령 전송)Remote Control (Send Commands)
POST /api/backend/send/{chargerId}
CSMS WebSocket 서버를 통해 충전기에 OCPP 명령을 전송합니다.Send OCPP commands to charger via CSMS WebSocket server.
// Request body
{
"action": "TriggerMessage",
"params": { "requestedMessage": "StatusNotification" }
}
// Success response
{ "success": true, "data": { ... } }
// Error response
{ "success": false, "message": "error description" }
action 값은 OCPP 2.0.1 스펙의 정확한 Action 이름을 사용해야 합니다 (예: RequestStartTransaction, 대소문자 정확히).
Note: The action value must match the exact OCPP 2.0.1 Action name (e.g., RequestStartTransaction, case-sensitive).
트러블슈팅Troubleshooting
| 증상Symptom | 원인Cause | 해결Solution |
|---|---|---|
| 자동 발견에서 충전기가 안 보임Charger not found in auto-discovery | WebSocket 미접속 또는 접속 끊김WebSocket not connected or disconnected | 충전기 로그에서 WSS 접속 상태 확인. wss:// 프로토콜 및 ocpp2.0.1 subprotocol 확인Check WSS connection in charger logs. Verify wss:// protocol and ocpp2.0.1 subprotocol |
| 역제어 명령 실패 (Validation error)Remote control fails (Validation error) | OCPP 메시지 포맷 불일치OCPP message format mismatch | OCPP 2.0.1 스펙 기준으로 params 필드 확인. 에러 메시지의 required property 참고Verify params fields per OCPP 2.0.1 spec. Check required property in error |
| BootNotification 응답이 RejectedBootNotification response is Rejected | 충전기 ID 미등록 또는 인증 실패Charger ID not registered or auth failure | CSMS 관리자에게 충전기 ID 사전 등록 요청Request charger ID pre-registration from CSMS admin |
| Heartbeat 응답 없음 (타임아웃)No Heartbeat response (timeout) | 네트워크 불안정 또는 방화벽Unstable network or firewall | WSS 443 포트 아웃바운드 허용 확인. 재접속 로직 구현Verify WSS port 443 outbound allowed. Implement reconnection logic |
Autocrypt · AOS Simulator Documentation · Updated 2026-04-01