상용 히스토리안 연동: AVEVA/OSIsoft PI
📍 현재 위치: Part IV · 현실과 마주하기 — 우리는 모든 것이 오픈소스인 안전지대를 떠나, 대부분의 공장이 결코 교체를 허락하지 않을 단 하나의 시스템, 즉 검증된 상용 히스토리안(historian)에 우리 스택을 연결한다.
공장의 PI 시스템(PI System)을 은행 금고 안에 있는 공식적이고 공증된 원장(ledger)이라고 생각해 보자. 우리는 그것을 버릴 수 없고, 솔직히 버리고 싶어 해서도 안 된다 — 감사관(auditor)이 그것을 신뢰하고, 이미 검증을 마쳤으며, 현장 전체가 이미 거기서 데이터를 읽어 가기 때문이다. 우리가 할 수 있는 일은 금고 옆에 빠르고 친절한 복사기를 만드는 것이다. 이 복사기는 우리의 분석을 위해 원장의 충실한 사본을 만들어 내고, 우리가 무언가 새로운 것을 계산하면 그 사본을 적절한 창구를 통해 되돌려 줄 수 있다. 이 장에서는 바로 그 복사기 — 우리 오픈소스 스택과 상용 히스토리안 사이의 깔끔한 경계 — 를 만들고, 어느 쪽이 원본을 보유하는지에 대해 정직하게 다룬다.
이 장에서 다루는 내용
지난 열여섯 개 장에 걸쳐 우리는 완전한 오픈소스 데이터 플랫폼을 구축했다. OPC UA 바이오리액터(bioreactor), 스파크플러그 버스(Sparkplug bus), TimescaleDB 히스토리안, PostgreSQL 안의 ISA-88/95 모델, 컨텍스트화(contextualization) 뷰, 그리고 지식 그래프(knowledge graph)까지. 이 모든 것이 노트북 한 대에서 돌아간다. 그렇다면 이 장은 왜 존재하는가?
실제 바이오의약품 공장에서 기록 원본(record of truth) 히스토리안은 거의 결코 여러분이 방금 만든 그것이 아니기 때문이다. 그것은 검증된 AVEVA PI 시스템(예전에 OSIsoft PI로 브랜딩되었던 제품)이며, 수년간 쌓인 GMP 공정 데이터의 **기록 원본(record-of-truth)**이다. 이 책의 정직한 하이브리드(honest-hybrid) 이야기는 바로 여기서 시작된다. 이 장에서 다루는 내용은 다음과 같다.
- GMP 히스토리안 기록이 왜 상용으로 남는지, 그리고 그것이 왜 오픈소스의 실패가 아니라 더 낮은 위험의 선택인지.
- 여러분이 실제로 엔지니어링하는 두 경계: PI Web API(REST)와 OPC UA.
- OSS 사본과 PI 원본이 일치하도록 하는 백필(backfill) 및 조정(reconciliation) 패턴.
- 실제 PI 서버에 접근할 수 없을 때 **PI 스텁(stub)**을 상대로 브리지를 개발하고 테스트하는 방법.
참고로 cGMP는 current Good Manufacturing Practice(현행 우수 제조 관리 기준)로, 의약품 제조가 통제되고 문서화되며 재현 가능해야 한다는 FDA의 구속력 있는 기대를 말한다. 이 단어를 기억해 두자. 금고가 잠긴 채로 남아 있는 이유가 바로 그것이다.
왜 기록 원본은 상용으로 남는가
PI 시스템은 단순한 데이터베이스가 아니다. 그것은 압축된 시계열 태그(tag)를 담은 **PI 데이터 아카이브(PI Data Archive)**에, 원시 태그를 계층 구조, 속성, 단위, 템플릿으로 컨텍스트화하는 자산 중심 계층인 **PI 자산 프레임워크(PI Asset Framework, AF)**를 더한 것이다 [1]. 현장은 일반적으로 이를 검증하는 데 수년을 들인다. 설치 적격성 평가(installation qualification), 운영 적격성 평가(operational qualification), 변경 관리(change control) SOP, 검토를 거친 감사 추적(audit trail)까지. 품질 위험 관리(quality risk management) 관점에서, 오픈소스 히스토리안을 좇겠다고 이것을 뜯어내는 것은 환자에게 거의 이득이 없으면서 노력과 위험이 큰 행동이다. ICH Q9(R1)은 위험 관리의 노력, 형식성, 문서화가 위험 수준에 상응해야 한다고 명시한다 [2] — 그리고 검증된 기록 시스템을 교체하는 위험은 크다.
FDA의 컴퓨터 소프트웨어 보증(Computer Software Assurance, CSA) 가이던스도 같은 방향을 가리킨다. 이는 위험 기반의 최소 부담(least-burdensome) 접근법을 권장한다. 보증 노력을 환자 위험이 있는 곳에 집중하고, 그 외에는 기존 통제에 의존하라는 것이다 [3]. 이것이 우리에게 깔끔한 역할 분담을 준다. 검증된 PI 시스템은 높은 엄격성이 요구되는 GxP 기록을 담당한다. 우리의 오픈소스 계층 — TimescaleDB, Grafana, 소프트 센서(soft sensor) — 은 더 낮은 위험의 분석 및 엣지(edge) 보완재다. 그것은 계산하고, 시각화하고, 탐색한다. 그것이 기록 원본일 필요는 없다.
이것이 바로 디지털 트윈(digital twin) 문헌이 기술하는 아키텍처다. 데이터 히스토리안은 기록의 통합 허브이며, 공정 데이터는 OPC와 TCP/IP 전송을 통해 거기서 클라우드와 분석 계층으로 복제된다 [4]. 우리는 새로운 패턴을 발명하는 것이 아니다. 우리는 누가 원본을 소유하는지를 명확히 인식한 채, 정립된 패턴을 오픈소스로 구현하고 있는 것이다.
데이터 무결성(data integrity) 용어는 그 경계를 정밀하게 만든다. MHRA의 GXP 가이던스는 **원본 기록(original record)**과 **진정 사본(true copy)**을 구별한다 [5]. 검증된 PI 시스템은 전체 감사 추적과 동적 데이터를 갖춘 원본 GxP 기록을 보유한다. 우리의 OSS 계층은 진정 사본과 파생 데이터를 보유한다. 설계 검토 회의에서 이 말을 소리 내어 하면 품질 부서(quality unit)는 안심할 것이다. 여러분은 그들에게 원본을 오픈소스에 맡겨 달라고 요청하는 것이 아니기 때문이다.
이데올로기가 아니라 엔지니어링으로서의 OSS↔PI 경계: PI는 원본 GxP 기록을 보관하고, 오픈소스 계층은 진정 사본을 보유하며 통제된 문을 통해 파생 값을 되돌려 쓴다. Original diagram by the authors, created with AI assistance.
두 경계: PI Web API와 OPC UA
현대 PI 시스템으로 들어가는 문은 정확히 둘이고, 여러분은 둘 다 사용하게 될 것이다.
첫 번째 문 — PI Web API. 이것은 클라이언트 애플리케이션에 PI 데이터 아카이브와 AF 데이터에 대한 HTTPS 기반의 읽기 및 쓰기 접근을 제공하는 RESTful 인터페이스다 [6]. JSON을 사용하고, 방화벽 친화적이며, 파이썬(Python) 클라이언트나 Apache NiFi 흐름에 자연스럽게 들어맞는다. 시간 창(time window)에 걸친 스트림의 기록 값(recorded values)을 요청하고, 포인트(point)에 새 값을 POST한다.
두 번째 문 — OPC UA. PI는 OPC UA용 PI 커넥터/어댑터(PI Connector/Adapter)를 통해 OPC UA 서버로부터 데이터를 수집하며, 이는 OPC UA를 PI와 엣지 사이의 일급(first-class) 읽기/쓰기 경계로 만든다 [7]. OPC UA는 플랫폼 독립적이고 안전하며 방화벽 친화적이고 [8], 우리 바이오리액터가 이미 그것을 사용하므로, 이 문은 우리에게 거의 비용이 들지 않는다 — 기존의 opcua-server와 Telegraf의 OPC UA 입력 플러그인 [9]이 그대로 꽂힌다. 미묘하지만 중요한 부분은 **이력(history)**이다. OPC UA Part 11, 이력 접근(Historical Access)은 클라이언트가 단지 실시간 값뿐 아니라 이력 데이터와 이벤트를 읽고 쓰는 방법을 정의한다 [10]. 바로 이것이 PI를 상대로 한 간격 채우기(gap-filling)를 가능하게 하며, 아래에 나오는 조정 패턴의 중추다.
현장에서 통용되는 경험칙: PI가 우리로부터 실시간 데이터를 끌어가야 할 때는 OPC UA를 사용하고(PI는 수집기로 남고, 검증된 경로는 변하지 않는다), 우리가 PI에서 끌어와 분석하거나 계산된 값을 되돌려 쓸 때는 PI Web API를 사용하라. 전자는 PI의 수집을 검증된 채 손대지 않은 상태로 유지하고, 후자는 우리 분석 루프를 빠르게 유지한다.
PI Web API와 대화하기: 요청의 형태
AVEVA PI는 노트북에서 실행될 수 없고 공개 이미지를 제공하지 않으므로, 정직한 하이브리드 설계는 실물 대신 **목(mock)**을 상대로 개발하는 것이다 — 이 책이 SAP와 DeltaV에 대해 취하는 것과 동일한 접근이다. 그 목은 이제 제공된다. 실제 PI Web API와 동일한 요청/응답 *계약(contract)*을 지키고, 우리의 골든 배치(golden batch)를 제공하며, 쓰기를 받아들이는, examples/services/pi-web-api-stub/에 있는 작은 FastAPI 서비스다. 동반 저장소의 compose.yaml은 이를 commercial 프로필 아래에서 실행한다(기존의 core, semantics, analytics/ops 프로필과 함께). 후속 장에 나오는, 아직 구축되지 않은 dcs-mock과 sap-mock만이 로드맵에 남아 있다. 따라서 아래의 PI 스니펫은 요청/응답 계약으로 — 명확히 표시된 예시적 형태로 — 간주하되, 그것을 제공하는 스텁과 그것을 파싱하는 브리지는 실제이며 테스트된 코드(examples/chapters/17-bridge-pi-historian/pi_bridge.py, examples/tests/test_bridges.py로 검증됨)임을 기억하라. 경계 우리 쪽의 로더(loader) — 이 장 뒤에 나온다 — 역시 실제다.
PI Web API는 모든 것을 불투명한 WebId로 주소 지정한다. 태그("PI 포인트(PI Point)")를 그 WebId로 한 번 해석(resolve)한 다음, 시간 창에 걸쳐 기록 값을 읽는다. 기록 값 응답은 다음과 같은 모습일 것이다(예시적인 PI Web API JSON으로, AVEVA의 문서화된 스키마와 일치한다 — 여러분의 목이 제공하고 여러분의 브리지가 파싱할 형태다).
{
"Items": [
{ "Timestamp": "2026-01-18T23:58:00Z", "Value": 5.8214, "UnitsAbbreviation": "g/L",
"Good": true, "Questionable": false, "Substituted": false },
{ "Timestamp": "2026-01-18T23:59:00Z", "Value": 5.7589, "UnitsAbbreviation": "g/L",
"Good": true, "Questionable": false, "Substituted": false }
]
}
주목할 점이 두 가지 있다. 첫째, 저 역가(titer) 값들 — 5.8214와 5.7589 g/L — 은 우리의 골든 배치 BATCH-2026-001에 대한 BR101.Titer.PV의 정확히 마지막 두 판독값으로, datasets/fedbatch_timeseries.parquet(아래 로더가 읽는 바로 그 파일)의 1분 간격 트레이스에서 가져온 것이며, 그 파일은 23:59에 끝난다. PI와 우리 스택은 동일한 물리적 바이오리액터를 바라보고 있다. 둘은 소수점 자리까지 일치해야 마땅하다. 둘째, PI Web API는 품질을 단일 숫자 OPC 품질 코드가 아니라 Good/Questionable/Substituted 플래그로 드러낸다. 우리 히스토리안은 OPC 방식의 품질(Good은 192, Uncertain은 64)을 저장한다. 둘을 잇는 것은 한 번 작성하고 검증해 두는 작은 매핑 테이블이다 — 결코 나중에 생각할 일이 아니다.
되돌려 쓰는 것은 같은 문을 거꾸로 사용하는 것이다. {Timestamp, Value} 항목으로 이루어진 JSON 본문을 포인트의 기록 값 엔드포인트에 POST하는 것이다. 이것이 계산된 태그 — 가령 26장의 라만(Raman) 모델에서 나온 BR101.Titer.SoftSensor — 가 PI 세계로 다시 들어가, 운영자가 자신이 신뢰하는 계측기 태그 옆에서 그것을 보게 되는 방식이다.
OSS 사본이 안착하는 곳: 다른 모든 소스처럼 적재하라
경계 우리 쪽에서, PI에서 끌어온 값은 그저 또 하나의 시계열 행일 뿐이다. 그것은 모든 수집 장이 기록하는 동일한 ts.sensor_reading 하이퍼테이블(hypertable)에, 동일한 여섯 개의 열로 안착한다. 동반 저장소의 로더가 정확한 형태와 정확한 COPY 경로를 보여 준다 — 다음은 examples/tools/load_datasets.py에서 가져온 것이다.
def load_timeseries(conn) -> int:
df = pd.read_parquet(DATA / "fedbatch_timeseries.parquet")
buf = io.StringIO()
df[["ts", "tag", "value", "unit", "quality", "batch_id"]].to_csv(buf, index=False, header=False)
buf.seek(0)
with conn.cursor() as cur:
cur.execute("TRUNCATE ts.sensor_reading")
with cur.copy("COPY ts.sensor_reading (ts, tag, value, unit, quality, batch_id) "
"FROM STDIN WITH (FORMAT csv)") as copy:
copy.write(buf.read())
return len(df)
이 열들이 계약이다: ts, tag, value, unit, quality, batch_id. PI 브리지가 하는 일은 이보다 더 이국적이지 않다 — 그것은 PI Web API JSON을 정확히 이 형태의 행으로 바꾸어 COPY해 넣을 뿐이다. 같은 파일의 헤더가 그 설계를 명확하게 말한다.
This is the path Chapters 5-13 build up piece by piece; here it is one script so
the contextualization and ALCOA+ chapters have data to query. Idempotent: it
truncates the loaded tables first.
**멱등성(idempotent)**이라는 단어가 브리지에서는 모든 것의 핵심이다. 로더를 다시 실행해도 테이블은 같은 상태로 남는데, 먼저 truncate하기 때문이다. 운영 환경의 PI 브리지는 매 실행마다 세상을 truncate할 수 없으므로, 다른 방식으로 멱등성을 얻어 낸다. 제공된 스키마가 부과하는 한 가지 제약에 주목하라. platform/db/20-historian.sql은 ts.sensor_reading을 (tag, ts DESC)와 (batch_id, ts DESC)에 대한 비고유(non-unique) 인덱스만 가진 TimescaleDB 하이퍼테이블로 만든다 — (tag, ts)에 대한 기본 키(primary key)나 고유 제약(unique constraint)은 없다. 따라서 순진한 INSERT ... ON CONFLICT (tag, ts)는 구축된 그대로의 저장소에서는 실패한다. 현재 스키마가 실제로 지원하는 메커니즘은 **윈도우 삭제 후 삽입(delete-window-then-insert)**이다. 하나의 트랜잭션 안에서, 곧 백필하려는 태그와 시간 창의 행들을 DELETE한 다음, 새로 읽은 값들을 INSERT한다. 그러면 겹치는 창을 다시 읽어도 결코 행이 중복되지 않는다. (진정한 업서트(upsert)를 원한다면 먼저 UNIQUE (tag, ts) 인덱스를 추가해야 하며 — 하이퍼테이블에서는 그 인덱스가 파티셔닝 열인 ts를 반드시 포함해야 한다.) 같은 목표, 다른 메커니즘이다. 로더가 소비하는 CSV는 시뮬레이터가 내보내는 것을 본 것과 동일한 롱 포맷(long format)이다(다음은 골든 배치의 마지막 두 개의 1분 간격 행, 즉 fedbatch_timeseries.parquet의 꼬리 부분이다).
ts,tag,value,unit,quality,batch_id
2026-01-18 23:58:00+00:00,BR101.Titer.PV,5.8214,g/L,192,BATCH-2026-001
2026-01-18 23:59:00+00:00,BR101.Titer.PV,5.7589,g/L,192,BATCH-2026-001
왕복(round-trip)이 닫히는 것에 주목하라. 위의 PI Web API JSON과 이 CSV 행은 같은 측정값을 기술한다. 브리지의 유일한 임무는 그것이 참으로 유지되도록 하는 것이다.
백필과 조정: 두 사본을 일치시키기
실시간 스트리밍은 쉬운 90%다. 어렵고 GxP와 관련된 10%는 네트워크가 두 시간 동안 다운된 후 무슨 일이 일어나는가이다. 이제 OSS 사본에는 PI 원본에는 없는 간격이 생겼다. PI의 검증된 수집기가 정전 동안 버퍼링을 했기 때문이다. 바로 이것이 OPC UA 이력 접근이 중요한 이유다 [10]. 브리지는 누락된 창에 걸친 이력 값을 PI에 요청하여 구멍을 메울 수 있다.
견고한 백필 루프에는 네 가지 동작이 있다.
- 간격을 찾는다. 우리 히스토리안에서 태그별 최신
ts를 조회한다. PI에 그보다 더 새로운 것이 있다면 여기서는 누락된 것이다. - 이력을 읽는다.
[last_ours, now]에 대한 PI Web API 기록 값(또는 OPC UA HA 읽기)을 끌어온다. - 창을 교체하라, 무턱대고 덧붙이지 말라. 하나의 트랜잭션 안에서, 해당 태그와
[last_ours, now]창의 행을DELETE한 다음, 새로 읽은 값을INSERT한다 — 그래야 겹치는 창을 행 중복 없이 안전하게 다시 끌어올 수 있다. (제공된 하이퍼테이블이 아직 갖고 있지 않은UNIQUE (tag, ts)인덱스를 추가한 후에만INSERT ... ON CONFLICT로 전환하라.) - 조정한다. 겹치는 점들의 표본을 다시 비교하여 허용 오차(tolerance) 내에서 일치하는지 확인하고, 어떤 불일치든 조용한 덮어쓰기가 아니라 데이터 무결성 이벤트로 로깅한다.
출처(provenance)를 갖춘 시각적이고 재생 가능한 흐름을 원할 때는 Apache NiFi가 이를 위한 자연스러운 거처다. 그것의 InvokeHTTP 프로세서는 구성 가능한 엔드포인트를 호출하고 FlowFile 본문을 요청으로 보내는 HTTP 클라이언트로, 읽기에는 GET을, 쓰기에는 PUT/POST/PATCH를 지원한다 [11] — 정확히 PI Web API가 사용하는 동사들이다. 그러면 NiFi의 출처 기능이 누가 무엇을 언제 어디서 끌어왔는지를 기록하는데, 이는 조사 중에 금처럼 귀중하다. 조정 단계 자체는 두 사본을 상대로 한 평범한 SQL이다.
-- Reconcile the OSS copy against PI for one tag/window.
-- Flags any point where the copies disagree by more than tolerance.
SELECT o.ts, o.value AS oss_value, p.value AS pi_value,
abs(o.value - p.value) AS delta
FROM ts.sensor_reading o
JOIN stage.pi_recorded p ON p.tag = o.tag AND p.ts = o.ts
WHERE o.tag = 'BR101.Titer.PV'
AND o.batch_id = 'BATCH-2026-001'
AND abs(o.value - p.value) > 1e-6; -- expect zero rows
그 쿼리가 행을 반환한다면, 여러분의 사본이 어긋난 것이다 — 어쩌면 단위 변환 버그, 어쩌면 시계 편차(clock skew) 때문이다. 0개의 행을 반환하는 것이 여러분의 테스트 스위트가 하는 단언(assertion)이며, 그것이 진정 사본이 원본에 충실하다는 엔지니어링적 증명이다.
PI에 접근할 수 없는 상태에서 브리지 테스트하기
여러분은 이 코드의 거의 전부를 근처에 PI 서버 하나 없이 작성하게 될 것이고, 그래도 괜찮다 — 단, 분위기(vibe)가 아니라 계약을 상대로 테스트한다면 말이다. 이제 저장소에 제공된 정직한 하이브리드 설계는, 실제 PI가 노출하는 PIPoint, Stream, AF 엔드포인트를 노출하고, 골든 데이터를 제공하며, 쓰기를 받아들이는 pi-web-api-stub이다. 이것을 OpenAPI 스펙과 계약 테스트에 고정(pin)하라 — 그러면 schemathesis 같은 퍼징(fuzzing) 도구가 실제 PI가 지키는 것과 동일한 스키마를 상대로 스텁과 브리지를 모두 행사(exercise)할 수 있다. 이 책이 명확하게 강조하는 요점은 이것이다: 목표는 PI 측이 목 처리된 채로, 계약을 상대로 실제이며 테스트된 브리지를 갖는 것이다. 실제 PI가 있는 현장에 도달하면, 베이스 URL과 자격 증명(credential) 하나를 바꾸고, 실제 서버를 상대로 동일한 계약 테스트를 실행하면, 끝이다. 이 장에서 오늘 실행되는 산출물은 브리지(examples/chapters/17-bridge-pi-historian/pi_bridge.py)와 그 스텁을 상대로 한 테스트(examples/tests/test_bridges.py), 그리고 위의 로더(examples/tools/load_datasets.py)다.
읽기 경로를 위한 최소 계약 — 예시적이며, 제공된 스텁의 OpenAPI가 고정하는 형태다.
# pi-web-api-stub — read path contract (illustrative)
paths:
/piwebapi/streams/{webId}/recorded:
get:
parameters:
- { name: startTime, in: query, schema: { type: string } } # e.g. "*-2h"
- { name: endTime, in: query, schema: { type: string } } # e.g. "*"
responses:
"200": { description: Recorded values, content: { application/json: {} } }
이것이 이 장 전체의 정직한 핵심이다: 우리는 AVEVA PI를 노트북에서 실행할 수 없으므로, 그런 척하지 않는다. 우리는 계약을 고정하고, 그것을 상대로 가차 없이 테스트하며, 현실로 바꾸는 한 줄짜리 교체를 문서화한다.
왜 중요한가
이 경계를 잘못 다루면 두 가지 실패 중 하나를 마주하게 된다. 오픈소스 히스토리안을 GMP 기록으로 만들려다 — 어떤 OSS 히스토리안도 기본 제공하지 않는 검증, 감사 추적, Part-11 부담을 환자에게 아무런 이득도 없이 떠안거나. 아니면 두 사본이 조용히 어긋나게 두어, 여러분의 번지르르한 Grafana 대시보드가 감사관이 실제로 읽을 기록과 슬그머니 어긋나게 되거나.
올바르게 다루면 그것은 해방적이다. 검증된 PI 시스템은 계속 자기 일을 한다 — 원본 기록, 전체 감사 추적, 품질 부서가 승인하는 바로 그것 [5]. 여러분의 오픈소스 계층은 SPC, 다변량 모델, 소프트 센서를 위한 진정 사본에 빠르고 저렴하며 제약 없는 접근을 얻고, 계산된 통찰을 통제된 문을 통해 되돌려 줄 수 있다. GAMP 5 제2판은 오픈소스가 — 검증된 라이프사이클 안에서, 용도에 비례하는 공급자 및 위험 평가와 함께 — GxP에 속한다고 명시한다 [12]. 브리지는 그 라이프사이클이 그어지는 이음새다.
실제 현장에서는
승인된 제품을 만드는 거의 어떤 mAb 공장에 들어가든, 중심에 PI 시스템이 있고 그것에 데이터를 공급하는 DCS 수집기와 그것에서 데이터를 읽는 분석 도구가 그것을 둘러싸고 있는 모습을 보게 될 것이다. 이 장의 패턴은 교육용 단순화가 아니다. 그것은 통합 팀이 실제로 살아가는 방식이다. 우리가 모델링하는 유가식(fed-batch) CHO + Protein A 라인은 승인된 단일클론항체(monoclonal antibody, mAb)의 지배적 양식이며, 그 데이터는 20년 동안 PI 히스토리안에 안착해 왔다.
NIIMBL — 바이오의약품 제조의 발전을 위한 미국의 민관 협력 연구소 — 은 정확히 이런 종류의 상호운용성(interoperability) 작업에 자금을 지원하며, 그 SABRE 시설(델라웨어 대학교의 파일럿 규모 cGMP 시설로, 2024년 4월에 착공했으며 2026년 중반 현재 여전히 건설 중이다)은 OSS 분석 계층이 검증된 상용 시스템을 대체하는 것이 아니라 그 곁에 자리할 그런 종류의 현장이다. 우리 공정의 강화/연속(intensified/continuous) 변형 — 다중 컬럼 포착(multi-column capture)을 갖춘 관류(perfusion) — 은 이 요점을 더욱 날카롭게 할 뿐이다. 더 많은 센서, 더 많은 태그, 저렴한 오픈소스 분석을 원할 더 많은 이유, 그리고 검증된 히스토리안을 그대로 두어야 할 정확히 같은 이유.
이 계층에 대한 정직한 오픈소스 대 상용 평결: 오픈소스는 여러분에게 탁월하고 확장 가능한 히스토리안(TimescaleDB), 세계 수준의 대시보드(Grafana), 그리고 자유롭고 유연한 브리지(Telegraf [9], NiFi [11], 파이썬 PI Web API 클라이언트)를 준다. 그것이 주지 않는 것은 검사관이 전화했을 때 책임질 공급업체가 있는, 턴키(turnkey)이며 검증되고 Part-11 준비가 된 기록 시스템이다. PI는 그것을 준다. 따라서 더 낮은 위험의, 규정을 준수하는 행보는 하이브리드다: PI는 원본을 보관하고, OSS는 사고를 한다 [3][2]. 순수 오픈소스는 여러분에게 플랫폼의 약 80%를 준다. 이것이, 솔직히 말해, 마지막 GxP 1마일이 하이브리드인 이음새 중 하나다.
핵심 용어
- 히스토리안 / 기록 원본(Historian / record-of-truth) — 공식적이고 감사 추적이 갖춰진 공정 기록을 보유하는 시스템. 대부분의 공장에서 이것은 OSS 히스토리안이 아니라 검증된 AVEVA/OSIsoft PI 시스템이다.
- PI Web API — PI 데이터 아카이브와 자산 프레임워크 데이터에 대한 AVEVA의 RESTful HTTPS 읽기/쓰기 인터페이스 [6].
- PI 자산 프레임워크(PI Asset Framework, AF) — 원시 PI 태그를 계층 구조, 속성, 단위로 컨텍스트화하는 자산 중심 계층 [1].
- WebId — PI Web API가 포인트, 스트림, AF 요소를 주소 지정하는 데 사용하는 불투명한 식별자.
- OPC UA 이력 접근(OPC UA Historical Access, HA) — OPC UA Part 11. 이력 값과 이벤트를 읽고 쓰는 것으로, 백필의 기반 [10].
- 백필(Backfill) — 정전 후 PI 원본에서 누락된 창을 읽어 OSS 사본의 간격을 채우는 것.
- 조정(Reconciliation) — 겹치는 창에 걸쳐 두 사본을 비교하여, 조용히 덮어쓰는 대신 불일치를 표시하는 것.
- 멱등성(Idempotent) — 반복해도 안전한 연산. 제공된 히스토리안(
(tag, ts)에 고유 제약이 없는)을 상대로, 브리지는 해당 창을 삭제하고 다시 삽입하여 이를 달성하므로, 다시 읽어도 결코 행이 중복되지 않는다. - 진정 사본 대 원본 기록(True copy vs original record) — MHRA 용어. OSS 계층은 진정 사본/파생 데이터를 보유하고, PI는 원본을 보유한다 [5].
- CSA(Computer Software Assurance) — OSS 분석 계층에 더 가벼운 엄격성을 적용할 수 있게 하는 FDA의 위험 기반, 최소 부담 보증 접근법 [3].
- cGMP — current Good Manufacturing Practice. 통제되고 문서화되며 재현 가능한 의약품 제조에 대한 구속력 있는 기대.
다음 이야기
히스토리안은 연동하기에 가장 친근한 상용 시스템이었다. 그것은 개방형 프로토콜을 사용하고 우리가 이미 이해하는 시계열을 다루기 때문이다. 다음 장 DCS, MES & ERP 연동: DeltaV, Siemens, SAP는 더 험한 영역으로 걸어 들어간다 — OPC UA를 통한 제어 시스템, 신뢰할 만한 오픈소스 GxP MES가 없다는 단호한 평결, 그리고 B2MML/ISA-95 메시지를 통한 자재, 로트(lot), 작업 지시(work order)의 ERP 교환 — 여기서는 정직한 하이브리드 경계가 선호가 아니라 필요에 의해 그어진다.