Files
ExperionCrawler/docs/측류추출식-통합유량설정공식-구현코딩-PhaseIII.md

12 KiB
Raw Permalink Blame History

측류추출 통합유량 — Phase III Auto-Write 구현 코딩 (RSP → DCS SP 쓰기)

성격: Phase I(advisory engine) + Phase II(UI 대시보드)에서 계산한 권장 SP(RSP)를 DCS Setpoint에 직접 쓰는(auto-write) 기능. Phase I 불변식("제어 레지스터 쓰기 0건")을 해제 — 단, 안전장치(WriteGuard)를 동반.


0. Phase 분할 현황

범위 Phase I (완료) Phase II (완료) Phase III (본 문서)
엔진 FeedforwardEngine.Tick θ 자동튜닝·바이어스 적응 (분석)
출력 권장 SP 저장 + 읽기 API 대시보드 시각화 (흐림/선명) DCS SP 쓰기
제어 Advisory(쓰기 0건) Advisory(쓰기 0건) Auto-write (조건부 쓰기)
설정 DB 테이블 + 로더 Web UI 설정 에디터 Auto-write On/Off 스위치
안전 WriteGuard + 워치독

1. 핵심 설계 원칙

1.1 Auto-write 조건

RSP를 DCS SP에 쓸 수 있는 조건은 다음 두 가지를 모두 만족해야 함:

WriteCondition = (Grade == A) AND (!Transient)
조건 의미 위반 시 조치
Grade == A 모델 파라미터(K, θ, τ)가 잘 튜닝됨 Grade B/C면 쓰지 않음
!Transient Feed/압력 안정 + 정착 대기 완료 Transient 중이면 이전 SP 홀드

1.2 Grade별 Auto-write 정책

Grade Auto-write 허용 근거
A 허용 K/θ/τ 튜닝 양호, 권장값 신뢰 가능
B 금지 튜닝 불확실성 존재, 운전원 수동 인가 필요
C 금지 모델 자체를 신뢰할 수 없음, 진단 우선

1.3 Transient 상태별 Auto-write 정책

상태 Auto-write RSP 처리 DCS SP 처리
정상(안정) 허용 최신 RSP로 갱신 RSP = DCS SP
FEED 이동 중 홀드 RSP는 계산 계속 (변함) 이전 SP 유지
압력 불안정 홀드 RSP는 계산 계속 (변함) 이전 SP 유지
정착 대기 중 홀드 RSP는 정상 계산 이전 SP 유지
FEAD BAD (Hold) 홀드 RSP = 이전 LastRec 이전 SP 유지

1.4 홀드 동작 상세

Transient 진입 시:

1. Transient 발생 (moving / pUnstable)
2. 현재 DCS SP 값을 snapshot으로 저장 (LastWrittenSP)
3. Transient가 지속되는 동안 DCS SP = LastWrittenSP 유지
4. Transient 해제 후:
   a. Grade == A → RSP로 즉시 갱신 (RSP는 transient 중에도 계속 계산됨)
   b. Grade != A → 쓰지 않음, 운전원 수동 인가 대기

RSP는 transient 중에도 매 틱 갱신되므로, transient 해제 시점에는 이미 최신 Feed를 반영한 값으로 부드럽게 전환됨 — ramp-up이 필요 없음.


2. WriteGuard 아키텍처

2.1 이중 조건 검증

[FF Engine] → RSP
                 │
                 ▼
         [WriteGuard]
           ├─ Grade == A ?
           ├─ !Transient ?
           └─ SP 변동폭 < SafetyLimit ?
                 │
          통과 ?──┤
                 │
              YES  NO
               │    │
           [Write]  [Hold]

2.2 SP 변동폭 제한 (SafetyLimit)

추가 안전장치로, 한 번에 변경 가능한 SP 폭에 상한을 둠:

|RSP - CurrentDCS_SP| > SafetyMaxDelta
→ 쓰지 않고 경고 로그, 운전원 확인 대기

제안값: SafetyMaxDelta = RateUpPerMin × 5min (5분 분량의 최대 변화율)

2.3 워치독 (Watchdog Timer)

- Auto-write 활성화 후 일정 시간(예: 30분) 동안
  Feed/압력 변화가 1회도 없으면 → 워치독 알람
- 의미: "RSP가 너무 오래 같음 — DCS가 FF를 추종 중인지 확인"

3. DCS 쓰기 인터페이스

3.1 쓰기 방식

DCS SP 쓰기는 OPC UA Write 서비스를 통해 수행:

