패킷 흐름

접속 → 설정 → 수집 시작 → 스트리밍 → 종료까지의 전형적 시나리오. 모든 명령 MSG는 ACK가 따라온다.

케이스 1. 정상 접속 및 수집 시작

SW Device │ TCP connect (:31024) ───────────────────────────▶ │ │ │ │ SCOPE_SET_PACKET ──────────────────────────────▶ │ (선택, 설정 동기화) │ ◀──── MSG(MSG_SCOPE_SET_ERROR, error=0) ACK │ │ │ │ PQN_SET_PACKET ──────────────────────────────▶ │ │ ◀──── MSG(MSG_PQN_SET_ERROR, error=0) ACK │ │ │ │ HW_SET_PACKET ──────────────────────────────▶ │ │ ◀──── MSG(MSG_HW_SET_ERROR, error=0) ACK │ │ │ │ MSG(MSG_SEND_DATA_START) ────────────────────────▶ │ │ ◀──── MSG(MSG_SEND_DATA_START) ACK │ │ │ │ ◀──────────────── SCOPE_DATA_PACKET (TRIG 즉시) │ │ ◀──────────────── PQN_DATA_PACKET (사이클당) │ │ ◀──────────────── ... 스트리밍 계속 ... │

실무상 SW는 접속 직후 SCOPE_SET → PQN_SET → HW_SET를 먼저 보내 장비 설정을 동기화한 뒤 START. PDF는 START 명령만 정의했지만 SET 패킷의 존재 자체가 이 시퀀스를 함의함.

케이스 2. Keep-alive

SW Device │ 3s tick │ │ MSG(MSG_ALIVE) ───────────────────▶ │ │ ◀──────── MSG(MSG_ALIVE) ACK │ │ ...반복... │

Rev 4 에 추가된 단순 살아있음 확인. 페이로드 없음, 같은 msg 코드로 응답.

케이스 3. 정상 종료

SW Device │ MSG(MSG_SEND_DATA_STOP) ───────────────────▶ │ │ ◀──── MSG(MSG_SEND_DATA_STOP) ACK │ │ (이후 SCOPE/PQN 스트림 중단) │ │ TCP close ──────────────────────────────▶ │

STOP 보낸 후 짧게 드레인 뒤 TCP close. ACK 받기 전 끊으면 장비 측에 이전 세션 잔여가 남을 수 있음(펌웨어 의존).

케이스 4. SET 명령 + 에러 응답

SET 패킷은 항상 대응 MSG로 ACK 됨. 에러 없으면 error=0, 있으면 error 필드에 코드 + 채널 오프셋.

SW Device │ SCOPE_SET_PACKET (3번 채널 ch_on=잘못된값) ────▶ │ │ ◀──── MSG(MSG_SCOPE_SET_ERROR, error=10023) │ │ │ │ │ └─ 디코드: base=10020 (CH_ON_INVALID) │ │ ch_offset=3 (3번 채널) │

케이스 5. NET_CFG 조회 / 설정

SW Device │ MSG(MSG_NET_CFG_INFO) ────────────────────────────▶ │ │ ◀──── MSG(MSG_NET_CFG_INFO, error=0) │ │ padding[0..5]=MAC, padding[6..9]=IP │ │ │ │ MSG(MSG_NET_CFG_SET) padding[0..9]=새 MAC+IP ──────▶ │ │ ◀──── MSG(MSG_NET_CFG_SET, error=0) 정상 │ │ 또는 │ │ ◀──── MSG(_, error=90011) b 옥텟 잘못 │ │ ◀──── MSG(_, error=90020) HW 변경실패 │

케이스 6. SELF_SYNC_ENABLE

SW Device │ MSG(MSG_SELF_SYNC_ENABLE) ─────────────────────────────▶ │ │ padding[0..3] = 'T','-','9','0' (84,45,57,48) │ │ padding[4] = 1 (ON) 또는 0 (OFF) │ │ │ │ ◀──── MSG(_, error=0) 정상 ON/OFF │ │ ◀──── MSG(_, error=100100) magic 불일치 (DENIED) │ ◀──── MSG(_, error=100110) padding[4] 0/1 아님 │ ◀──── MSG(_, error=100120) sync_freq 불일치 (제조사 문의)

케이스 7. REBOOT

SW Device │ MSG(MSG_REBOOT) ───────────────────────▶ │ │ ◀──── MSG(MSG_REBOOT) ACK │ │ │ │ ◀──── (TCP close, 펌웨어 재시작) │ │ 잠시 후 SW가 재접속 시도 │

케이스 8. 비정상 단절

SW Device │ ◀────×──── (network drop / power off / 펌웨어 hang) │ (read EOF) │ │ → "disconnect" 이벤트 emit │ │ → 재접속 정책에 따라 dial 재시도 │

장비가 STOP 받기 전에 끊긴 경우, 재접속 시점에 이전 세션 streaming 잔여가 흘러나올 수 있음 (펌웨어 의존).

SCOPE vs PQN 도착 타이밍

두 스트림은 같은 시각의 사이클이라도 도착 시각이 다르다.

그래서 cycle_index 가 SCOPE=80 일 때 PQN=75 같은 차이가 정상. SW 에서 두 스트림 매칭은 cycle_index 키로 정렬해서.

phase wrap-around

SCOPE_DATA_PACKET.phase 는 sync 주파수에 따라 다음 최대값 도달 후 다음 사이클 진입하면서 wrap.

sync_freqphase 최대값wrap 예시 (PDF)
60 Hz1,666,6661,656,738 → 4,979
120 Hz833,333831,189 → 902

일반식: phase_max ≈ 1e8 / sync_freq (10ns 단위로 한 주기).

구조체 정의는 → T90 프로토콜, 각 데이터의 의미는 → 5종 데이터 한눈에.