# NILM MQTT 3P3W·3P4W 통신 규격서 분석 및 전체 시스템 적용 계획 `Docs/NILM_MQTT_3P3W_3P4W_통신규격서.pdf` 규격서를 정밀 분석하여, 현재 Delphi 13 VCL 기반 AgentNILM MQTT Client 프로그램에 전반적으로 적용하기 위한 종합 구현 계획을 수립하였습니다. --- ## 1. 통신 규격서 핵심 내용 분석 요약 ```mermaid flowchart TD subgraph MQTT_Broker["MQTT Broker (QST/SUNGJOO/NEWPRIME/...)"] T1["/{GWID}/{NDID} (측정값 - 비Retain)"] T2["/{GWID}/{NDID}/status (노드 상태 - Retain)"] T3["/{GWID}/{NDID}/event (이상 이벤트 - 비Retain)"] T4["/{GWID}/gateway (게이트웨이 상태/LWT - Retain)"] end subgraph Parser["MQTT 수신 및 토픽 분기 라우터"] R1[측정 데이터 파서] R2[노드 통신상태 파서] R3[이벤트 알람 파서] R4[게이트웨이 상태 파서] end subgraph Core["핵심 비즈니스 로직"] W1{"wire 확인 (3P3W vs 3P4W)"} OP[가동/미가동 상태 판정] AGG[공장 전체 Total 전력 집계] end subgraph Output["출력 및 저장 계층"] DB[(PostgreSQL DB)] UI[실시간 모니터링 UI / 차트] OPC[OPC Automation Server] end T1 --> R1 --> W1 --> OP --> DB & UI & OPC W1 --> AGG --> UI & DB T2 --> R2 --> UI & DB T3 --> R3 --> UI & DB T4 --> R4 --> UI ``` ### 주요 규격 요약 1. **MQTT 토픽 구조**: `QST/SUNGJOO/NEWPRIME/{GWID}/{NDID}` - `/{NDID}`: Edge Meter 실시간 측정값 (비Retain) - `/{NDID}/status`: Edge Meter 통신 상태/손실률 (Retain) - `/{NDID}/event`: Edge Meter 비주기 이벤트/알람 (비Retain) - `/gateway`: LoRa Gateway 자체 상태 및 LWT (Retain) 2. **측정 데이터(Payload) JSON 구조**: - `gw`, `dev`, `seq`, `COMM`, `rssi`, `wire` ("3P3W" | "3P4W"), `freq`, `wh` - `ch`: 3채널 배열 (`v`, `i`, `p`, `q`, `s`, `pf`) - **3P3W (3상 3선식, 2전력계법)**: `ch[0]`(A-B 선간전압, A선 전류), `ch[1]`(null/미사용), `ch[2]`(C-B 선간전압, C선 전류). 전체 유효전력 = $P_A + P_C$. - **3P4W (3상 4선식, 상별 전력)**: `ch[0]`(A상), `ch[1]`(B상), `ch[2]`(C상). 전체 유효전력 = $P_A + P_B + P_C$. - `total`: 전체 전력값 객체 (`p`, `q`, `s`, `pf`) - 3P3W/3P4W 모두 설비 표시 및 공장 집계에는 `total` 객체값 사용. 3. **공장 전체 집계 원칙**: - 결선 방식 혼재 시 각 장치의 `ch` 값을 합산하지 않고 `total.p`, `total.q`를 기준으로 집계 ($P_{factory} = \sum P_{device,total}$). --- ## 2. User Review Required (사용자 검토 및 결정 필요 사항) > [!IMPORTANT] > **검토 1. DB 테이블 스키마 변경 및 신규 필드 수용** > - 기존 `nilm_data` 및 `nilm_history` 테이블에 `wire` (결선방식), `rssi` (LoRa신호세기), `wh` (누적전력량), `total_p`, `total_q`, `total_s`, `total_pf` 컬럼을 추가할 예정입니다. > - 기존 센서 컬럼(`vrms_a`, `irms_a`, `active_power_a` 등)은 `ch[0]`, `ch[1]`, `ch[2]`의 `v`, `i`, `p`, `q`, `s`, `pf` 값과 1:1 매핑되어 완벽히 호환됩니다. > - 3P3W 장비의 경우 `b`상(L2) 필드는 `NULL` 또는 `0`으로 안전하게 저장됩니다. > [!IMPORTANT] > **검토 2. 게이트웨이 및 노드 상태 화면 표시 방식** > - 신규 규격의 `/{GWID}/gateway` 및 `/{GWID}/{NDID}/status` 메시지를 수신하여 메인 화면 상단 또는 상태 탭에 게이트웨이 연결 상태(온라인 노드수, LoRa 주기) 및 장비별 통신 손실률(`loss_rate`, `polls`, `responses`)을 표시하도록 지원할 계획입니다. > [!TIP] > **검토 3. OPC 태그 자동 매핑 규칙** > - `ch[0]~ch[2]`의 전압/전류/전력과 함께 `total.p`, `total.pf`, `wh`, `rssi`, `wire` 등도 OPC 태그(`SYSTEM.{DeviceID}/total_p`, `SYSTEM.{DeviceID}/wh` 등)로 쓸 수 있도록 확장합니다. --- ## 3. 전체 시스템 적용 세부 계획 ### Phase 1: 데이터 타입 및 상수 정의 (`uNILMTypes.pas`) * **결선 상수 확정**: `PHASE_3P3W = '3P3W'`, `PHASE_3P4W = '3P4W'`, `PHASE_SINGLE = 'SINGLE'` * **신규 데이터 구조체 정의**: - `TNILMChannelData`: `v, i, p, q, s, pf` (Double, Nullable/Valid 플래그) - `TNILMTotalData`: `p, q, s, pf` (Double) - `TNILMMeasurementPayload`: `gw, dev, seq, COMM, rssi, wire, freq, wh, ch[0..2], total` - `TNILMNodeStatusPayload`: `gw, dev, online, last_seen_age_s, loss_rate, polls, responses` - `TNILMGatewayPayload`: `gw, online, nodes_total, nodes_online, cycle_ms, uptime_s` - `TNILMEventPayload`: `gw, dev, age_ms, code, name, seq, value` * **센서 템플릿 개선 (`TNILMSensorTemplate`)**: - 3P3W: A선(R-S 선간전압 380V), B선(미사용), C선(T-S/C-B 선간전압 380V), Total - 3P4W: A상(R-N 220V), B상(S-N 220V), C상(T-N 220V), Total ### Phase 2: DB 스키마 및 매니저 개선 (`uNILMManager.pas`) * **DDL 업데이트 (`EnsureTables`)**: - `nilm_data` 및 `nilm_history`: `wire`, `rssi`, `wh`, `total_p`, `total_q`, `total_s`, `total_pf` 컬럼 추가 (자동 마이그레이션 `ADD COLUMN IF NOT EXISTS`). - `nilm_gateway_status` 테이블 신설: 게이트웨이별 최신 상태 및 가동 시간 기록. * **측정 데이터 저장 로직 (`SaveNILMData`)**: - 신규 `TNILMMeasurementPayload` 구조에 맞추어 `ch[0..2]` 및 `total`, `wh`, `rssi` 값을 UPSERT. - 3P3W 결선 시 B상(L2) 데이터는 안전하게 Null 처리. * **노드 상태 & 게이트웨이 상태 & 이벤트 저장 메서드 추가**: - `SaveNodeStatus(const AStatus: TNILMNodeStatusPayload)` - `SaveGatewayStatus(const AGateway: TNILMGatewayPayload)` - `SaveNILMEvent(const AEvent: TNILMEventPayload)` * **전력량 및 공장 전체 집계 로직 (`CalculateEnergyConsumption`, `GetFactoryTotalPower`)**: - 각 장비의 `total.p`를 합산하여 공장 전체 실시간 전력($P_{factory}$) 계산. - 누적 전력량(`wh`) 필드를 활용한 당일/기간별 전력 사용량 산출. ### Phase 3: MQTT 토픽 라우팅 및 파싱 (`uMain.pas`) * **MQTT 구독(Subscribe) 규칙 최적화**: - 장비별 토픽 개별 구독 또는 와일드카드 구독(`QST/SUNGJOO/NEWPRIME/#` 또는 `.../+/+`) 지원. * **토픽 분기 라우터 (`OnMQTTMessage`)**: - 토픽의 마지막 세그먼트 분석: - `/gateway` $\rightarrow$ 게이트웨이 상태 파싱 (`ProcessGatewayPayload`) - `/{NDID}/status` $\rightarrow$ 노드 통신 상태 파싱 (`ProcessNodeStatusPayload`) - `/{NDID}/event` $\rightarrow$ 이상 이벤트 알람 파싱 (`ProcessEventPayload`) - `/{NDID}` (숫자형) $\rightarrow$ 측정값 파싱 (`ProcessMeasurementPayload`) * **신규 측정 Payload JSON 파서**: - `slave_data` 유무에 상관없이 신규 표준 JSON 골격(`gw`, `dev`, `wire`, `ch`, `total` 등) 및 기존 레거시 JSON 모두를 유연하게 수용할 수 있는 하이브리드 파서 구현. * **가동/미가동 상태 판정 로직 (`opStatus`) 고도화**: - `wire = '3P3W'`인 경우: `ch[0]`(A선) 및 `ch[2]`(C선) 전류 또는 `total.pf` / `total.p`를 반영하여 가동 상태(0: 전원꺼짐, 1: 미가동, 2: 가동) 판정. - `wire = '3P4W'`인 경우: 3개 상 전류 및 역률 반영. ### Phase 4: 화면 UI 및 모니터링 반영 (`uMain.pas`, `uMain.dfm`, `uNILMDeviceForm.pas`) * **실시간 모니터링 그리드 (`grdMQTTMonitor`)**: - 컬럼에 `결선(wire)`, `누적전력량(wh)`, `Total 유효전력(W)`, `Total 역률(pf)`, `RSSI(dBm)`, `통신상태` 등 표시 추가. - 3P3W 장비는 L2(B상) 열에 `"-"` 또는 `"미사용"` 표시하여 시각적 직관성 부여. * **트렌드 차트 (`Chart_Main`) 및 히스토리 조회**: - 3P3W 장비 조회 시 L2(B상)는 차트에서 비활성화/제외하고, `Total` 전력/역률 트렌드 보기 옵션 제공. * **장비 등록/수정 다이얼로그 (`uNILMDeviceForm.pas`)**: - 상수 선택 라디오그룹: `3상 3선식(3P3W)`, `3상 4선식(3P4W)`, `단상(SINGLE)` 선택 및 기본 토픽 포맷 자동 생성 가이드. ### Phase 5: OPC Server 태그 연동 고도화 * **신규 태그 확장 쓰기**: - `SYSTEM.{DeviceID}/wire` - `SYSTEM.{DeviceID}/wh` - `SYSTEM.{DeviceID}/total_p`, `SYSTEM.{DeviceID}/total_pf`, `SYSTEM.{DeviceID}/total_q` - `SYSTEM.{DeviceID}/rssi` - `SYSTEM.{DeviceID}/op_status` - 채널별 태그: `ch0_v`, `ch0_i`, `ch0_p`, `ch0_pf` (또는 기존 호환 `vrms_a`, `irms_a`, `active_power_a` 등) --- ## 4. 변경 대상 파일 목록 | 구분 | 파일명 | 변경 요약 | |:---|:---|:---| | 수정 | [`uNILMTypes.pas`](file:///c:/Users/MyName/Desktop/antigravity/AgentNILM_MQTTClient(Delphi13%20VCL)/uNILMTypes.pas) | 3P3W/3P4W 데이터 구조체, 채널/Total 레코드, 센서 템플릿 정의 | | 수정 | [`uNILMManager.pas`](file:///c:/Users/MyName/Desktop/antigravity/AgentNILM_MQTTClient(Delphi13%20VCL)/uNILMManager.pas) | DB DDL 스키마 확장, 신규 JSON 필드(wire/wh/total/rssi) 저장 및 히스토리/집계 함수 | | 수정 | [`uMain.pas`](file:///c:/Users/MyName/Desktop/antigravity/AgentNILM_MQTTClient(Delphi13%20VCL)/uMain.pas) | MQTT 토픽 분기(측정/status/event/gateway), 신규 JSON 파싱, 가동 판정, 그리드/차트/OPC 갱신 | | 수정 | [`uNILMDeviceForm.pas`](file:///c:/Users/MyName/Desktop/antigravity/AgentNILM_MQTTClient(Delphi13%20VCL)/uNILMDeviceForm.pas) | 3P3W / 3P4W 결선 선택에 따른 센서 설정 및 UI 매핑 | | 수정 | [`Docs/sungju_mqtt_1_34.dxp`](file:///c:/Users/MyName/Desktop/antigravity/AgentNILM_MQTTClient(Delphi13%20VCL)/Docs/sungju_mqtt_1_34.dxp) | 1~34번 장비 전체에 신규 MQTT 규격 태그(`total_p/q/s/pf`, `wh`, `freq`, `rssi`, `wire`) 추가 | --- ## 5. OPC Server DXP 파일 (`sungju_mqtt_1_34.dxp`) 분석 및 수정 계획 ### 분석 결과 * **장비 구성**: 1번 ~ 34번 장비 (총 34대) * **기존 태그 (장비당 47개)**: `COMM`, `OpStatus`, 상별(a/b/c) `vrms`, `irms`, `active_power`, `reactive_power`, `apparent_power`, `power_factor`, `phase_angle`, `vthd`, `ithd`, 에너지 항목 등 * **신규 추가 태그 (장비당 8개 신규 태그 추가 $\rightarrow$ 총 55개 태그/장비)**: 1. `total_p`: 전체 유효전력 (Float, Type 6, 주소 `N011`) 2. `total_q`: 전체 무효전력 (Float, Type 6, 주소 `N013`) 3. `total_s`: 전체 피상전력 (Float, Type 6, 주소 `N015`) 4. `total_pf`: 전체 역률 (Float, Type 6, 주소 `N017`) 5. `wh`: 누적 유효전력량 (Float/Double, Type 6, 주소 `N006`) 6. `freq`: 계통 주파수 (Float, Type 6, 주소 `N005`) 7. `rssi`: LoRa 수신감도 (Short, Type 2, 주소 `N004`) 8. `wire`: 결선 방식 (Short, Type 2: 0=3P3W, 1=3P4W, 주소 `N003`) --- ## 6. 검증 계획 (Verification Plan) ### 빌드 및 단위 검증 1. **컴파일 검증**: Delphi 13 컴파일러를 통해 문법 오류 및 타입 불일치 확인. 2. **DB 스키마 마이그레이션 검증**: `EnsureTables` 실행 시 기존 DB 데이터 손실 없이 신규 컬럼 정상 추가 확인. ### 시나리오 통합 테스트 1. **3P3W 측정 Payload 수신 테스트**: - `ch[1]`이 `null`인 3P3W JSON 수신 $\rightarrow$ 정상 파싱, L2 제외한 A/C 및 Total 값 올바르게 DB 저장 및 그리드 표시 확인. 2. **3P4W 측정 Payload 수신 테스트**: - 3상 4선식 JSON 수신 $\rightarrow$ A/B/C 3상 및 Total 전력 정상 처리 확인. 3. **서브토픽 분기 테스트**: - `.../{NDID}/status`, `.../{GWID}/gateway`, `.../{NDID}/event` 각각의 메시지 발행 시 해당 라우터가 정상 동작하는지 확인. 4. **가동/미가동 상태 판정 및 OPC 쓰기 테스트**: - 임계치 조건에 따른 `opStatus` 판정 및 OPC 태그 전송 검증.