# 유닛의 주소 공간

> 유닛이 Process.Model.Unit 아래에 공개하는 모든 포인트와 그 형식과 뜻, 어느 포인트가 쓸 수 있는 명령인지, 그리고 Logic 스크립트가 거기에서 무엇을 읽을 수 있는지입니다.

유닛은 자기 실행 데이터를 `Process.<Model>.<Unit>` 아래의 평범한 [Logic](logic) 주소로 공개합니다. 그래서 대시보드와 Logic 수식과 내장 OPC UA 서버와 에이전트가 별도의 배관 없이 거기에 닿습니다. 이 갈래는 Logic 페이지의 "다른 페이지에서 옴"([다른 페이지에서](logic-from-other-pages)) 아래에서, 그리고 모든 주소 고르개에서 살펴볼 수 있습니다. 모델이나 유닛이나 채널이나 메타데이터 항목이나 판정이나 판정 기준의 이름을 바꾸면 해당하는 주소가 바뀌고 살아 있는 글 참조가 다시 쓰입니다. 기록된 파일은 쓰일 때의 이름을 얼린 채로 지닙니다. 마디는 정리된 이름입니다. "Climatic chamber" 모델의 "유닛 1"이라는 유닛은 `Process.Climatic_chamber.유닛_1`로 주소가 붙습니다.

