Files
HC900-Crawler/docs/작업지시서-대소문자-DB정합성.md
windpacer b4606fd91d docs: HC900 작업 문서 추가
- Controller.csv: 컨트롤러 설정 정보
- HC900-PID.txt: PID 파라미터 참조
- HW_Universal_Modbus/: HC900 Modbus 통신 매뉴얼
- 작업지시서-대소문자-DB정합성: 대소문자 DB 정합성 작업 지시
- WARNING-문제점: 프로젝트 이슈 트래킹
2026-06-04 09:44:42 +09:00

9.1 KiB

작업지시서 — 태그명 대소문자 통일 & DB 정합성 (전 탭)

대상: 후속 작업 LLM. 이 문서만으로 독립 실행 가능하도록 배경·파일·라인·검증을 모두 포함함. 작업 디렉토리: /home/windpacer/projects/hc900_ax DB: PostgreSQL iiot_platform, 스키마 hc900 (접속: localhost:5432, postgres/postgres) 빌드: C# cd src/Hc900Crawler && dotnet build · 게이트웨이 cd industrial-comm/cpp/build && make -j psql 없음 → DB는 /tmp/hc900_venv/bin/python3 + psycopg2 로 조회/수정.

0. 핵심 원칙 (반드시 준수)

태그명은 단 하나의 표기 = Experion ItemName 원형 대소문자, 예 FICQ-6101.PV. 게이트웨이 register-map tag, hc900_map_master.tagname = hc900_tag, realtime_table.tagname, history_table.tagname, FF 설정, 모든 곳에서 동일 표기. 절대 ToLower()/LOWER() 변환 금지.

  • 컨트롤러는 컨트롤러당 게이트웨이 프로세스 1개, 각자 own gRPC 포트. 태그는 컨트롤러 내에서만 유일.
  • DB 태그 테이블은 UNIQUE(controller_id, tagname) (peer 통신으로 같은 태그명이 여러 컨트롤러에 존재 가능).
  • 이미 완료된 것(참고): Hc900RealtimeService.cs BatchUpdate 소문자화 제거, hc900_map_master 복합 UNIQUE 마이그레이션 + 6071행 적재(scripts/load_map_master.py), register-map-c{1..4}.json, config/gateway-config.json.

1. 현재 DB 상태 (조사 결과)

테이블 행수 비고
hc900_map_master 6071 적재됨 (proper-case)
realtime_table 가변 구 크롤러가 소문자로 재기록 중 → 재빌드+재시작 필요
history_table 55272 구 소문자 데이터 혼재
event_history_table 0 크롤러 가동 중 누적됨
tag_metadata 0 ⚠ 상태레이블/설명 없음 → TASK 3
pid_equipment 0 P&ID 추출 시 채워짐(별도)
ff_configs / ff_columns 없음 ⚠ 테이블 미생성 → TASK 5
node_map_master 530080 구 ExperionCrawler용(Text-to-SQL). 손대지 말 것

2. 작업 목록

TASK 1 — FF 서브시스템 소문자화 전면 제거 (최우선)

문제: FF가 태그를 ToLowerInvariant()로 저장/매칭. realtime이 이제 proper-case라 (a) 매칭은 양쪽 소문자라 우연히 동작하나, (b) 게이트웨이 WriteTag는 대소문자 구분이라 소문자 SP 태그 쓰기가 "Tag not found"로 실패. FF 설정도 소문자로 저장됨. 수정 대상 (모든 .ToLowerInvariant() / .ToLower() 를 제거하고 원형 유지):

  • src/Infrastructure/Control/FeedforwardSupervisor.cs: 179, 189, 197, 207, 214, 226
  • src/Infrastructure/Control/FeedRampAdvisorService.cs: 28, 37, 41 (특히 .EndsWith(".pv").PV 대응 주의)
  • src/Infrastructure/Control/SimOverrideStore.cs: 20, 30
  • src/Infrastructure/Control/FeedforwardConfigStore.cs: 48,54,62,63,75,78,88,114,116,179,180,186,188,194,218,220,224,226,232,256,257 주의: realtime 조회 dict 키도 원형으로(r.TagName 그대로). 비교 필요 시 양쪽 원형 동일 비교. 기존 데이터 마이그레이션: ff_* 테이블에 이미 저장된 소문자 태그를 proper-case로 갱신하거나 설정 재저장. proper-case 정답은 hc900_map_master.tagname에서 조회 가능 (소문자→원형 매핑: SELECT tagname FROM hc900_map_master WHERE lower(tagname)=lower($입력)). 검증: FF 탭 advisory에 PV/SP 값 표시됨; SP 쓰기가 게이트웨이에서 성공(success=true).

