BACnetなる技術についての概要まとめ

最近業務でBACnetなる技術を初めて触り、結構な時間を使ってキャッチアップしたので、せっかくならその技術についてまとめてみようということで、今回記事を書いてみています。
この技術自体はweb界隈の人が関わることはほぼないと思うので、qiitaに書いて需要があるかは甚だ疑問ですが。。

# BACnetとは？
なにはともあれ、BACnetとは何者なのか、というところから。
読み方は「バックネット」で、「Building Automation and Control networking protocol」の略です。
以下は[Wikipedia](https://ja.wikipedia.org/wiki/BACnet)より引用
>BACnet は、インテリジェントビル用ネットワークのための通信プロトコル規格である。ASHRAE、ANSI、ISOでの標準規格とされている。Building Automation and Control Networking protocol の略。空調、照明、アクセス制御、火気検出などの総合的制御に使われる。BACnet プロトコルは、各種機器がメーカー固有の仕様であっても、共通なインタフェースを介することですべて接続し、監視できる。

要はビルの各種機器（空調、照明、エレベータ、火災報知器など）をコントロールするための技術で、あくまでプロトコルなのでHTTPなどの類のもので、ビルの機器同士がどのように通信するかの取り決めを定義している規格です。

ビルの機器というのは昔はそれぞれのメーカーが独自の通信規格を用いてコントロールをしていたらしいのですが、それだと異なるメーカー同士の機器を繋ぐためには追加の開発が必要になったり、機器を選定する側も自由に選択することができなかったので市場の競争が適切に行われないなどの問題があったらしいです。

そこで、業界で統一的な通信規格を定義して、それをオープンにすることで、メーカー問わず連携できるようにしようよというのが、BACnetが生まれた背景らしいです。

# どんなふうに通信するの？
BACnetの通信にはUDP/IPを利用して通信します。
実際はこれはBACnetの中でもBACnet/IPと分類されるものだけで、BACnetには他にも種類あるのですが、web界隈の人が関わることがあるとすればこれだけだと思うので、BACnet = UDP/IPを使うと理解しててもそんなに問題ないかと思います。
（BACnet/IP以外では通信にRS-485を利用するBACnet MS/TPなどがあります。）

UDP/IPなので、TCP/IPと違ってコネクションせずに信号投げっぱなし、受信できたかは知らんという感じで通信します。
じゃあ通信できたかわからなくない？という部分については、UDP/IPより上位のレイヤーでなんとかしてます。
なぜUDPなの？というと、オーバーヘッドをなるべく小さくしたかったというのが大きな理由のようです。

# 実際に通信の中身を見てみよう
仕様とか説明していくより先に、まずは実際に通信されるものってどんな感じなの？というのを見てみたいと思います。
通信の中身をキャッチして確認するためのツールとして今回は[Wireshark](https://www.wireshark.org/download.html)を用います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484082/52ce24b8-600d-4e39-e01f-2ebb49fc0437.png)


udp通信でポート番号47808を指定すると、BACnetの通信を観測することができます。
ちなみに、「47808」を16進数に変換すると「BAC0」であるため、このポートをBACnet通信のデフォルトのポート番号としているようです。（他のポートを指定することも可能）

Protocolの部分にBACnet-APDUと書かれていることから、これがBACnetの通信であることがわかります。
APDUというのは、Application Protocol Data Unit の略で、BACnetの機器間が通信する最小のデータ単位です。
Infoの部分の「Unconfirmed-REQ i-Am device, 1234」というのは通信の中身の概略です。詳細は別途。

Wiresharkの画面上で真ん中の部分が通信の中身を詳細に解析した結果で、下の部分がバイト列で表現したものになっています。
先に述べたAPDUが実際の通信の中身で、それより上の部分はAPDUを通信で渡すためのヘッダー類で、[OSI参照モデル](https://ja.wikipedia.org/wiki/OSI%E5%8F%82%E7%85%A7%E3%83%A2%E3%83%87%E3%83%AB)の各レイヤー間で情報を受け渡すときに必要な情報をヘッダーとして含んでいます。

「User Datagram Protocol」より上の部分はUDP/IPより下のレイヤー部分なので今回は触れず、BACnet Virtual Link Controlより下の部分の詳細を見ることで、ざっくりとしたイメージをつかみたいと思います。

### BACnet Virtual Link Control (BVLC)
BACnet Virtual Link Layer (BVLL, BACnet仮想データリンク層)と呼ばれる、ネットワーク層とその階層である各種通信サブシステムとの間のインターフェースを担う部分です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484082/9e2e70b5-4603-79cc-1632-8bb7c3e1e429.png)

- プロトコルの種類がBACnet
- ブロードキャストで送られた信号
- APDU部分まで含めたデータの長さが25バイト（そのうちBVLC部分が４バイトを占めている）

と言うことをそれぞれ表しています。
BACnetの各種機器は、まずこの部分の情報を読み取って、BACnet以外の通信を切り捨てたり、後続のバイト列のデコードに必要な情報を取得したりします。

### BACnet NPDU
Building Automation and Control Network NPDUの部分です。
NPDUは Network Protocol Data Unit の略です。
いわゆるネットワーク層よりも上位レイヤーの意味合いを表現しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484082/5a976b6a-cc49-6819-53da-690466a6c249.png)

- Version : BACnetプロトコルのバージョンは１（現状１しか存在しない）
- Control : 通信先の情報を持っている(他にも通信元の情報を持っているかどうかなど、NPDUがどう言う構成かを示す部分)
- Destination : 通信先がどこなのか
- Hop Count : ネットワークが循環してしまっている場合などに、データが永遠に残らないようにするためのもの

などの情報を示しています。
APDUの内容をどうやって届けるか、についての情報を保持している部分と言えます。

### BACnet APDU
Building Automation and Control Network APDUの部分です。
APDUは上にも書きましたが、Application Protocol Data Unit の略です。
OSIモデルにおけるアプリケーション層に相当します。
すなわち、BACnetは物理層、データリンク層、ネットワーク層、アプリケーション層の4層構造になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484082/e0c56273-9dee-555c-829b-9ee5394c49e1.png)