| 갈래 | 무엇을 공개하는가 | 쓸 수 있는가 |
| --- | --- | --- |
| `Channels.<Channel>` | 채널마다 이어 둔 실시간 값이며, 채널이 선언한 형식으로 나옵니다. | 쓸 수 있는 채널(쓰기 전용이나 읽기와 쓰기 역할)은 쓰기 통로를 거쳐 쓸 수 있는 포인트입니다. 실행이 차지한 신호원은 다른 모든 쓰는 쪽을 거부합니다. |
| `Procedure.<point>` | 실행 상태이며 포인트마다 스칼라 하나입니다(아래 표). | 아니요. |
| `Commands.<command>` | `Start`, `Hold`, `Resume`, `Stop`, `Abort`, `Comment`입니다. | 예. 쓰면 명령이 나갑니다(아래 표). |
| `Next.<point>` | 다음 시작이 소비하는 준비 영역입니다. | 손으로 넣는 메타데이터 항목만 쓸 수 있습니다. |
| `LastRun.<point>` | 유닛이 마지막으로 끝낸 실행의 기록입니다([LastRun](#lastrun)). | 아니요. |
| `Productivity.Today.<branch>`와 `Productivity.Rolling.<branch>` | 기간마다의 유닛 생산성 집계입니다. | 아니요. |

## 채널 {#channels}

채널 포인트는 유닛의 바인딩 뒤에 있는 값을 읽어 채널의 데이터 형식으로 비춰 주며, 채널이 이어져 있지 않거나 신호원을 쓸 수 없으면 결측으로 읽힙니다. Logic 스크립트에서 그 포인트는 이어 둔 태그나 변수를 읽기 전용으로 비춰 준 것이며 태그 자체가 결코 아닙니다. `Value`, `ValueObject`, `ValueRaw`, `ValueScaled`, `ValueCalibrated`, `ValueLimited`, `ValueRounded`, 변환 `ValueToBool()`, `ValueToInteger()`, `ValueToReal()`, `ValueToString()`, `ValueToDateTime()`, 품질 `State()`, 시각 `SourceTimeStamp()`와 `ApplicationTimeStamp()`, `Refresh()`, `Name`, `EngineeringUnit`입니다. 값 변환 경로의 구성원은 태그 바인딩에 대해 답합니다. 변수 바인딩은 값과 애플리케이션 시각을 답합니다.

## Procedure {#procedure}

모든 포인트는 살아 있는 실행에서 계산되며 좋은 품질로 읽힙니다. 말할 것이 없는 포인트는 결측으로 읽힙니다.

| 포인트 | 형식 | 뜻 |
| --- | --- | --- |
| `Status` | 문자 | 유닛을 잡아 두었지만 아직 실행이 없으면 `Preparing`, 아무것도 차지하고 있지 않으면 `Idle`, 그 밖에는 실행 상태입니다. `Running`, `Held`, `Saving`, `Completed`, `Aborted`, `Failed`입니다. |
| `Running` | 부울 | 엄격하게 실행 중 상태입니다. 준비나 일시 정지됨이나 저장 중이나 마무리에서는 결코 참이 아닙니다. |
| `Busy` | 부울 | 차지하고 있는 구간 전체입니다. 잡아 둠, 실행 중, 일시 정지됨, 저장 중, 그리고 실행 파일을 닫는 마지막까지입니다. |
| `Verdict` | 문자 | `Ok`, `Nok`, `Indeterminate`, `None`입니다. 화면이나 인쇄된 라벨이 어떤 말로 보여 주든 값은 대소문자까지 이 표기 그대로이므로, 비교는 `Process.<Model>.<Unit>.Procedure.Verdict == "Nok"`처럼 씁니다. 판정한 증거는 실행이 끝난 뒤에도 다음 실행이 시작될 때까지 읽을 수 있게 남습니다. |
| `Mode` | 문자 | 진행 중인 실행의 방식이며 `Instant`, `Temporal`, `Controlled`입니다. 단일 명령(스냅숏, 즉시 판정)도 여기에 알립니다. 대기 중에는 결측입니다. |
| `ActiveProcedure` | 문자 | 진행 중인 실행의 이름("절차 · 유닛")입니다. 대기 중에는 결측입니다. |
| `SegmentIndex` | 정수 | 시간 프로파일의 지금 구간이며 0부터 셉니다. 프로파일이 없으면 결측입니다. |
| `CycleIndex` | 정수 | 지금 사이클이며 0부터 셉니다. 대기 중에는 결측입니다. |
| `CycleCount` | 정수 | 실행의 전체 사이클 수입니다(한 번만 도는 실행이면 1). 대기 중에는 결측입니다. |
| `Cycle` | 문자 | 사이클을 도는 실행이면 "2 / 10"입니다. 사이클을 돌지 않는 실행에서는 결측이므로, 이어 둔 읽기 표시가 한 번만 도는 실행인 것처럼 오해를 부르는 대신 결측 표시를 보여 줍니다. |
| `FailedCycles` | 정수 | 지금까지 불합격으로 판정된 사이클입니다. 사이클을 돌지 않는 실행에서는 결측입니다. |
| `SamplesEvaluated`, `SamplesOut`, `SamplesUnavailable`, `SamplesInvalid` | 정수 | 판정의 증거 개수이며 판정 엔진이 한 번에 갱신합니다. 판정한 증거가 없으면 결측입니다. |
| `Elapsed` | 실수 | 실행이 시작된 뒤 지난 초입니다. 대기 중에는 결측입니다. |
| `StartedAt` | 날짜와 시각 | 진행 중인 실행이 시작된 때입니다. 대기 중에는 결측입니다. |
| `Metadata.<Field>` | 문자 | 모델의 메타데이터 항목마다 포인트 하나이며, 진행 중인 실행이 시작할 때 얼린 값입니다. 대기 중에는, 그리고 그 실행이 묻지 않는 항목에서는 결측입니다. 비워 둔 항목은 빈 문자로 읽힙니다. 시작할 때 호출되는 액션이 시작하는 실행에서 읽는 것이 이것입니다. `Next.<Field>`는 이미 그다음 실행을 보여 주기 때문입니다. |

## Commands {#commands}

명령 포인트를 읽으면 "지금 이것을 실행할 수 있는가"에 답하므로, 이어 둔 단추가 스스로를 잠급니다. 쓰면 실행 콘솔을 거쳐 그 명령이 나가고, 쓴 화면을 신호원으로 삼아 기록에 남으며, 누가 눌렀는지의 신원과 함께 기록됩니다. 명령은 서비스 호출이지 대기열에 넣는 포인트 쓰기가 결코 아닙니다.

| 포인트 | 언제 참으로 읽히는가 | 쓰면 |
| --- | --- | --- |
| `Start` | 유닛이 바쁘지 않고, 런타임이 조작을 받고, 인터록이 정상이며, 절차가 준비되어 있을 때입니다. | 준비한 메타데이터로 준비한 절차를 시작합니다. |
| `Hold` | 실행이 실행 중이고 그 절차가 시간형일 때입니다. | 시간 구간을 멈춰 둡니다. |
| `Resume` | 실행이 일시 정지되어 있고 인터록이 정상일 때입니다. | 일시 정지를 풉니다. |
| `Stop` | 실행이 실행 중일 때입니다. | 실행을 완료로 끝냅니다. |
| `Abort` | 실행이 실행 중이거나 일시 정지되어 있을 때입니다. | 실행을 중단됨으로 끝냅니다. |
| `Comment` | 결코 참이 아닙니다. 이 포인트에는 읽는 값이 없습니다. | 쓴 글을 진행 중인 실행에 코멘트로 덧붙이고, 유닛이 대기 중이면 그 유닛에서 가장 최근에 끝난 실행에 실행 뒤 메모로 덧붙입니다. 실행이 하나도 없는 유닛은 거부하고("이 유닛에는 코멘트를 남길 실행이 없습니다."), 빈 글도 거부합니다. |

스테이션이 쓰기를 거부하는 동안에는(런타임 정지) 모든 명령이 거짓으로 읽힙니다.

## Next {#next}

| 포인트 | 형식 | 뜻 |
| --- | --- | --- |
| `Next.Procedure` | 문자 | 준비한 절차의 이름입니다. 여기에서는 읽기 전용입니다. 준비는 유닛 패널의 실행 카드에서 합니다. |
| `Next.<Field>` | 문자 | 준비한 절차가 묻는 메타데이터 항목마다 포인트 하나입니다. 유닛에 다른 절차를 준비하면 갈래의 모양이 바뀌고, 다른 절차의 항목은 결측으로 읽힙니다. 손으로 넣는 항목(문자나 숫자)은 쓸 수 있는 준비 포인트이며, 거기에 이어 둔 입력 구성 요소가 쓰는 것이 바로 그것입니다. 일련번호 항목은 카운터가 지금 조립할 식별자를 읽기 전용으로 예측한 것이며, 읽는다고 해서 결코 잡히지 않습니다. |

준비는 스테이션 전체의 것이고 메모리에 있으며 잠깐만 삽니다. 애플리케이션을 시작하면 풀리고, 시작이 비우는 것이 아니라 소비합니다.

## Productivity {#productivity}

기간 둘, `Today`(스테이션 기준 자정부터)와 `Rolling`(모델이나 유닛에 선언한 구간)이 있고, 저마다 갈래 셋을 가집니다([생산성](process-productivity)).

| 갈래 | 포인트 | 형식 |
| --- | --- | --- |
| `Summary` | `ProductivityPercent`, `YieldPercent`, `TypicalElapsedSeconds` | 실수이며 분모가 생기기 전에는 결측입니다. |
| `Summary` | `Finalized`, `OK`, `NOK`, `Indeterminate`, `Unclassified`, `Aborted`, `Failed` | 정수 개수입니다. |
| `Outputs.<key>` | `Quantity`, `RatePerHour` | 실수이며 이름 붙은 수량마다 키 하나, 모델이 수량을 선언하지 않았으면 생산을 세는 절차마다 키 하나입니다. |
| `Procedures.<key>` | `Quantity`, `RatePerHour`와 위의 요약 포인트 | 위와 같으며 생산을 세는 절차마다입니다. |

키는 표시 이름이 아니라 변하지 않는 id와 얼어붙은 생산량 단위에서 나오므로, 이름을 바꿔도 수식이 결코 어긋나지 않습니다. 모든 포인트는 읽기 전용이며, 집계는 실행 파일이 아니라 실행 색인에서 읽습니다.

## LastRun {#lastrun}

유닛이 마지막으로 끝낸 실행의 기록입니다. 어느 실행이었는지, 어떻게 끝났는지, 작업자가 시작할 때 무엇을 넣었는지, 판정 기준이 저마다 어떻게 나왔는지를 지닙니다. 완료할 때 호출되는 Logic 액션이 읽는 것이 이것이며([액션](process-actions#logic-action-commands)), 다른 소비자도 똑같이 읽습니다. 마지막 제품을 보여 주는 화면, 경보, 스테이션의 서버입니다. 유닛의 기록된 실행은 모두 셉니다. 실패한 실행도, 스냅숏과 즉시 판정도 들어갑니다. 가져온 실행은 결코 세지 않습니다.

| 포인트 | 형 | 뜻 |
| --- | --- | --- |
| `RunId` | 문자 | 실행의 식별자입니다. |
| `Procedure` | 문자 | 실행이 기록한 절차의 이름입니다. |
| `Status` | 문자 | `Completed`, `Aborted`, `Failed` 가운데 하나이며, 철자 그대로입니다. |
| `Verdict` | 문자 | `Ok`, `Nok`, `Indeterminate`, `None` 가운데 하나이며, `Procedure.Verdict`와 같은 철자입니다. 실패한 실행은 `None`으로 읽힙니다. |
| `StartedAt`, `FinishedAt` | 날짜와 시각 | 실행이 시작된 때와 끝난 때입니다. |
| `Elapsed` | 실수 | 시작부터 끝까지의 초입니다. |
| `CycleCount` | 정수 | 실행의 사이클 수입니다(한 번 통과면 1). |
| `FailedCycles` | 정수 | 불합격으로 판정된 사이클입니다. |
| `Metadata.<Field>` | 문자 | 모델의 메타데이터 항목마다 포인트 하나이며, 실행이 시작할 때 얼린 값입니다. 실행이 묻지 않은 항목은 결측입니다. 비워 둔 항목은 빈 문자로 읽힙니다. |
| `Evaluations.<Evaluation>.<Criterion>.<point>` | 아래 표와 같습니다 | 모델의 판정마다 폴더 하나, 그 아래 판정 기준마다 폴더 하나가 있으며, 판정 기준의 이름으로, 이름이 없으면 그것이 보는 채널의 이름으로 불립니다. |

판정 기준은 저마다 판정받은 모든 사이클을 접은 결과 하나를 지닙니다. 그래서 한 번 통과든 사이클 100개짜리 실행이든 주소가 같습니다.

| 포인트 | 형 | 뜻 |
| --- | --- | --- |
| `Outcome` | 문자 | `Ok`, `Nok`, `Indeterminate` 가운데 하나이며, 철자 그대로입니다. 불합격인 사이클이 하나라도 있으면 `Nok`, 그렇지 않고 판정 불가인 사이클이 하나라도 있으면 `Indeterminate`, 둘 다 없으면 `Ok`입니다. |
| `Passed` | 부울 | `Outcome`이 `Ok`일 때만 참입니다. |
| `Value` | 실수 | 보는 채널의 측정값입니다. 구간에서 마지막으로 평가된 표본이며, 한 지점 방식에서는 판정된 표본입니다. 값을 잰 가장 최근 사이클의 것입니다. |
| `MinValue`, `MaxValue` | 실수 | 모든 사이클에 걸쳐 평가된 가장 작은 값과 가장 큰 값입니다. |
| `Limits` | 문자 | 기록된 그대로의 한계이며, 예를 들어 `5 .. 45`입니다. |
| `WorstExcursion` | 실수 | 모든 사이클에 걸쳐 한계를 넘어선 가장 큰 거리입니다. |
| `FailedCycles` | 정수 | 이 판정 기준을 불합격으로 판정한 사이클입니다. |

이 갈래의 모양은 모델에서 오며, 마지막 실행의 모양에서 오는 일은 없습니다. 카탈로그의 메타데이터 항목 모두와 모든 판정의 모든 판정 기준이 포인트가 되므로, 그중 하나를 가리키는 스크립트는 어떤 실행 전에도, 다른 판정으로 판정하는 절차를 실행한 뒤에도 검증을 통과합니다.

| 상황 | 포인트가 읽는 것 |
| --- | --- |
| 유닛의 실행이 아직 하나도 끝나지 않음 | 모든 포인트가 품질 나쁨의 결측입니다. |
| 실행이 끝남 | 새 기록이며, 유닛의 `Procedure.Status`가 실행이 끝났다고 말하기 전에 이미 들어와 있습니다. |
| 유닛의 다른 실행이 진행 중 | 그 실행이 끝날 때까지 이전 기록 그대로입니다. |
| 애플리케이션이 다시 시작됨 | 유닛이 마지막으로 끝낸 실행을, 시작하고 조금 뒤에 그 실행 파일에서 다시 읽은 것입니다. 읽기 전까지는 결측입니다. |
| 마지막 실행이 판정하지 않은 판정 기준(다른 판정의 것이거나 나중에 더한 것) | 모든 포인트가 결측입니다. |
| 이름이 같게 읽히는 판정 둘, 또는 판정 기준 둘 | 아무것도 없습니다. 주소는 어느 쪽으로도 풀리지 않으며, 판정 페이지가 그렇다고 알립니다([판정](process-evaluations#names-are-addresses)). |

메타데이터 항목, 판정, 판정 기준, 또는 이름 없는 판정 기준이 보는 채널의 이름을 바꾸면, 이 페이지의 다른 이름 바꾸기와 똑같이 이 주소들이 옮겨집니다.

## 스크립트가 할 수 있는 일 {#what-a-script-may-do}

Logic의 변수와 경보와 액션 스크립트는 여기의 모든 것을 **읽을** 수 있습니다. 채널 값, 실행 상태, 명령 준비 상태, 준비한 값, 마지막 실행, 생산성 포인트입니다. 명령을 쏘거나, 준비 항목을 쓰거나, 코멘트를 덧붙일 수는 없습니다. 그런 쓰기는 명령을 소비한다고 분명히 밝힌 쪽의 것입니다. 운전 패널, 대시보드의 단추와 입력, 유닛 자동화, 그리고 에이전트 도구입니다.

채널 포인트는 [채널](#channels)의 형이 붙은 투영으로 읽힙니다. 여기의 다른 포인트는 모두 뒤에 `.Value`를 붙이지 않는 있는 그대로의 값으로 읽힙니다. 변수와 다른 점입니다.

```js
if (Process.Oven_soak.Oven_1.LastRun.Verdict === "Ok") {
  Variables.Last_serial = Process.Oven_soak.Oven_1.LastRun.Metadata.Serial;
}
```
