BACnetとは
BACnet(バックネット)とは、ASHRAE(アメリカ暖房冷凍空調学会;アシュレ)などで標準化されたビルオートメーション用通信プロトコルです。
空調や衛生(給水・排水)、エレベータ、電気、防犯、防災(消火設備)などの装置間の通信において、広く利用されています。
もし、これらビル用装置からデータを取得したり、制御したりする場合、BACnetの知識が役に立ちます。
本稿では、BACnet ToolsでBACnetデバイスに接続し、いろいろ遊んでみます。
BACnet Toolsとは
オープンソースで開発されているBACnetプロトコル用ライブラリとして、BACnet Stackがあります。
そのライブラリをデモとしてCLIツールを実装したものが、BACnet Toolsです。
Source Forge上では、Windows向けにコンパイルされた実行ファイルが提供されており、これを用いて簡単にBACnetデバイスと通信ができます。
プロジェクトのウェブページ
Windows向け実行ファイルの配布先
BACnetデバイスを見つける
bacwi
ネットワークに接続しているBACnetデバイスを、bacwiで探します。
bacwiは、Who-Isサービスをネットワーク上に送信し、応答のあったデバイスのリストを出力します。
以下に、私の環境で実行した結果を示します。
> ./bacwi.exe
;Device MAC (hex) SNET SADR (hex) APDU
;-------- -------------------- ----- -------------------- ----
6367 ■■:■■:■■:■■:■■:■■ 0 00 1476
;
; Total Devices: 1
※出力結果のMACアドレスは「■」に置き換えています。
もしデバイスが見つからない場合、ネットワークインターフェースが正しく選択できていない可能性があります。
BACnetデバイスを接続しているネットワーク上の、自分のIPアドレスを以下のように環境変数BACNET_IFACE
に設定します。
コマンド上の"192.168.0.184"
は、自分のIPアドレスです。
また、PowerShell上での、環境変数の設定コマンドです。
環境に合わせて変えていください。
$Env:BACNET_IFACE = "192.168.0.184"
bacwiにより、ネットワーク上のBACnetデバイスを見つけることができました。
デバイスIDが6367のBACnetデバイスがいるようです。
他のbacwiの使い方は、以下のコマンドで出力できます。
> ./bacwi.exe --help
bacwh
ある特定のオブジェクトを持っているデバイスを探したい場合があるかもしれません。
その場合、Who-Hasサービスでデバイスを探す、bacwhが適しています。
探したいオブジェクトの、「オブジェクトタイプ オブジェクトインスタンス」か「オブジェクト名」を指定します。
私の環境における実行結果を以下に示します。
AnalogOutputオブジェクトで、インスタンス番号0のオブジェクトを持っているデバイスを探索
> ./bacwh analog-output 0
I-Have: analog-output 0 from device 6367!
オブジェクト名が「myAnalogOutput」のオブジェクトを持っているデバイスを探索
> ./bacwh myAnalogOutput
I-Have: analog-output 0 from device 6367!
いずれも、デバイスインスタンス6367が、探しているオブジェクトを持っていると、BACnetデバイスがI-Haveサービスで応答しています。
BACnetデバイスからプロパティを取得する
bacrp
では、見つけたBACnetデバイスから、プロパティを取得します。
1つのプロパティを取得する場合、bacrpを使います。
例えば、AnalogOutput#0の現在値を取得してみます。
> ./bacrp.exe 6367 analog-output 0 present-value
0.000000
オブジェクトのIDやプロパティのIDを数値で指定することもできます。
例えば、IDはそれぞれanalog-outputは1で、present-valueは85なので、以下のようになります。
> ./bacrp.exe 6367 1 0 85
0.000000
bacrpm
bacrpでプロパティを一つづつ取得できますが、手間なので一度にたくさんのプロパティを取得したいです。
その場合、bacrpmを使います。
引数は順に以下です。
- デバイスID
- オブジェクト型
- オブジェクトインスタンス番号
- プロパティ番号(
,
で複数を連結可能)
プロパティ番号は例えば、現在値を示すpresent-valueは85となります。
配列の一部を取得するには、87[0]
のようにカッコ[]
で囲んでインデックス番号を指定します。
配列のすべてを取得するには、カッコを囲わずに指定します。
./bacrpm.exe 6367 analog-output 0 85,87[0],87
analog-output #0
{
present-value: 0.000000
priority-array: [0]16
priority-array: {Null, Null, Null, Null,
Null, Null, Null, Null,
Null, Null, Null, Null,
Null, Null, Null, Null}
}
複数のオブジェクトのプロパティを取得するには、デバイスID~プロパティ番号の組を、複数回繰り返して引数に指定します。
./bacrpm.exe 6367 analog-output 0 85 analog-input 0 85
analog-output #0
{
present-value: 0.000000
}
analog-input #0
{
present-value: 0.000000
}
すべてのプロパティを取得するには、プロパティ番号として8を指定します。
> ./bacrpm.exe 6367 analog-output 0 8
analog-output #0
{
object-identifier: (analog-output, 0)
object-name: "myAnalogOutput"
object-type: analog-output
present-value: 0.000000
status-flags: {false,false,false,false}
event-state: normal
out-of-service: FALSE
units: percent
priority-array: {Null, Null, Null, Null,
Null, Null, Null, Null,
Null, Null, Null, Null,
Null, Null, Null, Null}
relinquish-default: 0.000000
description: "hello analog output"
reliability: no-fault-detected
cov-increment: 1.000000
}
他に、選択可プロパティをすべて取得するには、プロパティ番号を80にします。
> ./bacrpm.exe 6367 analog-output 0 80
analog-output #0
{
description: "hello analog output"
reliability: no-fault-detected
cov-increment: 1.000000
}
必須プロパティをすべて取得するには、プロパティ番号を105にします。
> ./bacrpm.exe 6367 analog-output 0 105
analog-output #0
{
object-identifier: (analog-output, 0)
object-name: "myAnalogOutput"
object-type: analog-output
present-value: 0.000000
status-flags: {false,false,false,false}
event-state: normal
out-of-service: FALSE
units: percent
priority-array: {Null, Null, Null, Null,
Null, Null, Null, Null,
Null, Null, Null, Null,
Null, Null, Null, Null}
relinquish-default: 0.000000
}
BACnetデバイスのプロパティを設定する
bacwp
BACnetデバイスのプロパティに値を設定してみましょう。
引数は順に次のとおりです。
- device-instance
- object-type
- object-instance
- property
- priority
- index
- tag
- value
5番目の引数であるpriorityは、設定する値の優先度を1~16で指定します。
16が最も低い優先度です。
優先度を0とすると、優先度を指定しないことを意味しますが、16に自動的に割り当てられます。
6番目の引数であるtagは、設定する値の型を指定します。
present-valueの型は小数(REAL)であるため、4を指定します。
以下に、AnalogOutput#0の現在値present-valueに100.0を設定する例を示します。
> ./bacwp.exe 6367 analog-output 0 present-value 16 -1 4 100.0
設定後のAnalogOutput#0の必須プロパティを確認してみます。
> ./bacrpm.exe 6367 analog-output 0 105
analog-output #0
{
object-identifier: (analog-output, 0)
object-name: "myAnalogOutput"
object-type: analog-output
present-value: 100.000000
status-flags: {false,false,false,false}
event-state: normal
out-of-service: FALSE
units: percent
priority-array:{Null, Null, Null, Null,
Null, Null, Null, Null,
Null, Null, Null, Null,
Null, Null, Null, 100.000000}
relinquish-default: 0.000000
}
無事、present-valueが100.0になっていました。
また、priorityが自動的に16に割り当てられたためか、priority-arrayの16番目も100.0となっています。
bacwpm
複数のプロパティに値を設定するWritePropertyMultipleサービスを実行するコマンドです。
詳細の説明は割愛します。
以下のコマンドでヘルプを見るとができます。
> ./bacwpm --help
BACnteデバイスのプロパティ変更通知COVを設定する
値が変化した場合に通知する仕組みをCOV通知(Change Of Value)といいます。
COV通知を購読するには、bacscovを使います。
引数は以下です。
- device-id: デイバスID
- object-type: オブジェクトタイプ(文字列または数値)
- object-instance: オブジェクトインスタンス番号
- process-id: COV通知を受け取るプロセスID
- <[un]confirmed lifetime|cancel>: 何秒間購読するか数値で指定、「cancel」で購読をキャンセルする
実際にBACnetデバイスにCOV通知を購読した例を示します。
AnalogInput#0のCOV通知を60秒間購読しました。
BACnetデバイスで値を変更したところ、COV通知がbacscovに通知されました。
> ./bacscov 6367 analog-input 0 1 confirmed 60
Sent SubscribeCOV request. Waiting up to 60 seconds....
SubscribeCOV Acknowledged!
CCOV: Received Notification! <-COV通知購読時に受け取った通知
CCOV: PID=1 instance=6367 analog-input 0 time remaining=60 seconds
CCOV: present-value
CCOV: status-flags
CCOV: Sending Simple Ack!
CCOV: Received Notification! <-値の変更時に受け取った通知
CCOV: PID=1 instance=6367 analog-input 0 time remaining=50 seconds
CCOV: present-value
CCOV: status-flags
CCOV: Sending Simple Ack!
付録1:EPICSファイルを出力する
EPICSファイルというBACnetデバイスのオブジェクトの一覧を定義したファイルがあるそうです。
電気設備学会のガイドラインでは、CSVによりオブジェクト一覧を記すフォーマットがありますが、そのようなものだと思います。
とりあえず、オブジェクトの一覧を取得できるので、大変便利です。
以下は実行例です。(長いので一部抜粋)
> ./bacepics 6367
PICS 0
BACnet Protocol Implementation Conformance Statement
...
List of Objects in Test Device:
{
{
object-identifier: (device, 6367)
object-name: "my-bacnet-device"
object-type: device
...
ip-subnet-mask: FFFFFF00
ip-default-gateway: C0A80001
ip-dns-server: { C0A80001,00000000,00000000 }
}
}
End of BACnet Protocol Implementation Conformance Statement
付録2:デモサーバを起動
BACnet Toolsには、BACnet接続の練習用として、デモサーバであるbacservが同梱されています。
デモサーバ用の起動前に、ポート番号を指定しておきます。
同じパソコン上でデモサーバとクライアントを開こうとすると、デフォルトのポート番号である47808をお互いに取り合おうとするからです。
そのため、デモサーバのポート番号を47809に変更し、
デフォルトのポート番号47808はGUIツールであるYet Another Bacnet Explorer用に残しておきます。
PowerShellでは、以下のコマンドでポート番号を指定する環境変数を変更できます。
$ENV:BACNET_IP_PORT = 47809
ポート番号を指定後、デモサーバを起動します。
> .\bacserv.exe 123
BACnet Server Demo
BACnet Stack Version 1.3.4
BACnet Device ID: 123
Max APDU: 1476
BACnet Device Name: SimpleServer
Yet Another Bacnet Explorerでデモサーバに接続した例です。