25 Commits

Author SHA1 Message Date
windpacer
b828647cca chore(sql): report_keep_qv_tags.sql 폐기표시 — 빌더가 근본 처리
응급 수동 보정(FIQ-*.QV를 addr=0/realtime=false로 keep 분류)은 이제 불필요.
빌더가 AnalogPoint 보조슬롯에서 FIQ-*.QV를 실제 주소·realtime=TRUE·archive=TRUE로
생성하므로 map 재빌드/--db-conn 적용 시 자동 분류·폴링된다. 이력 보존용으로만 유지.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 05:47:38 +09:00
windpacer
c7a115c928 fix(builder): AnalogPoint 보조 A1~A4 일반 어드레싱 + 폴링 대상화
이전(PR#5)은 비루프 AnalogPoint에만, 또 realtime=False로 보조를 넣어 적산 QV가
크롤러 폴링집합(is_active AND realtime_enabled)에서 빠져 라이브로 흐르지 않았다.

- is_analog 판정을 분기 앞으로 올려 모든 AnalogPoint(루프 포함)에 보조 처리 적용.
  루프 엔트리와 겹치면 seen_tags가 중복 흡수.
- 슬롯명 있는 A1~A4를 일반적으로 모두 어드레싱(공백 슬롯만 제외).
- realtime 기본값(True) 사용 → 보조도 폴링 대상. QV=연속 누적값만 archive 유지.
- FlexibleParameter(사용자정의)는 기존대로 realtime=False(폴링 제외) 유지.

맵 재생성(c1~c4): 순수 추가. C3 +6(FICQ-8118/LICA-5113 GAIN/RATE/RESET 등 루프
보조 누락분), 리포트 스팀적산 FIQ-*.QV 전부 포함, 제거 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 05:20:12 +09:00
windpacer
47149253aa fix(builder): AnalogPoint 보조 QV(AuxiliaryNameA*) 레지스터 생성
FIQ 류 적산기는 QV(적산)가 FlexibleParameter가 아니라 AnalogPoint 보조슬롯
(AuxiliaryNameA{n}=QV ↔ SourceAddressA{n})에 노출된다. 빌더는 FlexibleParameter
에서만 .QV를 만들어 FICQ-*.QV는 잡았지만 FIQ-*.QV(스팀 적산 등)를 전부 놓쳤다.
→ 리포트(energy_intensity_qv 등)가 의존하는 태그가 register-map/map_master에서
누락되어 archive 기준 '삭제대상'으로 오분류, 라이브 폴링도 안 됐음.

AnalogPoint else 분기에 보조 A1~A4 처리 추가: 이름 있는 보조슬롯을 실제
SourceAddress로 해석해 {item}.{AuxName} 엔트리 생성, QV=연속 누적값→archive=TRUE.
realtime=False(기존 .QV/FlexibleParameter와 동일 정책).

검증(dry build): C3 FIQ-6115/6215/8115.QV, C4 FIQ-9115/9215/10115/10215.QV 등이
실제 주소(8390 등)·archive=true로 생성. 커밋맵 대비 순수 추가(제거 0).
→ map 재빌드 시 keep 분류 자동 유지 + 라이브 적산 폴링 가능.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 20:55:44 +09:00
windpacer
bb99729e9e chore(report): 디지털잔재정리 문서 폐기 + 리포트 .QV 7개 keep 재분류
- docs/작업지시-history-디지털잔재정리.md: SUPERSEDED 배너(실행 금지).
  2026-06-18 실측 — 삭제대상(비-archive ~2천만)은 디지털 잔재 0, 전부 아날로그
  루프/적산. 특히 .QV는 리포트(history_table)가 의존 → 삭제 시 과거 리포트 파손.
- scripts/sql/report_keep_qv_tags.sql: SteamFlow 적산 FIQ-*.QV 7개를
  archive_enabled=TRUE로 재분류(register-map 누락 보정). realtime/is_active=FALSE
  로 폴링 부작용 0. 멱등(map 재빌드 후 재적용). DB에는 이미 적용.

검증: 리포트 태그 삭제대상 0행, 전체 삭제대상 19.98M→17.62M(2.36M 보호).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 20:42:37 +09:00
windpacer
400ba2c639 feat(report): P2-C 템플릿별 자동생성 스케줄러 — 멱등 catchup BackgroundService
- report_template에 schedule_enabled/period/hour/source 컬럼(ALTER IF NOT EXISTS,
  p0_report.sql + 서비스 EnsureSchema 멱등).
- Hc900ReportScheduleService: 매 N초 활성 템플릿마다 완료된 기간(anchor)을
  lookback 내 산출 → report_run 성공기록 없으면 FillAsync 생성·기록.
  중복 0(HasSuccessfulRun dedup)·다운타임 자동복구. 윈도는 셀 토큰 period=가 결정.
- IReportTemplateStore.UpdateSchedule/HasSuccessfulRun, ListAsync에 스케줄 컬럼.
- PUT /api/report/template/{id}/schedule (period/hour 검증).
- UI: 목록에 스케줄 상태 표시 + 선택 템플릿 스케줄 편집기.
- appsettings Report:Schedule (간격·catchup) 추가.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 21:30:17 +09:00
windpacer
c3a5258bf2 feat(report): P1d 실시간 알람 엔진 (kpi_alert) — P1 온라인 히스토리안 완료
운전모드/폐합 기반 실시간 알람 — P1 마지막 조각.

- kpi_alert 테이블(edge-trigger: 진입 active, 해제 resolved, DB상태라 크래시 무관).
- Hc900LiveKpiService 알람 평가: 최신 history_1s 샘플로 운전모드(cleaning/drawdown/normal) 판정
  + 폐합 이탈(normal & |closure-100|>tol). 룰: cleaning/drawdown(info), closure_deviation(warning).
- GET /api/report/alerts. Report:LiveKpi:ClosureTolerancePct(기본 2%) config.

검증: 라이브 C-8111 drawdown 알람 발화(feed≈0 포착), opened_at 고정·updated_at 갱신(edge-trigger),
/alerts 정상. (데모 sim은 임계 빈번교차로 flapping 가능 — M분 디바운스는 운영 튜닝.)

P1 완료: P1a 1초버퍼 · P1b 연속집계 · P1c 온라인누적기 · P1d 알람.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 08:15:29 +09:00
windpacer
b820e6c33a feat(report): P1c 온라인 KPI 누적기 (live_kpi) + 메트릭 소스 일반화
온라인 히스토리안 3계층 — 실시간 KPI를 history_1s에서 산출·캐싱.

- 메트릭 소스 일반화: history_table | history_1s | history_1min_src | fast_record.
  history_1min_src = 연속집계 드롭인 호환뷰(bucket→recorded_at).
- Hc900LiveKpiService: 매 15s 오늘(KST) 컬럼별 KPI(production/yield/energy/closure)를
  history_1s에서 재계산해 live_kpi upsert. 재계산=러닝상태의 stateless 동등판(causal 동치,
  크래시 복구 불필요). 컬럼 state(normal/idle/error) 산출.
- live_kpi 테이블 + GET /api/report/live 조회 엔드포인트.
- Report:LiveKpi config(Enabled/IntervalSeconds/Source).

검증: 라이브 live_kpi 28행(7컬럼×4KPI) 15s 갱신, /live 정상. 데모 sim은 totalizer가
평평해 값 0/idle(플러밍 정상, 실데이터면 실값).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 07:52:31 +09:00
windpacer
3506a67c28 feat(report): P1b 연속집계 history_1min — 1초 버퍼 60초 롤업(장기 무손실)
온라인 히스토리안 2계층: history_1s(최근 14일, 고해상) + history_1min(장기, 60초).

- history_1min 연속집계(timescaledb.continuous): time_bucket('1 min') + last(value)/last(controller_id).
  refresh 정책(start 3h, end 10min, 5분마다) → 집계 lag ≪ 보존윈도(14일)이라 1초 raw evict 전 materialize.
- Hc900FastHistoryService.EnsureSchemaAsync에 cagg 생성+정책 멱등 추가. SQL 파일 동기화.

검증: 2계층 값 일치(1s last == 1min cagg), 정책 활성, 무손실 불변식 충족.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 07:13:12 +09:00
windpacer
7f67f0e54d feat(report): P1a 1초 링버퍼 히스토리안 (history_1s)
온라인 히스토리안 1계층 — 디스크 상한 고정 1초 버퍼.

- history_1s Timescale 하이퍼테이블(1h 청크) + 압축(6h) + 보존 14일(청크DROP, 디스크 상한 고정).
- Hc900FastHistoryService: 매 1초 realtime_table 큐레이션 태그 → history_1s append.
  기동 시 스키마/정책 멱등 생성. Hc900HistoryService(60s) 패턴.
- ReportColumnMap.HistorianTags(): 메트릭/마스크가 읽는 태그를 기존 config에서 유도(~105개,
  중복정의 없음) — 유량 .PV/.QV, 진공, 민감단 TC, 하부루프 .PV/.SP/.OP.
- Report:Historian config(Enabled/IntervalSeconds/RetentionDays).

검증: 라이브 초당 ~38행 append, 샘플 간격 ~1.004s, 보존/압축 정책 활성.
주의(데모): realtime 폴링이 areas 61/62/81만 커버 → 1s 버퍼도 해당 컬럼만(배포 시 전 컨트롤러).
1s 버퍼 주 가치는 .PV/.OP 동특성; .QV 적산은 60s로도 정확.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 04:56:15 +09:00
windpacer
37a464ab96 feat(report): P0 셀프서비스 결정론 리포트 — 메트릭 3종·엑셀 토큰 채움·fastRecord 소스
운전원이 올린 엑셀 템플릿의 {{ metric=...; column=... }} 토큰을, 선택한 날짜의
결정론 계산값으로 채워 다운로드하는 셀프서비스 리포트 레이어(P0).

- 메트릭 3종: energy_efficiency·yield·control_residual (분 버킷 피벗, 클린필터,
  KST→UTC 경계). history_table(60s)·fast_record(s/min) 동일 long 포맷이라 source만 교체.
- 컬럼→태그 매핑은 기존 appsettings SteamAdvisor:Columns 재사용(7컬럼 무료).
- EPPlus 토큰 치환 + 셀 주석에 해상도 메타(source/sampling/n/keep) 부착.
- report_template/report_run 테이블 + cells_json 감사 박제.
- 리포트 탭(웹 UI) + 샘플 템플릿.

검증: 빌드 0에러. E2E 라운드트립 실동작(2026-05-15 C-6111 효율 0.778·수율 0.872·
잔차 mean 0.746 — 오프라인 검증값과 일치). 결정론 검증 게이트 준수(표본0=N/A, 0 날조 금지).

⚠️ EPPlus는 NonCommercial 컨텍스트 — 상용 출시 전 라이선스 정리 필요.

설계: docs/작업플랜-셀프서비스-분석리포트-MVP-P0-상세설계.md

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 00:14:35 +09:00
windpacer
18963455f2 feat: Steam 온도프로파일 제품명 사용자정의 + 자동매칭 폐지
- 제품 라벨(P0/P1)에 MSDS 화학물질명(PMA/PGMEA/EL) 매핑 레이어 추가
  (product_labels.json, 플랜트=컬럼별). 통계 기준밴드는 데이터 산출 유지
- 운전원용 ⚙제품명 설정 모달: GET/POST /api/steam/productlabels/{col}
- 온도기반 자동매칭 폐지 → 운전원이 고른 제품만 기준밴드로 비교, 미선택 시작
- 드롭다운: 탭 진입/컬럼변경 시 즉시 채움, 선택은 플랜트별 localStorage 유지
- 중복 '제품(수동)' 배지 제거(헤더 줄바꿈 해소)
- 설계·검수 문서 추가

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 16:56:50 +09:00
windpacer
f12290fc2b chore: 레지스터맵 생성 스크립트 정리 + field_hist import
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 08:12:01 +09:00
windpacer
f9a601e077 fix: 레지스터맵 dedup 흡수 정정 + PICA-9111A/9211A 컨트롤러 오기 수정
- dedup _pfx_num 정규식을 (\d+[A-Za-z]?)로: 단일 trailing letter(TI-6111A 등)를 번호키에 포함해 TICA-xxxxA로 흡수. 인터록/복합 suffix는 fullmatch로 보호.
- TI-6111A/5111A/6211A/8111A, PI-8111A, LI-2113A 등 중복 indicator 흡수 누수 해소.
- Experion 소스 오기 정정: PICA-9111A/9211A 알람SP가 C1 LOOP로 잘못 참조 → C4로 수정(xlsx) 후 C1·C4 맵 재생성.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 08:11:03 +09:00
windpacer
1f989bd861 feat: FF 온도계 위젯 + 민감단 모듈1 T_C 유지 SP 제안
위젯: AdvisoryResult에 config 시각화 필드 추가, ffThermometer() 세로 온도계 위젯 구현 (4단 마커+sweet spot 밴드+하한선+C편차 화살표+옵션 푸터)

모듈1: FeedforwardEngine SteamAdvisor DI + ResolveTcTemp, Normal 모드에서 T_C 유지 Steam OP 제안 (SteamAdvisor Predict + FB trim gain-0.6/dwell20분)
2026-06-07 08:22:43 +09:00
windpacer
7409fabc58 컬럼명칭 통일 C-xxxxx + SIGPIPE 대응 + SteamAdvisor/FF 개선
=== 컬럼명칭 통일 (c{prefix} → C-{prefix}11) ===
Python 분석스크립트: data pkl 경로  →
gen_temp_profiles: tempref 파일명  →
SteamAdvisorController: TagsFor() 숫자서픽스 → 풀컬럼키(C-6111), ToSuffix() 변환
steam.js: ST_TEMP_COLS ['61',...] → ['C-6111',...], selectbox defaultColumn
appsettings.json: Columns 키 c61/c62/... → C-6111/C-6211/..., DefaultColumn c6111→C-6111
run_column.py: 추출/분석시 col_key = f"C-{{prefix}}11"
C-{x}11_{model,tempref}.json: 신규 명칭 기준 기준프로파일/모델 7컬럼분

=== SteamAdvisor 수정 ===
SteamModel: [JsonPropertyName] 매핑(snake_case → PascalCase 역직렬화)
예외처리: LinearCoeffs.Count < 3 방어코드
steam.js: catch(_) {} → 에러메시지 표시, missing_tags 응답처리

=== Feedforward Controller 개선 ===
ff.js: 상승/하강 양방향 램프 confirm, 방향뱃지(↑↓), Normal 모드 표시
FeedforwardController: 업램프 단독제한 제거(양방향), tcReturnTcTarget/Band 노출

=== DB ===
Hc900DbContext: realtime_table_tagname_key 레거시 UNIQUE 제약/인덱스 DROP 로직
Hc900Controllers: ToDictionaryAsync → GroupBy 변환 (중복 tagname 대응)

=== SIGPIPE 대응 ===
gateway.cpp: signal(SIGPIPE, SIG_IGN) 메인스레드 설치
modbus_tcp.cpp: send() flags 0 → MSG_NOSIGNAL (EPIPE 복구)
sigpipe_ignore.c: LD_PRELOAD 우회 공유라이브러리
Hc900GatewayProcessService: LD_PRELOAD 환경변수 설정
2026-06-07 00:29:47 +09:00
windpacer
7b21c35af6 feat: 민감단온도 전환복귀제어 + SteamAdvisor + FeedRamp 전면 구현
=== 민감단온도(T_C) 전환복귀제어 (작업플랜 구현) ===
- FeedforwardModels: TempLowLimit, TcReturnRebTarget/Band, TcReturnDeltaAdRef/Band 추가
- FeedforwardEngine: sigTLow (T_C 하한 트리거, -1e9=비활성) + 온도기반 복귀게이트(tcRecovered)
  -> Recovering→Returning 전이: mbRecovered(물질수지) OR tcRecovered(reb-A+ΔT+T_C)
- FeedRampCalculator: 하강 램프 전면 구현 (RateUpPerMin/RateDnPerMin 분리, θ_up/θ_dn 분기, floor clamp)
- FeedRampExecutorService: 하강 램프 step 방향 지원
- FeedforwardConfigStore: 신규 6개 컬럼 SELECT/INSERT/UPDATE
- Hc900DbContext: temp_low_limit, tc_return_reb_target/band, tc_return_delta_ad_ref/band
- FeedforwardController: API 노출 + feed-ramp start/cancel/status

=== SteamAdvisor ===
- SteamAdvisorController: steam map 로드/시각화/제품매칭/온도프로파일
- steam.js, steam.html: SteamAdvisor 전용 UI 패널

=== Feed Ramp 실행 ===
- FeedRampExecutorService: BG service (BackgroundService)
- FeedRampJobStore: in-memory job store
- FfTrackingStore: ramp tracking DB
- FeedforwardSupervisor/WriteGuard: SP 쓰기 advisory + rate-limit

=== 분석 스크립트 ===
- gen_temp_profiles.py: 컬럼 온도 프로파일 기준 산출 → c{prefix}_tempref.json
- export_plotdata.py: analysis 결과 plot data export
- gen_instrument_ranges.py: 계기 범위 생성
- c6111_extract.py: C-6111 추출/운전모드 분류
- run_column.py: 전체 분석 파이프라인

=== Web UI ===
- ff.js/ff.html/ff.css: 전환류 상태기계 UI, TagBrowser, config save
- fast.js: Fast 조작 패널
- trend.js, pb.js, llmchat.js: 각 패널 확장
2026-06-06 18:33:56 +09:00
windpacer
23a9202b91 feat: 일별 리포트 스크립트 + 10차 시운전 caveat
- daily_report.py: 지정 기간 일별 운전값(피드·스팀·비율·온도) + 생산맵 예측품질
  (predOP_MAE·within2%·OOD) 표. --prefix/--asset/--start/--end/--train-end.
  6-2차 4~5월 검증: 신뢰구간 OP MAE 0.89%, 고부하(OOD) 외삽으로 최대 -10%.
- run_column.py: 10차(101/102)는 본 dump 창 대부분 시운전(PROD 2~6%) 주석.
  2026-06 생산 진입 → 데이터 누적/최신 dump 재반입 시 정상 분석 대상.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 21:47:37 +09:00
windpacer
3a7c9d60c3 fix: 10차 reb_level/reflux_drum 매핑 정정 (LIA vs LICA 혼동)
10차는 리보일러 레벨이 LI-10111이 아니라 LIA-10111(10-1)/LIA-10211(10-2).
기존 예외가 이를 reflux_drum으로 잘못 라벨 → 정정:
- reb_level → LIA-10111/LIA-10211 (사용자 확정)
- reflux_drum → base 규칙 LICA-10113/LICA-10213 (실존, 리플럭스 드럼)

검증: 8개 컬럼 전부 16/16 해석(5차는 T_C=TI-5111B 대체로 T_B와 공유).
참고: reb_level·reflux_drum은 현재 FEATURES·startup 미사용(수집만).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 20:49:37 +09:00
windpacer
b45f0e2481 fix: 누락 솔벤트 컬럼 추가 (5차·9-2·10-2) + 5차 T_C 센서 부재 처리
run_column.py 실행목록에 빠졌던 컬럼 보완 — 전체 8개 측류 솔벤트 컬럼 커버:
- 5차(51/P5) 신규 추가: 완전 누락이었음. 민감단 TI-5111C 센서 부재(A/B/D만)
  → COLUMN_EXCEPTIONS["51"]에서 T_C를 TI-5111B로 대체(사용자 확정).
- 9-2(92), 10-2(102) 추가: COLUMN_EXCEPTIONS엔 있었으나 COLUMNS 실행목록 누락.

검증: 8개 컬럼 핵심 FEATURES 전부 해석 OK, 5차·9-2 추출 스모크 정상(336519행).
(플랜트8은 단일 train=81, 8-2 없음 확인.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 20:45:04 +09:00
windpacer
4306f76ddb feat: 형제 컬럼(6-2~10차) 분석 + SHUTDOWN + operator-assist + C# SteamAdvisor 포팅
- c6111_extract: roles_for() 동적 생성, COLUMN_EXCEPTIONS per-prefix
- c6111_prodmap/shadow/startup/rolling: --data/--prefix CLI 인자 지원
- run_column.py: 5개 컬럼 전 파이프라인 실행 래퍼
- c6111_shutdown.py: detect_cutoffs + shutdown_milestones (lookback 1200)
- c6111_operator_assist.py: OOD 게이트 + shadow 리플레이
- c6111_export_model.py: 선형근사 JSON export
- SteamAdvisor.cs: Predict+ClassifyMode+InEnvelope (NaN guard, Ood fix)
- SteamAdvisorController: GET/POST /api/steam/predict
- appsettings.json/Program.cs: DI 등록
- docs: 작업지시서 현황 갱신, 진단보고서 작성 (3 MED/8 LOW, 100% 정확도)
2026-06-05 19:46:57 +09:00
windpacer
1bc46b1eb0 feat: 6-1차 컬럼 학습형 제어 오프라인 분석 (생산맵·shadow·startup)
신암정유 6-1차 측류 솔벤트 컬럼(C-6111) 실데이터로 오퍼레이터 모방 제어 분석:

- 데이터 추출기 tag_frame() (field_hist WIDE 포맷 디코드) + 운전모드 분류
- ① 생산맵: 스팀유량=f(피드,제품,목표T_C) 운전점 GBM R²0.99 (steam/feed≈0.73)
- shadow 백테스트: in-envelope 오퍼레이터 OP 94% 모방, OOD 게이트→폴백
- 롤링 재학습: 새 로드레짐 적응 (5월 OP MAE 3.9→1.2%)
- 캠페인내 트림: 컬럼 자기제어, 피드백 미미 → 전향 맵이 제어 지배
- ② START-UP 절차: 레시피 + 제품컷인 트리거(reb-A 84.5℃, ΔT 2℃, 조건기반)

문서: 설계·진행 플랜 + 남은 작업(형제확장·shutdown·assist·live포팅) 작업지시서.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 17:33:17 +09:00
windpacer
62a9631fe6 feat: 컨트롤러 설정 생성 스크립트 + map_master 로더 + 스캔시간 측정
- build_controllers_config.py: gateway-config.json 생성
- load_map_master.py: hc900_map_master 테이블 적재
- measure_scan_time.py: HC900 스캔 시간 측정 유틸
2026-06-04 09:44:45 +09:00
windpacer
daeb5316a2 refactor: 태그 대소문자 register-map 기준 대문자로 전역 통일
- FeedforwardSupervisor: PvTag() ToUpperInvariant + empty FeedTag 가드
- FeedforwardConfigStore: 모든 ToLowerInvariant() 제거
- FeedRampAdvisorService: ToLowerInvariant 제거 + StringComparison.OrdinalIgnoreCase
- SimOverrideStore: ToLowerInvariant 제거
- Hc900RealtimeService: HealthCheck SERVING 판정, mapping 없는 태그 대소문자 유지
- PidExtractorService: ToLowerInvariant → OrdinalIgnoreCase 비교
- Hc900Entities: 주석 업데이트 (대문자 표준)
- load_state_labels.py: 소문자 변환 금지, controller_id 파라미터 추가
- Hc900Controllers: 대소문자 무시 정렬
- write.js: .MODE → AutoManState/RemLocSPState/SP_SelectState/TuneSetState
- setup.js/html: 중복 함수 제거, C5 컨트롤러 placeholder
2026-06-04 09:43:37 +09:00
windpacer
f9f6a04054 feat: Sinam_xlsx 기반 register-map 재생성 + C1-C4 컨트롤러 추가
- register-map.json 재생성 (C3: 328→1974 registers)
  - .PV/.SP/.OP 등 suffix 추가, write_addr 필드 도입
  - LOOP_LAYOUT 기반 고정 레이아웃 전개 + 명명되지 않은 레지스터 보존
  - FC16 쓰기를 위한 write_addr 분리 (.MD는 LOOPSTAT 읽기/MODEIN 쓰기)
- build_register_map_from_sinam.py 리팩터
  - --controller 인자 추가 (C3/C4/C5 복수 컨트롤러 지원)
  - --validate-csv 옵션 추가 (HC Designer CSV 교차검증)
  - tag명 대문자 유지 (ToLower 금지)
  - 출력 경로 Path 객체 사용
- gateway-config.json: C1-C4 컨트롤러 설정 추가
2026-06-04 09:43:14 +09:00
windpacer
16fc7a2598 Initial commit: HC900 Crawler
Honeywell HC900을 Modbus TCP로 직접 폴링 → gRPC → C# 크롤러 → PostgreSQL.
기존 Experion OPC UA 데이터 경로를 HC900 직접 통신으로 대체.

- industrial-comm/cpp: C++ Modbus 게이트웨이 (gRPC 서버)
- src: C# .NET 8 ASP.NET Core 크롤러 + 웹 UI (3-Layer)
- mcp-server: Python FastMCP (RAG/NL2SQL/P&ID)
- 다중 컨트롤러(N-Controller) 지원

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 20:28:14 +09:00