시뮬레이터 자동화와 오류 재현
- 시뮬레이터를 상대 장비 또는 상대 호스트로 써서 자신의 프로그램을 시험합니다.
- headless 시나리오로 시험을 자동화하고 종료 코드로 결과를 판정합니다.
- 연결 거부, 세션 ID 불일치, T3 타임아웃, 처리하지 않는 요청, 쓰기 배압을 일부러 만들고 각각 어떻게 보이는지 확인합니다.
- 재현 결과를 추적 파일과 로그로 남깁니다.
준비물
섹션 제목: “준비물”- 첫 통신을 마친 환경. 튜토리얼 C++ 예제
build/pdcomm-tutorial을 씁니다. - 환경 변수
PDCOMM_ROOT,PDCOMM_SIMULATOR
명령은 Linux와 macOS 셸 기준입니다. Windows에서는 "$PDCOMM_SIMULATOR/pdcomm-simulator-headless"를 & "$Simulator\pdcomm-simulator-headless.exe"로 바꿉니다.
1. 내 호스트를 시뮬레이터 장비로 시험합니다
섹션 제목: “1. 내 호스트를 시뮬레이터 장비로 시험합니다”external-peer 시나리오는 장비를 띄우고, 외부 호스트가 S1F13과 S1F1을 보낸 뒤 끊기를 기다립니다.
"$PDCOMM_SIMULATOR/pdcomm-simulator-headless" --scenario external-peer --session-id 7 --timeout-ms 20000두 번째 줄의 local_address(예: 127.0.0.1:50092)로 호스트를 연결하고 establish, identity, quit을 입력합니다.
"$PDCOMM_ROOT/build/pdcomm-tutorial" host active 127.0.0.1:50092시뮬레이터가 s1f13, s1f1, disconnect를 관찰하고 "outcome":"passed", 종료 코드 0으로 끝납니다. 자신의 호스트 프로그램을 자동 시험에 넣을 때는 이 출력의 두 번째 줄에서 주소를 읽어 호스트에 넘기고, 시뮬레이터의 종료 코드로 판정합니다.
2. 내 장비를 시뮬레이터 호스트로 시험합니다
섹션 제목: “2. 내 장비를 시뮬레이터 호스트로 시험합니다”먼저 튜토리얼 장비를 시작합니다.
"$PDCOMM_ROOT/build/pdcomm-tutorial" equipment passive 127.0.0.1:5006다른 터미널에서 시뮬레이터를 호스트 역할로 실행합니다.
"$PDCOMM_SIMULATOR/pdcomm-simulator-headless" --role host --address 127.0.0.1:5006 --session-id 7시뮬레이터가 연결하고 통신을 수립한 뒤 "outcome":"passed"로 끝납니다. 장비 터미널에는 받은 S1F13의 결과 RESULT kind=1 request=0 outcome=2가 나옵니다.
3. 시나리오로 기능을 한 번에 확인합니다
섹션 제목: “3. 시나리오로 기능을 한 번에 확인합니다”headless 시뮬레이터에는 기능별 왕복 시나리오가 들어 있습니다. 튜토리얼의 각 장에 대응하는 시나리오를 실행해 SDK와 시뮬레이터가 그 기능을 지원하는지 먼저 확인합니다.
mkdir -p resultsfor scenario in status-round-trip data-report-round-trip directory-round-trip remote-report-config-round-trip typed-command-round-trip; do "$PDCOMM_SIMULATOR/pdcomm-simulator-headless" --scenario "$scenario" > "results/$scenario.jsonl" echo "$scenario exit=$?"donestatus-round-trip exit=0data-report-round-trip exit=0directory-round-trip exit=0remote-report-config-round-trip exit=0typed-command-round-trip exit=0시나리오 목록과 출력 형식은 headless 시뮬레이터에 있습니다. GUI에서 만든 프로필과 시나리오도 프로젝트 파일로 저장해 같은 방식으로 실행할 수 있습니다.
4. 스크립트나 AI 도구로 시뮬레이터를 조작합니다
섹션 제목: “4. 스크립트나 AI 도구로 시뮬레이터를 조작합니다”GUI를 --mcp-stdio로 실행하면 MCP 클라이언트가 GUI의 세션을 만들고 시작할 수 있습니다. GUI가 스스로 입출력을 진행하므로 외부 프로그램을 그 세션에 바로 연결할 수 있습니다.
다음 순서로 시뮬레이터 장비를 만들고 튜토리얼 호스트를 연결해 값을 바꾸는 시험을 자동화할 수 있습니다.
simulator.session.create:roleequipment,modepassive,address127.0.0.1:5000,protocol_session_id7simulator.lifecycle.start: 응답의generation과revision을 다음 호출에 씁니다.- 튜토리얼 호스트에서
establish,values 1001 1002→SECS-II 01 02 41 04 49 44 4c 45 b1 04 00 00 00 00 simulator.status_data.update:kindstatus,id1002,value"5"- 튜토리얼 호스트에서
values 1001 1002→ 마지막 값이b1 04 00 00 00 05로 바뀝니다.
MCP 서버 설정과 도구 목록은 시뮬레이터 MCP 서버에서 설명합니다.
5. 오류를 일부러 재현합니다
섹션 제목: “5. 오류를 일부러 재현합니다”실패 상황을 미리 만들어 보면 실제 장비에서 같은 증상을 만났을 때 원인을 빨리 찾을 수 있습니다. 각 실험이 끝나면 프로그램을 모두 종료하고 다음 실험을 시작합니다.
상대가 없을 때: 연결 거부
섹션 제목: “상대가 없을 때: 연결 거부”장비 없이 호스트만 실행합니다.
"$PDCOMM_ROOT/build/pdcomm-tutorial" host active 127.0.0.1:5010몇 초 뒤 state를 입력하면 STATE tcp=5 gem=0이 나옵니다. 5는 RetryWait입니다. 호스트는 연결이 거부될 때마다 T5(튜토리얼은 1초)만큼 기다렸다가 다시 연결합니다. quit으로 끝냅니다.
포트를 이미 쓰고 있을 때
섹션 제목: “포트를 이미 쓰고 있을 때”같은 주소로 장비 두 개를 시작합니다. 두 번째 장비는 바로 PDComm native operation failed를 출력하고 종료 코드 1로 끝납니다. C# 예제에서는 상태 이름 IoError가 함께 나옵니다.