OPC UA NodeId:     ns=3;s="{tag_name}.sp"  (예: "ficq-6118.sp")
데이터 타입:        Double
쓰기 권한:          WriteGuard 통과 시에만 호출

3.2 쓰기 주기

정상 상태:  매 Scan(2초)마다 RSP를 쓰지 않음
           → RSP 변화 감지 시에만 Write 호출
           → 변화 없으면 Skip (OPC UA 부하 감소)

Transient: 쓰지 않음 (Hold)
최초 쓰기: Auto-write On → 즉시 1회 Write

3.3 쓰기 실패 처리

- OPC UA Write 실패 → 3회 재시도 (1초 간격)
- 3회 실패 → Auto-write 자중단, 경고 로그
- 운전원 UI에 "DCS 쓰기 실패" 표시

4. UI: Auto-write On/Off 제어

4.1 설정 에디터 추가 항목 (Phase II ff.js 확장)

컬럼 편집 모달:

  [일반 설정]         [Auto-write 설정]
  컬럼명: C-6111      ☐ Auto-write 활성화
  Feed: ficq-6101     SafetyMaxDelta: ____
  ...                 워치독(분): ____

  [스트림]
  Key │ Flow 태그 │ 역할 │ 레벨태그 │ K │ θ_up │ ...
  P   │ ficq-6118 │ Commanded │    │ 0.95 │ 60 │ ...
  R   │ ficq-6113 │ Commanded │    │ 0.80 │  0 │ ...
  D   │ ficq-6114 │ LevelDriven │ lica-6113 │ 0.02 │ ...
  B   │ ficq-6116 │ LevelDriven │ li-6111   │ 0.03 │ ...

4.2 대시보드 표시

┌─────────────────────────────────────────────────────────┐
│  C-6111                          FEED 1000  12:34:56    │
│  [Auto-Write ● 활성]                                    │
│                                                         │
│  스트림 │ PV    │ 권장 SP │ DCS SP │ Δ    │ 신뢰 │
│  P      │ 780.2 │ 950.0   │ 950.0  │ —    │ A    │ ← auto-written
│  R      │ 623.0 │ 760.0   │ 623.0  │ -137 │ A    │ ← 수동 (환류)
│  D      │ 20.0  │ 20.0    │ 20.0   │ —    │ B    │ ← auto-written
│  B      │ 30.0  │ 30.0    │ 30.0   │ —    │ B    │ ← auto-written
│                                                         │
│  물질수지: 정상  V_loss: +0.5  수율: 95.0%              │
└─────────────────────────────────────────────────────────┘
  • DCS SP 열 추가 (현재 DCS에 쓰여진 SP 값)
  • Δ는 권장 SP - DCS SP (auto-write 중엔 보통 0)
  • Auto-write 활성 상태를 헤더에 뱃지 표시

4.3 Auto-write 활성화 조건

※ 전체 Column 단위 On/Off (스트림 개별 아님)

On 전환 조건:
  - 해당 Column의 모든 스트림이 Grade A는 아니어도 됨
  - 단, Grade A인 스트림만 Auto-write 대상
  - Grade B/C 스트림은 운전원 수동 유지

Off 조건:
  - 운전원 수동 Off
  - WriteGuard 연속 실패 (3회)
  - 워치독 타임아웃

5. DB 변경

5.1 ff_column_config (ALTER TABLE)

ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS auto_write_enabled BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS safety_max_delta DOUBLE PRECISION;  -- NULL=무제한
ALTER TABLE ff_column_config ADD COLUMN IF NOT EXISTS watchdog_min INTEGER NOT NULL DEFAULT 30;

5.2 신규 테이블: ff_write_log (감사 추적)

