# BACnet

> BACnet/IP 빌딩 자동화 장치에 접속합니다. 장치 인스턴스, 객체 형식과 인스턴스로 적는 주소, Who-Is 검색, 그리고 presentValue.

**BACnet** 드라이버는 BACnet/IP로 빌딩 자동화 장비와 이야기합니다. 태그는 저마다 BACnet 객체 하나의 **현재 값**을 읽습니다. 아날로그 입력의 실시간 읽기, 바이너리 출력의 상태, 다중 상태 값의 자리 같은 것입니다. [Connector](connector)에서 BACnet 드라이버 아래에 장치를 추가하십시오. 패널은 이 프로토콜이 쓰는 칸만 보여 줍니다.

## 연결 {#connection}

| 칸 | 뜻 | 기본값 |
| --- | --- | --- |
| **호스트** | BACnet 장치(또는 그것을 대신해 답하는 라우터)의 IP 주소나 호스트 이름. 이름은 장치가 접속할 때 IPv4 주소로 풀립니다. 이 컴퓨터가 풀 수 없는 이름이면 장치는 연결되지 않고, 이유가 그렇게 말해 줍니다. | 비어 있음 |
| **포트** | 장치의 UDP 포트이며 1에서 65535까지입니다. 칸이 비어 있으면 BACnet/IP 표준인 47808이 회색으로 보이고 장치에는 그 포트로 닿습니다. 0으로 저장된 장치도 똑같이 보입니다. | 47808 |
| **장치 Id** | 장치의 인스턴스 번호이며, 그 Device 객체의 번호이자 BACnet 네트워크에서 고유한 값입니다. | 0 |

장치 머리글은 조립된 endpoint를 보여 줍니다. 예를 들어 `bacnet://192.168.0.30:47808/1234`입니다. 접속할 때는 장비가 답하는지 확인하려고 장치의 객체 목록 크기를 묻는 요청 하나를 보냅니다. 객체 목록 자체를 훑지는 않습니다. 그 답이 곧 연결입니다. 답하지 않는 장치는 연결된 것처럼 보이는 대신 오프라인으로 남고, 그 이유(UDP 포트를 이미 다른 것이 잡고 있음, 주소가 아닌 주소)는 Events 페이지와 그날의 로그 파일에 적힙니다. 이 드라이버에는 읽기 주기 칸이 없습니다. 그 태그는 1초에 한 번 읽힙니다.

## 주소 지정 {#addressing}

BACnet 태그의 주소는 태그 신호원 카드의 형식 있는 칸 둘로 적습니다. 자유 입력 주소는 없습니다.

| 칸 | 뜻 | 받는 값 | 기본값 |
| --- | --- | --- | --- |
| **객체 형식** | 읽을 BACnet 객체의 갈래. | 아래의 아홉 가지 형식 | `AnalogInput` |
| **인스턴스** | 그 형식 안에서 객체의 인스턴스 번호. | 0 이상 | 0 |

제시되는 객체 형식과 그 표준 BACnet 형식 코드는 이렇습니다.

| 객체 형식 | 코드 | 현재 값이 담는 것 |
| --- | --- | --- |
| `AnalogInput` | 0 | 측정된 숫자 |
| `AnalogOutput` | 1 | 명령된 숫자 |
| `AnalogValue` | 2 | 저장된 숫자 |
| `BinaryInput` | 3 | 비활성/활성 |
| `BinaryOutput` | 4 | 비활성/활성 |
| `BinaryValue` | 5 | 비활성/활성 |
| `MultiStateInput` | 13 | 1부터 시작하는 상태 번호 |
| `MultiStateOutput` | 14 | 1부터 시작하는 상태 번호 |
| `MultiStateValue` | 19 | 1부터 시작하는 상태 번호 |

장치 1234의 `AnalogInput` 5는 "그 장치 아날로그 입력 5의 현재 값"이라는 뜻입니다. 읽을 때마다 객체의 `presentValue` 속성을 묻습니다. 다른 속성에는 주소를 매길 수 없습니다. 신호원 카드의 읽기 전용 **신호원 주소 (버스)** 줄은 편집하는 대로 조립된 `type,instance` 쌍을 보여 줍니다.

## 데이터 형식 {#data-types}

**데이터 형식** 선택 목록은 네 형식을 내놓습니다. 객체에 맞는 것을 고르십시오.

| 데이터 형식 | 어울리는 곳 | 비고 |
| --- | --- | --- |
| Float | 아날로그 객체 | Real 현재 값입니다. double은 Float으로 좁혀집니다 |
| Boolean | 바이너리 객체 | Boolean 현재 값이거나, 바이너리 객체가 답하는 열거값 0과 1입니다 |
| Int32 | 다중 상태와 그 밖의 정수 값 | 부호 있는 답과 부호 없는 답과 열거된 답이 모두 여기로 들어옵니다 |
| String | 문자열 값 | 장치가 보내는 그대로의 글자 |

고른 형식은 객체가 담고 있는 것과 맞아야 합니다. 다른 것으로 답하는 장치는 그 태그의 읽기를 실패시킵니다. 태그는 품질이 나쁜 것이 되고, 이유가 무엇이 도착했는지 밝힙니다("장치가 Integer로 선언된 지점에 Single 값으로 답했습니다."). 변환된 숫자가 추세와 이력과 경보에 들어가는 일은 없습니다. 아날로그 객체를 부울로 읽거나 Real을 Int32로 읽는 것이 바로 그 경우입니다. 장치의 나머지는 계속 읽히고, 형식이 틀린 태그 하나 때문에 다시 연결되는 일도 없습니다.

