141 lines
5.3 KiB
Markdown
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**
|