CREATE TABLE IF NOT EXISTS ff_write_log (
    id          BIGSERIAL PRIMARY KEY,
    column_id   INTEGER NOT NULL REFERENCES ff_column_config(id) ON DELETE CASCADE,
    stream_key  TEXT NOT NULL,
    sp_before   DOUBLE PRECISION,
    sp_after    DOUBLE PRECISION,
    grade       TEXT NOT NULL,
    transient   BOOLEAN NOT NULL,
    success     BOOLEAN NOT NULL,
    error_msg   TEXT,
    written_at  TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

6. 구현 파일 배치

변경:
  src/Core/Application/Feedforward/
    FeedforwardModels.cs                      # ColumnConfig: AutoWriteEnabled, SafetyMaxDelta, WatchdogMin
    IFeedforwardStores.cs                     # (변경 없음)
  src/Infrastructure/Control/
    FeedforwardEngine.cs                      # (변경 없음 — RSP 계산 로직은 그대로)
    FeedforwardSupervisor.cs                  # Auto-write 로직 추가 (WriteGuard 호출)
    FeedforwardConfigStore.cs                 # auto_write_enabled, safety_max_delta, watchdog_min 저장/로드
  src/Infrastructure/OpcUa/
    OpcUaClientService.cs                     # WriteNodeAsync(tag, value) — OPC UA Write 래퍼
  src/Web/Controllers/
    FeedforwardController.cs                  # GET/POST config에 auto-write 필드 추가
  src/Web/wwwroot/js/ff.js                    # 설정 에디터 + 자동쓰기 On/Off + DCS SP 표시
  src/Web/wwwroot/css/ff.css                  # DCS SP 열, auto-write 뱃지 스타일

신규:
  src/Infrastructure/Control/
    WriteGuard.cs                             # 조건 검증 + SafetyLimit + 워치독
    AutoWriter.cs                             # 조건 충족 시 OPC UA Write 호출
  docs/측류추출식-통합유량설정공식-구현코딩-PhaseIII.md  # 본 문서

7. 안전 시나리오

7.1 정상 동작

1. 운전원이 FF 설정에서 "Auto-write 활성화" ON
2. Feed/압력 안정, Grade A
3. RSP가 DCS SP에 자동 반영 (Scan 주기로 변화 감지 시)
4. 운전원은 모니터링만
5. 비정상 상황 시 수동 OFF → 즉시 쓰기 중단

7.2 Transient 발생

1. Feed 급변 → moving = true
2. WriteGuard가 transient 감지 → Write 차단
3. DCS SP는 마지막 값 유지 (변경 안 됨)
4. RSP는 내부적으로 계속 계산
5. 30분 후 transient 해제
6. WriteGuard 조건 재확인 → Grade A → 새 RSP Write
7. DCS SP가 최신 RSP로 점프 (ramp 불필요 — RSP는 transient 중에도 계산됐으므로)

7.3 OPC UA 단절

1. OPC UA 서버와 연결 끊김
2. Write 실패 → 3회 재시도 → 실패
3. Auto-write 자동 중단
4. 운전원 UI에 "DCS 쓰기 불가" 경고
5. 연결 복구 시 자동 재개 (선택 사항 — 운전원 확인 후 재활성화)

7.4 운전원 수동 개입

Auto-write 활성화 상태에서 운전원이 DCS SP를 수동 변경:
→ WriteGuard 감지 (DCS SP != LastWrittenSP)
→ 자동 쓰기 일시 중단 (예: 60초)
→ 60초 후 WriteGuard가 조건 재확인
   → 조건 만족: RSP로 다시 쓰기 (운전원 변경 덮어씀)
   → 조건 불만족: 중단 유지

※ 운전원 변경을 존중하려면:
   "수동 변경 감지 시 auto-write 영구 중단" 정책도 고려
   → UI에 "운전원 수동 변경 감지 — Auto-write 중단됨" 표시

8. Phase III 마일스톤

단계 내용 비고
M1 WriteGuard 구현 (조건 검증 + SafetyLimit) 단위테스트
M2 OPC UA Write 래퍼 (WriteNodeAsync) 기존 OpcUaClientService 확장
M3 AutoWriter 구현 (Guard → Write) + ff_write_log 통합테스트
M4 Supervisor에 Auto-wire 루프 통합 + Transient 홀드 Supervisor 확장
M5 DB: 컬럼 추가 + Config Store 확장 마이그레이션
M6 UI: 설정 에디터(Auto-write On/Off, SafetyLimit) + DCS SP 열 ff.js 확장
M7 UI: Auto-write 뱃지 + 쓰기 실패 표시 대시보드 확장
M8 종합 테스트 (시나리오 7.1~7.4) 감독자 진단

9. Phase I 불변식 해제 선언

Phase I 불변식: "제어 레지스터(SP/OP)에 쓰기 호출 0건"
Phase III에서 해제. 단, 아래 조건을 모두 만족해야 함:

✅ WriteGuard가 쓰기 허가를 내린 경우에만 Write
✅ Grade A && !Transient
✅ SafetyMaxDelta 초과 시 Write 금지
✅ 쓰기 실패 3회 → 자동 중단
✅ 운전원 수동 OFF 가능
✅ 모든 쓰기 내역은 ff_write_log에 기록 (감사 추적)