장치에 없는 객체를 가리키는 태그는 장치 자신의 답과 함께 읽기에 실패합니다. 이유는 그 주소에 장치의 객체가 없다는 것을 알리고, 장치가 보낸 오류(`ERROR_CODE_UNKNOWN_OBJECT`)를 밝힙니다. 그래서 잘못된 주소는 답하지 않게 된 장치와 구별됩니다. 장치는 연결된 채로 남습니다.

## 쓰기 {#writes}

**접근**이 읽기와 쓰기이거나 쓰기 전용인 태그는 쓸 수 있습니다. 쓰기는 태그의 데이터 형식과 상관없이, BACnet 표준이 그 종류의 객체에 정한 형식으로 객체의 `presentValue`를 정합니다.

| 객체 | 쓰는 형식 | 받아들이는 값 |
| --- | --- | --- |
| 바이너리 입력, 출력, 값 | Enumerated | 비활성(0) 또는 활성(1). Boolean 태그나 0 또는 1인 Int32에서 |
| 다중 상태 입력, 출력, 값 | Unsigned | 1부터 시작하는 상태 번호 |
| 아날로그 입력, 출력, 값 | Real | Float 또는 Int32 태그에서 온 숫자 |
| 그 밖의 모든 객체 형식 | 태그의 데이터 형식 | Float은 Real, Boolean은 Boolean, Int32는 부호 있는 정수, String은 문자열 |

쓰기와 함께 명령 우선순위를 보내지는 않습니다. 객체가 담을 수 없는 값, 예를 들어 다중 상태 객체에 0이나 바이너리 객체에 2는 아무것도 보내기 전에 거부되고, 그 거부가 이유를 알려 줍니다. 장치가 쓰기에 오류로 답하면 태그는 성공한 척하는 대신 장치가 보낸 오류 클래스와 오류 코드를 알리고, 장치는 연결된 채로 남습니다. 새 태그는 읽기 전용으로 시작합니다.

## 장치 검색 {#discovery}

Connector의 장치 검색 단추는 BACnet **Who-Is**를 브로드캐스트하고 10초 동안 **I-Am** 응답을 듣습니다. 답하는 장치는 모두 자기 주소와 포트와 장치 인스턴스를 담은 후보가 되어 연결 칸이 채워진 채 추가할 준비가 됩니다. 10초가 다 지난 뒤가 아니라 답하는 그 순간에 목록에 나타나므로, 도중에 취소한 스캔도 이미 답한 것은 모두 지킵니다. 스캔은 객체를 훑지 않으므로 후보는 태그 0개로 들어옵니다. 객체 형식과 인스턴스 쌍은 직접 추가하십시오.

Who-Is는 **스캔 범위** 카드가 가리키는 네트워크로 나갑니다. 그 입력란에는 그 네트워크의 IPv4 주소(장치의 주소 또는 그 네트워크에서 이 컴퓨터 자신의 주소, 예: `192.168.1.20`)를 쓰며, 그러면 스캔은 그 네트워크에만 브로드캐스트합니다. 비워 두면 Who-Is는 이 컴퓨터의 모든 네트워크로 나가므로, 네트워크 카드가 두 장이거나 VPN이나 Docker가 있는 컴퓨터도 각 네트워크의 장치를 찾습니다. 끝까지 다 쓴 IPv4 주소가 아닌 것은 입력란 아래에서 거부되고, 고칠 때까지 장치 검색 단추는 회색으로 남습니다.

**BACnet 라우터를 거쳐** 답하는 장치도 같은 방식으로 추가됩니다. 그 후보는 라우터의 주소와, 그 옆에 장치 자신의 네트워크와 그 네트워크에서의 주소를 함께 담습니다. 추가할 때 둘 다 지켜지고, 모든 읽기는 안쪽 장치를 밝히면서 라우터로 보내집니다. 그래서 이렇게 찾은 장치도 다른 장치와 똑같이 읽히며, 그 endpoint는 "라우터를 거친 장치"로 읽힙니다. 손으로 추가한 장치에는 경로가 없고 자기 호스트로 곧바로 닿습니다.

## 알아 두면 좋은 것 {#good-to-know}

- BACnet/IP만 다룹니다. MS/TP나 BACnet/SC 장비에는 그것을 BACnet/IP로 내주는 라우터를 거쳐야만 닿을 수 있고, 그것을 찾아 주는 것이 스캔입니다. 장치가 답한 경로는 스캔에서 그대로 지켜지므로, 칸을 손으로 입력하는 대신 검색된 목록에서 추가하십시오.
- 네트워크 인터페이스가 여러 개인 컴퓨터(네트워크 카드 두 장, VPN, Docker)에서는 각 장치에 이 컴퓨터가 그 주소로 가는 경로에 쓰는 인터페이스로 닿습니다. 여기서 다른 프로그램이 쓰는 것과 같은 인터페이스이므로 고를 것이 없습니다.
- 이 스테이션의 표준 BACnet UDP 포트 47808을 쓰는 것은 장치의 메시지를 기다리는 소켓뿐입니다. 그래서 같은 컴퓨터에서 다른 BACnet 애플리케이션이 그 포트를 독점하고 있으면 충돌할 수 있습니다. 장치로 가는 요청은 클라이언트마다 시스템이 고르는 포트에서 나갑니다.
- 이 드라이버의 모든 태그는 1초 주기로 고정되어 읽힙니다. 보통의 읽기 주기 칸은 나오지 않습니다.