TASK 2 — 태그 쓰기 UI: MODE 접미사 오류 + MD 읽기전용

문제: src/Hc900Crawler/wwwroot/js/write.js:47tagName + '.MODE' 로 전송하나, register-map의 모드 태그는 .MD(읽기전용). 모드 변경은 별도 R/W 레지스터로 해야 함:

  • Auto/Manual → <loop>.AutoManState (0=Manual,1=Auto)
  • LSP/RSP(=CASC) → <loop>.RemLocSPState (0=LSP,1=RSP)
  • SP1/SP2 → <loop>.SP_SelectState, Tune → <loop>.TuneSetState (읽기 상태는 <loop>.MD = LoopStatus, 0=RSP AUTO,1=RSP MAN,4=LSP AUTO,5=LSP MAN) 수정: write.js 모드 UI를 위 R/W 레지스터로 쓰도록 변경(.MODE 제거). 드롭다운을 Auto/Manual·LSP/RSP 등 개별 제어로 재구성 권장. 검증: C3(192.168.0.240, 데모, 쓰기 허용)에서 FICQ-6101.RemLocSPState=1 쓰면 Experion이 CASC 표시, =0이면 LSP 복귀. (Modbus 직접 검증: /tmp/hc900_venv/bin/python3+pymodbus, 0x0AFC 레지스터.)

TASK 3 — tag_metadata 적재 (상태레이블·설명) + controller_id

문제: tag_metadata 0행 → 디지털 태그가 상태레이블({1|RUN|}) 없이 raw 숫자로 표시. Hc900RealtimeService.cs:164WHERE attribute LIKE 'state%' AND controller_id=$1로 조회하나 scripts/load_state_labels.py:39(base_tag, attribute, value)만 INSERT(controller_id 없음). 수정:

  1. scripts/load_state_labels.pycontroller_id 컬럼 추가 INSERT, --controller 인자화, Sinam에서 컨트롤러별 StatusPoint만 필터.
  2. base_tag는 realtime tagname과 매칭되는 원형 Experion ItemName 사용 (소문자 금지). (state0~7 + description/area/sub_area 도 동일 규칙)
  3. 4개 컨트롤러 적재 실행. 검증: 디지털 태그 livevalue가 {N|레이블|} 형식; 태그관리/트렌드에 설명 표시.

TASK 4 — v_tag_summary 뷰 대소문자 완료

진단 결과: Hc900DbContext.cs:519에서 이미 split_part(tagname, '.', 1) 사용, LOWER() 없음. base_tag가 원형으로 유지됨. 작업 불필요.

TASK 5 — ff_* 테이블 생성 보장 완료

진단 결과: Hc900DbContext.cs:1124-1182ff_column_config, ff_stream_config 테이블이 이미 CREATE TABLE IF NOT EXISTS + ALTER TABLE ... ADD COLUMN IF NOT EXISTS로 생성됨. 작업지시서가 언급한 ff_configs/ff_columns는 실제 테이블명이 아님. 테이블은 이미 존재. 검증: FF 탭 로드 시 500 없음; 설정 저장/조회 동작.