- APDU Type : タイプは確認なしのRequest
- Unconfirmed Service Choice : サービスの種類はI-Am
- Object Identifier : このメッセージを送ってきた機器の識別番号は1234番
- Max APDU Length Accepted : このメッセージを送ってきた機器の受信可能なバイト長の最大値が1024バイト
- Segmentation Supported : セグメント化（メッセージが長過ぎる場合にメッセージを分割して送信すること）に対応していない
- Vendor ID : このメッセージを送ってきた機器を作ったベンダーはBACnet Stack at SourceForge

などの情報を持っています。
APDUが、実際にBACnetの各機器がやりとりしたい情報の中身であり、その中身はAPDU Typeやサービスの種類によって変わります。
APDU Typeは、たとえば
- Confirmed-request(応答ありのRequest)
- Unconfirmed-request(応答なしのRequest)
- SimpleACK(シンプルな応答)
- Error(エラー)

など、８種類が定義されています。
そして、それぞれのタイプに対して、サービスが複数定義されており、例えばConfirmedRequestの場合は29種類のサービスが定義されています。
信号を受信した機器は、これらのタイプやサービスの種類に応じた適切なデコードをすることで、信号の中身を解釈します。

「通信できたかわからなくない？という部分については、UDP/IPより上位のレイヤーでなんとかしてます。」というのを上の方で書きましたが、
APDU TypeのSimpleACK, ComplexACKというのを応答信号として送ることで、通信できたことを認識しています。
Unconfirmed-requestというのを定義しているように、応答を必要としないサービスもあるため、TCPではなくUDPを使うことでオーバーヘッドを減らしています。

# オブジェクト、プロパティとは？
BACnetでは、通信機器をデバイス、オブジェクト、プロパティという概念で抽象化して表現しています。 

- デバイスは実際の通信機器ひとつひとつに対応する概念
- オブジェクトはその中の様々な機能を表現する概念であり、１つのデバイスの下には複数のオブジェクトが定義される
    - 例： AnalogInput, AnalogOutput, BinaryInput, BinaryOutput, Calendar, EventLog, NotificationClassなど
- プロパティは各オブジェクトが持つ属性情報
    - 例: ObjectName, ObjectType, PresentValue, PropertyListなど

例えば、以下のように各機器を表現できます。
device1
┃   └ ObjectName: デバイス１
┣AnalogInput1
┃   └ ObjectName: 温度
┃   └ PresentValue: 20
┣AnalogInput2
┃   └ ObjectName: 湿度
┃   └ PresentValue: 60
┣BinaryInput1

オブジェクトの数は50を超え、エレベータなども表現できたりするので、ビル管理に必要な各種機器をそれらで表現することが
できるようになっています。

# どんなサービスがあるの？
例えば、基本的なサービスとして、以下のようなものが定義されています。

- Confirmed-request(応答ありのRequest)
    - readProperty: オブジェクトとプロパティを指定して、その内容を取得する
    - writeProperty: オブジェクトとプロパティを指定して、その内容を更新する
    - subscribeCOV: COV(Change Of Value)の通知を受け取れるように、通知先として自分の情報を登録する
- Unconfirmed-request(応答なしのRequest)
    - i-Am: 自分の情報（Id情報や通信先のアドレスなど）を周知する
    - who-is: Idを指定して、そのIdをもつデバイスから、通信するためのアドレス情報を返してもらうように依頼する
    - unconfirmedCOVNotification: 自身の値が変わったことを他のデバイスに周知する

この他にも多くの種類のサービスがあり、これらを利用してデバイス間で情報をやりとりしたり、他のデバイスを操作したりします。

# まとめ
実際の信号の中身を見てみることで、どんな通信が行われるのかざっくりしたイメージが掴めたかなと思います。
また、オブジェクトやプロパティで実際の機器を表現して、サービスでその情報を操作するということもなんとなくわかったかなと思います。
BACnetについての情報は、特に導入部分を日本語で解説しているものが少ないので、理解の一助となれば幸いです。

# 参考情報
- [BACnet公式サイト](http://www.bacnet.org/)
公式のサイトです。歴史を感じます。。

- [BACnet International](https://www.bacnetinternational.org/)
テスト機関などへのリンクなども掲載しています

- [BACnetについて解説している技術ブログ](https://blog.fits-inc.jp/2020/03/19/bems%E3%80%81bacnet%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/)
ググって出てきた中で一番説明がわかりやすかったです

- [BACnet Stack](http://bacnet.sourceforge.net/)
オープンソースのライブラリなどを公開しているプロジェクトです
C, C#, python, Javaなどのライブラリがあるようです

- [BACnet Testing Lab](https://www.bacnetlabs.org/)
テスト機関のサイトです。製品として販売する際に認証を取得したりするための期間です。
[自身でテストするためのツール](https://www.bacnetlabs.org/page/pre_testing_tools)の紹介などもあり、いくつか自分も利用しました。
VTSというものを実際利用しましたが、Windows上でしか動かせないのがネックでした。。

- [公式の仕様書、翻訳版](https://www.ieiej.or.jp/service/text-app/book10.html)
高いです。あと、全てが翻訳されているわけではないのが注意が必要なのと、日本語が怪しい部分多々ありますが、
実際にBACnetを使って開発するためには必須の書籍です。
英語が苦手でなければ、英語版を買った方が確実です。