JSON 명령 레퍼런스
PDComm Modbus의 모든 조작은 JSON 명령입니다. SDK에서는 pdcomm_modbus_call이나 래퍼의 call/Call에, 헤드리스에서는 표준 입력 한 줄에, MCP에서는 modbus_<action> 도구의 인수로 넘깁니다. C, C++, .NET 함수 자체의 설명은 API 레퍼런스에 있습니다.
응답 형식
섹션 제목: “응답 형식”| 결과 | 응답 |
|---|---|
| 성공 | {"ok":true,"result":<결과>} |
| 서비스 오류 | {"ok":false,"error":"<메시지>"}. C ABI는 PDCOMM_MODBUS_SERVICE_ERROR와 함께 돌려줍니다. 라이선스 오류에는 code가 더 있습니다. |
action이 없으면Action is required, 모르는 이름이면Unknown service action입니다.- 객체의 필드 순서는 의미가 없습니다. 응답은 이름순으로 나옵니다.
- 오류 메시지 목록은 서비스 오류에 있습니다.
PDU 표기
섹션 제목: “PDU 표기”request, execute의 pdu와 fault의 bytes는 두 형식을 받습니다.
- 16진수 문자열:
"0300000001". 바이트 사이 공백은 무시합니다("03 00 00 00 01"). 글자 수가 홀수면Invalid hex length, 16진수가 아닌 글자는Invalid hex입니다. - 바이트 배열:
[3,0,0,0,1]. 0~255 밖의 값은Expected a byte array or hex string입니다.
응답의 response는 항상 10진수 바이트 배열이고, 응답이 없으면 null입니다.
capabilities
섹션 제목: “capabilities”빌드 기능을 돌려줍니다. 인수는 없습니다.
| 결과 필드 | 뜻 |
|---|---|
protocol |
항상 "modbus" |
tcp, rtu, ascii, security |
빌드에 포함된 전송과 보안 |
functions, diagnostics |
지원 기능 코드와 진단 하위 기능 목록 |
mei13 |
"opaque_extension". MEI 13은 내용을 해석하지 않습니다. |
canopen |
항상 false |
project_version |
지원 프로젝트 버전(1) |
diagnostic_logging, logging_schema_version |
진단 로그 지원과 로그 형식 버전 |
state
섹션 제목: “state”{"config":{...},"connected":<bool>,"listen_only":<bool>,"delimiter":<ASCII 종료 문자>,"trace_count":<기록 수>}를 돌려줍니다. TCP 클라이언트가 시간 초과나 상대 종료로 연결을 닫았으면 connected는 false입니다.
configure
섹션 제목: “configure”연결을 끊은 상태에서 구성 전체를 바꾸고 state와 같은 결과를 돌려줍니다. 서버의 진단 상태(카운터, 청취 전용)도 새로 시작합니다. 연결 중이면 Disconnect before changing configuration입니다.
{"action":"configure","config":{"transport":"tcp","role":"client","address":"127.0.0.1:1502","port":"","unit":1,"baud":19200,"parity":"even","stop_bits":1,"timeout_ms":1000}}| 필드 | 필수 | 값 | 설명 |
|---|---|---|---|
transport |
예 | tcp, rtu, ascii |
|
role |
예 | client, server, gateway |
gateway는 rtu나 ascii와 함께 씁니다. |
address |
예 | IP:포트 |
TCP 주소. 직렬 구성에서도 형식상 필요합니다. 호스트 이름은 받지 않습니다. |
port |
예 | 문자열 | 직렬 장치. TCP에서는 "" |
unit |
예 | 1~247 | |
baud |
예 | 1 이상 | TCP에서도 값이 필요합니다. |
parity |
예 | even, odd, none |
|
stop_bits |
예 | 1, 2 | none 패리티는 2 |
timeout_ms |
예 | 1~60000 | |
ascii_timeout_ms |
아니요 | 1~60000, 기본 1000 | |
turnaround_ms |
아니요 | 0~60000, 기본 100 | |
routes |
아니요 | {"TCP 유닛":직렬 주소} |
게이트웨이 경로. 키 1 |
security |
아니요 | 객체 또는 null |
Modbus/TCP Security. 아래 표 |
security 객체의 필드는 다음과 같습니다. TCP 구성에서만 씁니다.
| 필드 | 필수 | 설명 |
|---|---|---|
chain, private_key, trust |
예 | PEM 파일 경로. chain은 루트 CA로 끝나야 합니다. |
mode |
아니요 | encrypted(기본) 또는 authentication_only |
hostname |
아니요 | 클라이언트가 서버 인증서에서 확인할 이름이나 IP. 기본 localhost |
roles |
아니요 | 서버: {"역할":[기능 코드,...]} |
null_role |
아니요 | 서버: 역할 없는 클라이언트에게 허용할 기능 코드. 기본 [] |
crls |
아니요 | CRL 파일 경로 목록 |
require_revocation |
아니요 | true이면 CRL로 폐기 여부를 반드시 확인합니다. crls가 필요합니다. |
모르는 필드가 있으면 unknown field ..., 필수 필드가 없으면 missing field ...로 실패합니다.
connect, disconnect
섹션 제목: “connect, disconnect”connect는 소켓, 리스너, 직렬 포트를 열고 state를 돌려줍니다. 포트 0으로 연 서버는 config.address에 실제 주소가 들어 있습니다. 이미 연결 중이면 Endpoint is already connected입니다. SDK 라이브러리는 connect할 때 라이선스를 확인하고, 없으면 code가 license_required인 오류를 돌려줍니다(서비스 오류). disconnect는 {"connected":false}를 돌려줍니다. 연결하지 않은 상태에서도 성공합니다.
poll
섹션 제목: “poll”서버나 게이트웨이가 대기 중인 요청을 한 번 처리하고 {"handled":N}을 돌려줍니다. SDK로 서버를 만든 애플리케이션은 작업 스레드에서 이 명령을 반복합니다. GUI, 헤드리스, MCP는 스스로 반복합니다.
request
섹션 제목: “request”| 인수 | 설명 |
|---|---|
pdu |
요청 PDU |
unit |
선택. 0~255. 없으면 구성의 unit |
결과는 {"response":[...]|null,"status":"success"|"exception"|"no_response","source":"wire"}입니다. 연결된 클라이언트에서만 씁니다. 아니면 Connect a client before sending a request입니다. 직렬 클라이언트의 브로드캐스트(unit 0)는 쓰기만 보낼 수 있고 결과는 no_response입니다.
execute
섹션 제목: “execute”request와 인수가 같고, 엔드포인트 자신의 데이터 모델에서 실행합니다. source는 local입니다. 직렬 구성에서는 다른 유닛 주소의 요청에 no_response로 답하고, 유닛 0의 쓰기는 브로드캐스트로 처리합니다.
data_get
섹션 제목: “data_get”데이터 모델 전체를 돌려줍니다. 형식은 model_set과 같습니다.
data_set
섹션 제목: “data_set”| 인수 | 설명 |
|---|---|
table |
coils, discrete_inputs, holding_registers, input_registers |
address |
시작 주소 |
values |
값 배열. 비트 테이블은 0 또는 1 |
결과는 {"written":N}입니다. 입력 테이블도 바꿀 수 있습니다. 모델 범위 밖이면 Address outside configured table, 값이 틀리면 Invalid data values, 테이블 이름이 틀리면 Unknown data table입니다.
model_set
섹션 제목: “model_set”모델 전체를 검사한 뒤 한 번에 바꾸고 {"updated":true}를 돌려줍니다. 실패하면 기존 모델을 그대로 둡니다.
| 필드 | 형식 | 규칙 |
|---|---|---|
coils, discrete_inputs, holding_registers, input_registers |
{"start":N,"values":[...]} |
시작 주소와 개수가 16비트 주소 범위 안이어야 합니다(Invalid table range). 비트 테이블은 0 또는 1 |
files |
{"파일 번호":[워드,...]} |
파일 번호 1 이상, 레코드 10000개까지 |
fifos |
{"FIFO 포인터 주소":[값,...]} |
값 31개까지 |
objects |
{"객체 ID":[바이트,...]} |
0, 1, 2 필수, 7~127 예약, 객체당 244바이트까지 |
server_id |
[바이트,...] |
2~251바이트. FC 17의 응답 내용 |
exception_status |
0~255 | FC 07의 응답 |
individual_access |
true/false |
MEI 14 개별 객체 읽기 허용 |
diagnostics, diagnostics_set
섹션 제목: “diagnostics, diagnostics_set”diagnostics는 {"register":N,"listen_only":<bool>,"delimiter":N,"event_log":[...],"counters":{...}}를 돌려줍니다. counters에는 bus_messages, communication_errors, exceptions, server_messages, no_responses, naks, busy, overruns, events가 있습니다.
diagnostics_set은 시험용으로 진단 레지스터(register, 0~65535)와 바쁨 상태(busy)를 정합니다. busy가 true이면 FC 11과 12의 상태 워드가 FFFF가 됩니다. configure는 이 값들을 처음 상태로 돌립니다.
trace, trace_clear
섹션 제목: “trace, trace_clear”trace는 {"entries":[...]}로 최근 1000개 기록을 돌려줍니다. 항목은 두 종류입니다.
| 종류 | 필드 |
|---|---|
| 요청 기록 | sequence, source(local, wire), unit, request, response, status. 실패한 request의 status에는 오류 메시지(예: Timeout)가 들어갑니다. |
| 직렬 원시 바이트 | sequence, source(wire), direction(tx, rx, rx_discarded), transport, bytes, timestamp_us, timestamp_scope(host_io_batch), truncated |
rx_discarded는 요청 전에 남아 있었거나 다른 주소에서 온 바이트를 버린 기록입니다. trace_clear는 {"cleared":true}를 돌려줍니다.
project_export, project_import
섹션 제목: “project_export, project_import”project_export는 {"kind":"pdcomm.modbus.project","version":1,"config":{...},"model":{...}}를 돌려줍니다. project_import는 project 인수로 그 객체를 받아 {"loaded":true}를 돌려줍니다. 연결을 끊은 상태에서만 불러옵니다. 규칙은 헤드리스와 시나리오에 있습니다.
fault
섹션 제목: “fault”| 인수 | 설명 |
|---|---|
bytes |
해석할 원시 바이트(4096바이트까지) |
transport |
선택. tcp, rtu, ascii. 없으면 구성의 전송 |
gap_us |
선택. RTU·ASCII 디코더에 넣는 바이트 사이 가상 간격. 기본 100 |
결과는 {"source":"synthetic","frames":[...],"errors":[...]}입니다. 입출력은 하지 않습니다. RTU 디코더는 구성의 baud로 t1.5, t3.5를 계산합니다.
serial_ports
섹션 제목: “serial_ports”{"ports":["/dev/cu.usbserial-...",...]}를 돌려줍니다.
logging_configure, logging_status, logging_flush
섹션 제목: “logging_configure, logging_status, logging_flush”진단 로그를 제어합니다. logging_configure의 config는 enabled, level, file, max_bytes, files, forensics를 받고 로그 상태를 돌려줍니다. logging_flush는 {"flushed":true}입니다. 자세한 내용은 실패 진단과 문의에 있습니다.
license_install, license_status, host_id
섹션 제목: “license_install, license_status, host_id”SDK 라이브러리 전용입니다. 헤드리스와 MCP 시뮬레이터에는 없습니다. 라이선스는 엔드포인트가 아니라 라이브러리 전체에 적용되므로 아무 엔드포인트에서나 보냅니다.
| 명령 | 입력 | 결과 |
|---|---|---|
license_install |
text: 라이선스 텍스트. 빈 문자열이면 설치한 텍스트를 지웁니다. |
{"installed":N}. N은 서명이 맞는 블록 수입니다. 그런 블록이 없으면 code가 license_invalid인 오류이고 이전 텍스트는 그대로입니다. |
license_status |
없음 | 라이선스 상태 객체(build_date, host_id, sources, licenses, modules 등) |
host_id |
없음 | {"host_id":"PDH1-XXXX-XXXX-XXXX-XXXX"}. 읽지 못하면 code가 host_id_unavailable인 오류입니다. |
자세한 내용은 라이선스 설치와 확인에 있습니다.
shutdown
섹션 제목: “shutdown”헤드리스 시뮬레이터 전용입니다. 응답 없이 프로그램을 끝냅니다. SDK와 MCP에는 없습니다.