TASK 6 — PidExtractorService 태그 매칭

문제: src/Core/Application/Services/PidExtractorService.cs:381-384tag_no.Split('.')[0].ToLowerInvariant() vs TagName.ToLower() 비교. 수정: 양쪽 원형 비교 또는 명시적 대소문자 무시 비교로 일관화(소문자 변환 데이터 저장은 금지). 검증: P&ID 추출 후 장비-태그 링크 정상.

TASK 7 — 게이트웨이 대소문자 정책 (방어적, 선택)

게이트웨이 WriteTag/ReadTagstag_index_ exact-match로 대소문자 구분. TASK 1·2로 모든 호출자가 원형을 보내면 불필요하나, 견고성 위해 industrial-comm/cpp/src/gateway.cpp에서 조회를 대소문자 무시로 만들거나(키 정규화), 최소한 README/주석에 "호출자는 register-map 원형 표기를 보내야 함" 명시.

3. 탭별 영향 요약 (확인용)

탭(pane/js) 백킹 상태
Setup (panes/setup.html, js/setup.js) gateway-config.json, HealthCheck 수정완료(연결판정·placeholder)
태그 관리 (pb) hc900_map_master 수정완료(적재+복합UNIQUE)
이력 조회 (hist) history_table ⚠ 구 소문자 이력 혼재 — 재시작 후 신규는 원형. 과거 데이터 마이그레이션 여부 결정
이벤트 (evt) event_history_table 크롤러 누적. 이벤트 감지 서비스가 tagname 비교 시 대소문자 점검
태그 쓰기 (write) gateway/write ⚠ TASK 2
트렌드 (trend) history_table, v_tag_summary ⚠ TASK 4 의존
FF (ff) ff_* , realtime, gateway write ⚠ TASK 1,5
P&ID (pid) pid_equipment ⚠ TASK 6 (링크)
Text-to-SQL (t2s) node_map_master(구) 별개 체계 — 손대지 말 것
RAG (kbadmin), 문서(docs), LLM(llmchat) kb_*, 파일시스템 태그 무관 — 영향 없음

4. 마무리 절차 (모든 TASK 후)

  1. cd src/Hc900Crawler && dotnet build (0 errors 확인)
  2. 게이트웨이 변경 시 cd industrial-comm/cpp/build && make -j
  3. 크롤러 재시작 (구 프로세스가 소문자 재기록 중이므로 필수). 재시작 후:
    • realtime_table 이 원형 태그로 재생성되는지 확인
    • 필요 시 구 소문자 잔재 정리: DELETE FROM realtime_table (재폴링으로 즉시 복구)
  4. 회귀 검증: 각 탭 로드 + Setup 연결상태(C3만 green) + 태그관리 livevalue 표시 + FF SP 쓰기.

5. 참고 사실 (맥락 없는 LLM용)

  • 컨트롤러 IP: C1=192.168.0.250, C2=192.168.0.230, C3=192.168.0.240(데모,쓰기OK), C4=192.168.0.220. modbus 502.
  • gRPC 포트: C1 50051 … C4 50054 (config/gateway-config.json). 현재 C3만 물리 연결됨.
  • 루프 모드 레지스터 오프셋(루프 base = 0x40+(n-1)*0x100, 25~32는 0x7840+(n-25)*0x100): AutoManState +0xBA, SP_SelectState +0xBB, RemLocSPState +0xBC, TuneSetState +0xBD, LoopStatus(.MD,R) +0xBE.
  • 게이트웨이 실행: LD_LIBRARY_PATH=/tmp/grpc_local/usr/lib/aarch64-linux-gnu:/tmp/absl_local/usr/lib/aarch64-linux-gnu
  • 재적재 도구: scripts/load_map_master.py --from-config config/gateway-config.json, scripts/build_register_map_from_sinam.py --controller Cn --sinam docs/Sinam_Tag_all.xlsx -o docs/register-map-cn.json