# Logic

> Logic 페이지, 주소 공간 열, 폴더, 명령 모음, 모든 패널 뒤에 있는 로직 주기와 쓰기 깔때기, 그리고 이 페이지가 무엇을 그릴지 정하는 세 권한.

Logic은 탐색 막대의 세 번째 항목입니다. **Logic 보기**를 가진 역할이면 누구에게나 열리며, 머리글은 "주소 공간 위에 변수(계산되거나 쓸 수 있는 값)와 액션(그 값을 쓰는 스크립트)을 정의합니다."라고 읽힙니다. 이 페이지는 마스터 상세 페이지입니다([페이지가 동작하는 방식](app-conventions)). 왼쪽에는 **주소 공간**이라는 제목의 열이, 오른쪽에는 명령 모음과 상세 패널이 있습니다. 여기에서 편집하는 것은 모두 입력하는 대로 자동으로 저장됩니다. 페이지 어디에도 저장 단추는 없습니다.

## 이 영역에서 {#in-this-area}

| 페이지 | 다루는 내용 |
| --- | --- |
| [주소 공간](logic-address-space) | 예약된 일곱 뿌리, 주소를 적고 다듬는 방식, 거르기 상자, 그리고 주소를 넣는 세 가지 방법. |
| [변수](logic-variables) | 변수 편집기: 신원과 주소, 수식 종류와 내부 값 종류, 값 카드, 값 설정. |
| [수식](logic-expressions) | 수식 언어, 포인트에서 읽을 수 있는 표면, 평가기가 지키는 규칙, 그리고 스크립트 편집기. |
| [액션](logic-actions) | 액션 편집기, 스크립트가 쓸 수 있는 것, 모든 검사 메시지, 그리고 실행과 사용/사용 안 함. |
| [트리거](logic-triggers) | 트리거 편집기와 간격 스케줄러. |
| [경보](logic-alarms) | 경보 편집기, 상태 기계, 알림, 그리고 확인과 모두 확인. |
| [다른 페이지에서 오는 것](logic-from-other-pages) | System, Server, Connector, Process 뿌리와 포인트 패널, 그리고 그것을 편집하는 페이지를 밝히는 알림. |

같은 열의 **Assets** 뿌리는 그 자체로 하나의 묶음입니다. [자산](logic-assets)이 Images, Icons, Colors, Symbols, Connection types를 다룹니다.

## 주소 공간 열 {#the-address-space-column}

이 열은 주소 공간의 뿌리를 두 제목 아래에 나열합니다. **여기에서 정의함**에는 이 페이지가 만들고 편집하는 것이 놓입니다. **Variables**, **Alarms**, **Actions**, **Triggers**, **Assets**입니다. **다른 페이지에서 옴**에는 이 페이지가 보여 주기만 하는 것이 놓입니다. **System**, **Server**, **Connector**, **Process**입니다. 첫 제목 아래의 모든 뿌리는 개수를 함께 답니다(Variables와 Alarms는 자기 정의를, Actions와 Triggers도 자기 정의를, Assets는 다섯 범주의 합을 셉니다). 그리고 Alarms 뿌리와 모든 경보 폴더와 모든 경보 행은 자기가 담고 있는 것 가운데 발생 중이거나 확인을 기다리는 가장 높은 우선순위의 색 점을 답니다. 그 경보에 답하는 순간 점은 사라집니다.

트리는 게으릅니다. 가지는 펼칠 때 읽힙니다. 트리에는 실시간 값을 결코 그리지 않습니다. 선택한 마디의 상세 패널이 그 값을 보여 주며 1초에 두 번 새로 고쳐집니다.