세션 ID가 다를 때
섹션 제목: “세션 ID가 다를 때”시뮬레이터 GUI를 Equipment, Passive - listen, 127.0.0.1:5000으로 시작하되 Session ID는 기본값 0으로 둡니다. 튜토리얼 호스트(세션 ID 7)로 연결해 establish를 입력합니다. 연결과 Select는 성공하지만(STATE tcp=4) 5초(T3) 뒤에 RESULT kind=3 request=1 outcome=0이 나옵니다. 세션 ID가 맞지 않는 데이터 메시지는 상대가 처리하지 않기 때문입니다.
상대가 응답하지 않을 때: T3 타임아웃
섹션 제목: “상대가 응답하지 않을 때: T3 타임아웃”장비와 호스트를 연결하고 establish까지 실행합니다. 세 번째 터미널에서 장비 프로세스를 일시 정지합니다.
kill -STOP "$(pgrep -f 'pdcomm-tutorial equipment passive 127.0.0.1:5000')"호스트에서 values 1 2를 입력하면 5초 뒤 RESULT kind=3 request=3 outcome=0이 나옵니다. 장비를 다시 실행합니다.
kill -CONT "$(pgrep -f 'pdcomm-tutorial equipment passive 127.0.0.1:5000')"장비는 밀린 S1F3에 뒤늦게 응답합니다. 호스트는 이미 끝난 트랜잭션의 응답이므로 받지 않고, 연결은 Selected로 유지됩니다. 다음 values 1 2는 정상으로 끝납니다. 이 과정을 로그로 확인하는 방법은 실패 진단과 문의에서 다룹니다.
처리하지 않는 요청
섹션 제목: “처리하지 않는 요청”C# 호스트로 튜토리얼 장비에 alarms를 보냅니다. 장비는 알람 카탈로그가 없으므로 요청을 처리하지 않고 ABORT S5F0 for S5F5로 트랜잭션을 중단합니다. 호스트는 T3를 기다리지 않고 바로 RESULT kind=3 request=13을 받습니다. 자세한 설명은 첫 통신의 7단계에 있습니다.
쓰기 배압
섹션 제목: “쓰기 배압”"$PDCOMM_SIMULATOR/pdcomm-simulator-headless" --scenario transport-backpressure-recovery --transport-fault-profile write_backpressure출력의 second-send-limit-exceeded에서 송신이 한도 초과로 거부되고, transport-fault-released 뒤 retry-send-accepted에서 같은 요청이 다시 받아들여집니다. GUI에서는 세션을 시작하기 전에 Overview의 Transport fault를 Write backpressure로 정하고, 통신이 수립된 뒤 Message Trace & Diagnostics의 Transport fault profile에서 Arm과 Release를 누릅니다.
6. 재현 결과를 남깁니다
섹션 제목: “6. 재현 결과를 남깁니다”- GUI: Message Trace & Diagnostics에서 Export trace를 누르거나 File > **Export Trace…**로 JSON 파일을 저장합니다. 메시지 본문은 들어 있지 않습니다.
- headless 프로젝트 모드:
--trace-output <파일>로 추적을 저장합니다. - SDK 프로그램:
PDCOMM_LOG환경 변수로 JSON Lines 진단 로그를 남깁니다.


실행 중인 튜토리얼 예제는 quit으로, GUI는 Stop 후 창을 닫아 끝냅니다. 일시 정지한 프로세스가 남아 있으면 kill -CONT로 다시 실행한 뒤 종료합니다. results 폴더는 필요 없으면 지웁니다.
다음 단계
섹션 제목: “다음 단계”- 실패 진단과 문의에서 로그로 원인을 찾습니다.
- 연결과 타임아웃 문제에서 증상별 해결 방법을 찾습니다.