Files
HC900-Crawler/CLAUDE.md
2026-06-10 08:12:01 +09:00

141 lines
5.3 KiB
Markdown

# CLAUDE.md
> **📌 [`docs/베이직아키텍처-태그-디자인-전면재설계.md`](docs/베이직아키텍처-태그-디자인-전면재설계.md)** 를 먼저 읽을 것 — 모든 아키텍처 결정 사항이 정의되어 있음.
## Project Overview
This project replaces the Experion OPC UA data path with a direct Modbus TCP connection to the Honeywell HC900 process controller:
```
Before: HC900 ──Modbus TCP──▶ Experion R530 ──OPC UA──▶ ExperionCrawler ──▶ PostgreSQL
After: HC900 ──Modbus TCP──▶ C++ Gateway ──gRPC──▶ HC900Crawler ──▶ PostgreSQL
```
**핵심 원칙:**
- 단일 진실 공급원 = **`docs/Sinam_Tag_all.xlsx`** (태그명·주소·메타데이터 전부 포함)
- **모든 태그명은 대문자** (OPC UA 강제 소문자 규칙 폐기)
- **컨트롤러별 독립 맵** (`register-map-cN.json`)
- Loop 블록은 **통째로 읽기** (개별 파라미터 금지)
- `build_register_map.py` 하나로 **맵 생성 + 메타데이터 적재** 모두 처리
Four active components:
- **`industrial-comm/cpp/`** — C++ gateway: Modbus TCP poller + gRPC server (`hc900_gateway` binary)
- **`src/Hc900Crawler/`** — C# .NET 8 ASP.NET Core web app: full monitoring platform (gRPC client + web UI + KB/P&ID/FF)
- **`mcp-server/`** — Python FastMCP server (port 5001): RAG, NL2SQL, P&ID processing tools
- **`scripts/`** + **`test/`** — Python utilities for register map generation and testing
## Commands
### C++ Gateway (build)
gRPC and abseil are pre-installed to `/tmp/grpc_local` and `/tmp/absl_local` (aarch64).
```bash
cd industrial-comm/cpp
mkdir -p build && cd build
cmake ..
make -j$(nproc)
```
Produces `build/hc900_gateway` and `build/libcomm_core.so`.
Run the gateway:
```bash
./build/hc900_gateway [host] [register-map-path] [poll_ms]
# defaults: 192.168.0.240, docs/register-map-c3.json, 1000
```
Log file: `/tmp/hc900_gateway.log`. gRPC listens on `0.0.0.0:50051`.
### C# Crawler (build + run)
```bash
cd src/Hc900Crawler
dotnet build
dotnet run
```
Configuration via `appsettings.json`: `Hc900.GatewayAddress` (default `http://localhost:50051`), `Hc900.PollIntervalMs`, `ConnectionStrings.DefaultConnection` (PostgreSQL, `Search Path=hc900`). Serves web UI at `http://0.0.0.0:5000`.
### Register Map Generation (단일 스크립트)
`docs/Sinam_Tag_all.xlsx` 하나로 모든 처리:
```bash
python3 scripts/build_register_map.py \
--xlsx docs/Sinam_Tag_all.xlsx \
-o docs/register-map-c3.json \
--controller C3 \
[--db-conn "Host=...;Database=hc900;..."]
```
출력:
- `register-map-cN.json` — 게이트웨이용 레지스터 맵
- `tag_metadata` upsert (state labels, units, desc, area)
**더 이상 `load_state_labels.py`를 별도 실행할 필요 없음.**
### Test Utilities
```bash
# Start Modbus TCP simulator (port 5020, loads register-map.json)
python3 test/modbus_sim.py
# Read tags directly via Modbus TCP
python3 test/read_tags.py FICQ-6101.PV FICQ-6101.SP FICQ-6101.MODE
python3 test/read_tags.py --port 5020 FICQ-6101.PV # against simulator
python3 test/read_tags.py --all --limit 50
```
## Architecture
**반드시 [`docs/베이직아키텍처-태그-디자인-전면재설계.md`](docs/베이직아키텍처-태그-디자인-전면재설계.md) 를 읽을 것.** 여기서는 요약만 기술.
### C++ Gateway (`industrial-comm/cpp/`)
**`Hc900Gateway`** (`src/gateway.cpp`, `include/gateway.h`) is the core class:
- Loads `register-map-cN.json` at startup into `registers_` and `tag_index_`
- Spawns poll thread (`PollLoop`) → `ReadAllRegisters()` every `poll_interval_ms`
- Groups consecutive registers into batches of **≤120** (FC03), **Loop 블록은 통째로 192 regs**
- Cache (`cache_`, protected by `cache_mutex_`); quality=192=good, quality=0=bad/stale
- `transport_mutex_` serializes Modbus calls between poll thread and gRPC `WriteTag`
**Key gRPC operations:**
- `ReadTags` — from cache, no Modbus I/O
- `WriteTag` — FC16 directly, then update cache
- `StreamTags` — push cache at interval
- `ListTags` — metadata from register list
- `HealthCheck` — connection state, poll count, duration
**`Controller`** → wraps `ITransport` with typed read/write. **`ModbusTCP`** → FC03/FC16. **Codec** → FP_B format.
### C# Crawler (`src/Hc900Crawler/`)
**Project layout:**
```
src/
Core/ ← Domain entities, interfaces, application services
Infrastructure/ ← DB (Hc900DbContext), HC900 services, Control, Kb, Mcp, Trend, Docs
Hc900Crawler/ ← ASP.NET Core web project
```
**BackgroundServices:**
- `Hc900RealtimeService` — gRPC poll → `realtime_table` upsert (500 rows/batch)
- `Hc900HistoryService` — 60s snapshot `realtime_table``history_table`
- `Hc900DigitalEventDetectorService` — 1s digital change detect → `event_history_table`
### Database (PostgreSQL, schema `hc900`)
| Table | Purpose |
|---|---|
| `realtime_table` | 실시간 값 (tagname, livevalue, timestamp) — upsert on conflict |
| `history_table` | 60초 이력 스냅샷 (TimeScaleDB hypertable) |
| `event_history_table` | 디지털 태그 상태 변경 이벤트 (TRIP/ALARM/RUN 등) |
| `tag_metadata` | 태그 메타 (desc, area, sub_area, state0-7, units) |
| `hc900_map_master` | 활성 태그 관리 (향후 단순화 예정) |
### HC900 Hardware
- Controller: HC900-C70, IP `192.168.0.240`, Modbus TCP port 502
- Unit ID: 1, Float format: **FP B**