| 조작 | 하는 일 |
| --- | --- |
| 거르기… | 이름에 입력한 글자가 들어 있는 행만 남도록 트리를 좁힙니다. 대문자와 소문자는 구별하지 않습니다. 아래의 무엇인가가 일치하는 폴더는 남아서 일치하는 것까지 열리고, Assets 뿌리는 이름이 일치하는 범주로 좁혀지거나 자기 이름만 일치할 때 통째로 남습니다. 자기 이름이 일치하는 주소 공간 뿌리는 목록에 남고 펼칠 때 자기 가지를 읽으며, Actions와 Triggers 구역은 일치하는 행만 나열합니다. |
| 새로 만들기…(열 바닥글) | 만들기 메뉴를 엽니다. **새 변수**, **새 액션**, **새 트리거**, **새 경보**, 그다음 구역마다 놓일 자리가 하나씩 있는 **새 폴더**(Variables, Alarms, Actions, Triggers)입니다. 여기에서 만든 것은 모두 자기 구역의 뿌리에 `Variable1`, `Action1`, `Trigger1`, `Alarm1`, `Folder1` 계열 가운데 비어 있는 첫 이름으로 놓입니다. 새 정의는 열리지 않습니다([만들기와 복사](#creating-and-copying) 참고). 새 폴더는 트리의 그 행에서 이름 칸을 엽니다. **Logic 구성**을 가진 역할에게만 그려지고, 스테이션이 잠겨 있는 동안에는 이유와 함께 회색이 됩니다. |
| 모두 펼치기 / 모두 접기 | 모든 가지를 열거나(단계마다 열면서 읽습니다) 모두 뿌리까지 닫습니다. |
| 오른쪽 단추 | 구역 뿌리나 사용자가 만든 폴더나 정의 행이나 Images, Icons, Colors, Symbols 행에서 그 행을 선택하고 아래의 메뉴를 엽니다. 다른 페이지에서 온 마디에서는 아무것도 열리지 않습니다. |

오른쪽 단추 메뉴는 행과 역할에 따라 이런 것을 담습니다. **새 변수 / 새 액션 / 새 트리거 / 새 경보**(누른 폴더나 뿌리 안으로), **새 폴더**(이미 세 단계 깊이인 폴더에서는 이유를 달고 회색이 됩니다), **실행**(액션 행), **확인**(경보 행), **모두 확인**(Alarms 뿌리), **사용** 또는 **사용 안 함**(액션, 트리거, 경보), **이동 위치**(구역 뿌리와 그 행이 들어갈 수 있는 모든 폴더가 있는 하위 메뉴), **복사**, 명령 모음과 같은 이름의 삭제(**변수 삭제** 등), 그리고 폴더에서는 **폴더 이름 바꾸기**와 **폴더 제거**입니다. Images, Icons, Colors, Symbols 행에서는 그 명령 모음, 곧 **이미지 가져오기…**, **새 사용자 아이콘**, **새 색**, **새 사용자 심볼**, **심볼 가져오기…**, **대화 지시문 복사**를 담습니다. Logic 구성이 없는 역할에게는 Logic 조작을 가졌을 때의 실행, 확인, 모두 확인과 Symbols 행의 대화 지시문 복사만 나오며, 그 어느 것도 없는 행에서는 메뉴가 열리지 않습니다.

무엇인가를 선택하기 전까지 상세 영역은 비어 있습니다. "마디를 선택하면 내용을 볼 수 있습니다. 변수, 액션, 트리거, 경보는 각자의 편집기를 엽니다. 새로 만들기로 하나를 만드십시오."

## 명령 모음 {#the-command-bar}

이 모음은 선택한 마디의 동사를 그립니다. 역할이 결코 쓸 수 없는 것은 그려지지 않고, 지금 상황이 거부하는 것은 그려진 채로 회색이 되며 도구 설명에 이유가 담깁니다. 엔지니어링 조작이 진행 중이면 "유닛이 실행 중인 동안에는 구성이 잠깁니다.", 스테이션이 읽기 전용으로 도는 동안에는 "런타임 정지"입니다.

| 선택 | 앞쪽 무리 | 뒤쪽(위험) 무리 |
| --- | --- | --- |
| 사용자가 만든 폴더 | 새 변수 / 액션 / 트리거 / 경보(그 구역이 담는 갈래), 새 폴더(깊이 한도에서는 "이 폴더는 이미 폴더가 겹칠 수 있는 깊이에 있습니다."로 회색), 폴더 이름 바꾸기 | 폴더 제거 |
| 변수 | 복사 | 변수 삭제 |
| 액션 | 실행, 사용 또는 사용 안 함, 복사 | 액션 삭제 |
| 트리거 | 사용 또는 사용 안 함, 복사 | 트리거 삭제 |
| 경보 | 확인, 사용 또는 사용 안 함, 복사 | 경보 삭제 |
| Alarms 뿌리 | 모두 확인 | |
| Assets, Images | 이미지 가져오기… | |
| Assets, Icons | 새 사용자 아이콘 | |
| Assets, Colors | 새 색 | |
| Assets, Symbols | 새 사용자 심볼, 심볼 가져오기…, 대화 지시문 복사 | |
| System, Server, Connector, Process 마디 | [다른 곳에서 편집한다는 알림](logic-from-other-pages#the-edited-elsewhere-notice)과 그 열기 단추 | |

**복사**는 선택한 정의를 그 구역의 뿌리로 복제합니다. 원본의 이름이 비어 있으면 그 이름으로, 그렇지 않으면 `이름 (2)`, `이름 (3)` 하는 식으로 놓고 복사본은 열지 않고 그 뿌리의 표에서 강조 표시합니다([만들기와 복사](#creating-and-copying) 참고). 복사한 경보는 정상에서 시작하고, 복사한 트리거는 일정 없이 시작하며, 복사한 액션에는 실행 기록이 없습니다. **사용**과 **사용 안 함**은 다른 칸과 같은 자동 저장으로 정의의 사용 표시를 뒤집습니다. 모든 **삭제**는 먼저 묻고("'X'을(를) 삭제하시겠습니까? … 이 작업은 되돌릴 수 없습니다.") 작업 기록 줄에 "삭제했습니다."라고 알립니다. 변수나 경보를 삭제하면 그 주소를 부르던 모든 수식과 스크립트와 조건과 대시보드 바인딩이 풀리지 않은 상태로 남으며, 그것은 [검증](validation)이 나열합니다. 삭제한 뒤에는 삭제한 것의 부모로 갑니다. 화면은 정의가 들어 있던 폴더나 그 구역의 뿌리로 가고, 그 행은 트리에서 선택되어 펼쳐지며 남은 것을 보여 주는 표가 보입니다. **폴더 제거**도 같은 방식으로 한 단계 위의 폴더나 구역의 뿌리로 갑니다.

## 만들기와 복사 {#creating-and-copying}

만들기는 만든 것을 열지 않으며, 복사도 만들기입니다. 열의 **새로 만들기…**에서든, 구역 뿌리나 폴더의 오른쪽 단추 메뉴에서든, 열려 있는 폴더의 명령 모음에서든 **새 변수**, **새 액션**, **새 트리거**, **새 경보**는 그 계열의 비어 있는 첫 이름으로 행을 만들고 화면을 그 부모의 페이지로 가져갑니다. 부모는 그 행을 넣은 폴더, 또는 그 구역의 뿌리입니다. 트리는 그 부모를 선택해 펼치고, 페이지의 표는 새 행을 강조 표시해 보이는 곳까지 스크롤하며, 작업 기록 줄에는 "'Variable1'을(를) 만들었습니다. 편집하려면 여십시오."가 나옵니다. 폴더 자신의 명령 모음에서 만들면 화면은 그 폴더에 그대로 있습니다. **복사**는 그 구역의 뿌리에서 같은 일을 하고, 작업 기록 줄에는 "'Setpoint (2)'(으)로 복사했습니다. 편집하려면 복사본을 여십시오."가 나옵니다. **거르기…** 상자에 입력한 거르기는 도착할 때 지워집니다. 부모와 새 행이 트리 안에 있어야 선택되고 펼쳐진 모습으로 보일 수 있기 때문입니다.

구역 뿌리나 사용자가 만든 폴더의 페이지는 그것이 가진 것의 표이며, **이름**, **주소**, **값**이 있고 각 행의 끝에는 **열기**가 있어 트리의 그 행과 똑같이 그 정의를 엽니다(Alarms 뿌리에서는 **Logic 조작**을 가진 역할에게 그 자리에 **확인**도 보입니다). 출력 유형이 아이콘, 이미지 또는 색인 변수는 값 셀에 그 아이콘, 이미지 또는 색 견본을 행에 맞는 작은 크기로 그립니다(색은 16진수 값도 함께 보여 줍니다). 셀은 아이콘의 소스를 절대 적지 않습니다. 행을 누르면 그 행이 선택되고, 선택된 행이 강조 표시된 행입니다. 강조 표시는 다른 행을 고르거나 열을 다른 곳으로 옮길 때까지 남습니다. 새 폴더는 예외이며, 트리의 그 행에서 이름 칸을 엽니다.

## 폴더 {#folders}

네 구역은 저마다 폴더로 정리할 수 있습니다. 폴더는 한 구역에 속하고 그 구역의 항목만 담으며, 많아야 세 단계까지 겹칩니다. 폴더는 정리를 위한 것일 뿐입니다. 권한도 없고 평가도 없고 상태도 없습니다.

**Variables**와 **Alarms**에서는 폴더가 이어지며 주소를 이룹니다. `Forno`에 있는 변수는 `Variables.Forno.Setpoint`로 읽히고, 그 `Zona1` 하위 폴더에 있는 변수는 `Variables.Forno.Zona1.Setpoint`로 읽힙니다. 한 구역의 한 단계는 그 폴더들과 정의들이 함께 쓰는 하나의 마디 이름 공간입니다. 두 폴더가 저마다 `Setpoint`를 담을 수는 있지만, 같은 단계에 놓인 것끼리 같은 마디로 다듬어져서는 안 됩니다. 편집기는 입력하는 대로 그런 이름을 거부하며 이미 쓰이고 있는 주소를 밝힙니다. **Actions**와 **Triggers**는 신원으로 참조되므로, 그 폴더는 트리를 정리하기만 하고 그 패널은 주소 대신 위치 줄을 보여 줍니다.

| 명령 | 일어나는 일 |
| --- | --- |
| 새 폴더 | `FolderN`이라는 이름의 빈 폴더를 만들고 트리 행에서 이름 칸을 엽니다. 칸을 비우거나 그대로 두고 벗어나면 그 이름이 남습니다. |
| 폴더 이름 바꾸기 | 행에서 이름 칸을 엽니다. 그 폴더 아래의 모든 주소가 함께 옮겨지고 모든 참조가 고쳐 쓰이며, 작업 기록 줄이 몇 곳인지 말합니다("폴더 이름을 바꿨고 참조 3곳을 갱신했습니다."). |
| 이동 위치 | 폴더나 정의를 같은 구역의 다른 폴더 아래로, 또는 구역 뿌리로 되돌려 놓습니다. 주소와 참조가 따라옵니다. 목록은 갈 수 있는 곳만 내놓습니다. 폴더 자신, 자기 하위 폴더, 다른 구역, 그리고 자기 하위 폴더가 깊이 한도를 넘게 될 단계는 결코 내놓지 않습니다. |
| 폴더 제거 | 무엇이 옮겨지는지 말하며 먼저 묻습니다. "그 안의 항목 3개가 Variables(으)로 옮겨지고 삭제되는 것은 없습니다. 옮겨지는 주소에 대한 참조는 갱신됩니다." 항목과 하위 폴더는 한 단계 위로 다시 놓입니다. 그 가운데 둘이 옮겨 갈 자리에서 부딪히게 되면 제거는 거부됩니다. |

## 로직 주기와 대기열 {#the-sweep-and-the-queue}

런타임은 차선 두 개 위에서 돌고, 둘 다 설비를 기다리는 일이 결코 없습니다. **주기**는 하나의 순차 대기열에서 100 ms마다 돕니다. 먼저 모든 수식 변수를 평가하고, 그다음 켜진 모든 경보 조건을 그 순서대로 평가하므로, 조건은 이번 주기의 변수 값을 읽습니다. 다른 데서 들어오는 내부 값 쓰기와 태그 쓰기, 경보 확인도 이 주기가 함께 나릅니다. **액션 차선**은 액션 스크립트를 한 번에 하나씩, 부탁받은 순서대로 돌립니다. 역시 100 ms마다 도는 별도의 검사가 때가 된 [트리거](logic-triggers)를 액션 차선에 올립니다.

두 차선이 서로 독립이므로 스크립트 도중에 주기가 한 번 지나갈 수 있고, 그래서 한 스크립트 안의 두 읽기가 서로 다른 회차를 볼 수 있습니다. 그 대신, 장치를 기다리느라 멈춘 스크립트는 자기 뒤의 액션만 붙들 뿐 수식도 경보도 운전자도 붙들지 않습니다. 쓰기가 그 자리를 두고 다투지도 않습니다. 순서는 전선이 있는 곳에서, 장치마다 하나씩인 대기열로 지켜집니다(아래를 보십시오). 소비하는 쪽(대시보드, 채널, 이 페이지)은 공개된 상태를 읽습니다. 이 페이지의 어떤 것도 손으로 평가를 일으키지 않습니다.

## 값 쓰기 {#writing-values}

무엇이 시작했든 모든 쓰기는 하나의 깔때기를 지나갑니다. 스크립트의 대입이나 `Write(...)`, 내부 값 변수의 **설정할 값** 칸, 대시보드의 조작, Process 레시피, 에이전트, 공개 노드에 쓰는 외부 OPC UA 클라이언트, [Modbus 서버](connector-modbus-server) 맵에서 쓰기를 허용한 행에 쓰는 Modbus 클라이언트가 모두 그렇습니다. 이 깔때기는 유한하지 않은 값이나 대상의 형식으로 바꿀 수 없는 값을 거부하고, 도는 레시피나 인터록이 잡고 있는 신호원을 거부하며(잡고 있는 쪽을 밝힙니다), 쓰기를 옛 값에서 새 값으로 그 출처(운전자, MCP, 실행) 아래에 기록하고, 그대로 적용합니다. 이 깔때기가 판단하는 것은 무엇에게도 묻지 않고 판단합니다. 값, 대상, 잠금, 그리고 장치가 연결되어 있기는 한지가 그것입니다. 깔때기가 받아들인 태그 쓰기는 그다음 Connector 안에 있는 그 장치 자신의 전달 대기열로 넘어갑니다. 그 장치에 보낼 값들은 거기서 도착한 순서대로 하나씩 나가고, 서로 다른 장치는 나란히 처리됩니다. 같은 태그에 더 새로운 쓰기가 앞질러 간 값은 그 대기열을 아예 떠나지 않으며, 설비가 듣는 것은 더 새로운 값입니다. 답을 기다리는 쪽은 부탁한 쪽이고, 로직 바깥 자기 코드에서 기다립니다. 대시보드 구성 요소, [태그 페이지](connector-tags#the-live-value-card)의 손 쓰기, 에이전트 도구, 외부 OPC UA 클라이언트, Modbus 클라이언트, 도는 레시피가 그렇고, 스크립트는 `WriteAndWait`라고 적은 자리에서만 그렇습니다. 출처가 액션인 쓰기만은 예외입니다. 그것은 Events 콘솔이 아니라 [상세 수집](events-console#detailed-capture)에만 들어갑니다. 주기마다 쓰는 스크립트는 값을 수천 개씩 만들어 내어 스테이션의 소식을 그 아래에 묻어 버리기 때문입니다. 콘솔이 액션에 대해 담는 것은 그 실패입니다. 태그 쓰기는 공학값을 받아 태그의 [변환 경로](connector-value-pipeline)를 거꾸로 적용해 장치가 받는 원시값으로 만듭니다. 자세한 내용은 [변수](logic-variables#set-value)와 [액션](logic-actions#what-an-action-may-write)에 있습니다.

## 권한과 잠금 {#permissions-and-locks}

| 권한 | 여기에서 허락하는 것 |
| --- | --- |
| Logic 보기 | 페이지를 열고 실시간 값을 포함해 그 위의 모든 것을 읽는 일. |
| Logic 구성 | 변수와 액션과 트리거와 경보와 폴더를 만들고 편집하고 이름을 바꾸고 옮기고 복사하고 사용하고 사용 안 함으로 두고 삭제하는 일, 그리고 자산 라이브러리를 가꾸는 일. |
| Logic 조작 | 여기에서, 대시보드에서, Events 페이지에서 내부 값을 쓰고 액션을 실행하고 경보를 확인하는 일. |

Logic 보기만 가진 역할은 페이지 전체를 읽기만 합니다. 편집기는 안내 아래에서 작동하지 않는 상태로 남고("현재 역할은 Logic을 볼 수는 있지만 구성할 수는 없습니다(변수, 액션, 트리거, 경보, 자산)."), 구성이나 조작 동사는 하나도 그려지지 않습니다. 조작은 가졌지만 구성은 가지지 않은 역할에게는 실행과 확인과 모두 확인과 값 설정이 살아 있습니다. Process 유닛이 스테이션을 잡고 있는 동안 페이지는 엔지니어링 잠금 알림을 보여 주고 모든 구성 동사와 편집기 칸이 회색이 됩니다. 실행과 확인과 값 설정은 계속 쓸 수 있습니다. 런타임이 정지된 동안에는 구성도 조작도 "런타임 정지"로 거부됩니다. 트리와 패널은 계속 읽을 수 있지만 실시간 데이터는 담지 않습니다. 권한의 목록은 [권한](users-permissions)에 있습니다.

## 이 페이지가 하지 않는 일 {#what-the-page-does-not-do}

저장도 실행 취소도 없습니다. 자판을 한 번 누르면 그것이 곧 저장된 변경이고(작업 기록 줄이 "저장했습니다."라고 말합니다), 거부된 저장은 스테이션이 가진 값으로 칸을 되돌립니다. 에이전트가 자기 도구로 만들거나 바꾸거나 삭제한 정의와 다른 창이 바꾼 정의는 열려 있는 열에 스스로 나타납니다. 그렇게 삭제된 정의를 열어 둔 편집기는 닫히고, 작업 기록 줄이 그 이름과 편집기 밖에서 삭제되었다는 사실을 알립니다. 경보 이력과 Events 콘솔과 대시보드는 자기 페이지에 있습니다.
