Node-REDのnode-red-contrib-bacnetを使って、CoolMasterのON/OFFを行う方法を調べます。
YABEのデータ

YABEを使ってCoolMasterを調べると、
L1.101 on/off(BV:256)がオンオフを制御するデータポイントのようです。

Present Valueが1となっていて、現在稼働中です。

Present Valueを0にすることでCoolMasterに接続された空調機(旧東芝キャリア)の電源もオフになりました。
Node-REDからON/OFFの状態を取得する

このようなフローを作成します。

TypeにはBV(BinaryValue)を意味する5

InstanceはBV:256に設定。

Deviceha接続するCoolMasterのIPアドレス。Client はNode-REDを動かすPCのIPを入れます。


実行すると

ValuesのValueが1で空調機が動いていることを確認。
空調の電源をオフにして再度実行。

Valueが0になりオフになったことが確認できました。
Node-REDからBACnetのONをにしてみる

BACnet WriteノードをつかってONにするフローを作成しました。

プロパティはReadと同じように設定。

このようにしたところ

型が合わないというエラーが出ました。
ON/OFFはBooleanだと思って

App-Tagを1にしたのですが、違うようです。
WireSharkで確認
YABEを使ってL1.101 on/off(BV256)を0にしてWiresharkでパケットを取得します。


Wireshark側ではこのようにパケットがキャプチャされました。
Frame 202: 65 bytes on wire (520 bits), 65 bytes captured (520 bits) on interface \Device\NPF_{0F0CA621-1947-4E3A-81CB-D5506A2CE640}, id 0
Section number: 1
Interface id: 0 (\Device\NPF_{0F0CA621-1947-4E3A-81CB-D5506A2CE640})
Encapsulation type: Ethernet (1)
Arrival Time: Jun 9, 2025 18:54:29.258290000 東京 (標準時)
UTC Arrival Time: Jun 9, 2025 09:54:29.258290000 UTC
Epoch Arrival Time: 1749462869.258290000
[Time shift for this packet: 0.000000000 seconds]
[Time delta from previous captured frame: 0.010301000 seconds]
[Time delta from previous displayed frame: 0.000000000 seconds]
[Time since reference or first frame: 9.533515000 seconds]
Frame Number: 202
Frame Length: 65 bytes (520 bits)
Capture Length: 65 bytes (520 bits)
[Frame is marked: False]
[Frame is ignored: False]
[Protocols in frame: eth:ethertype:ip:udp:bvlc:bacnet:bacapp]
[Coloring Rule Name: UDP]
[Coloring Rule String: udp]
このデータをChatGPTに開設してもらいます。


Frame 202: 65 bytes on wire (520 bits)
- このパケットは物理層で 65バイト(520ビット) です。
- イーサネットの最小パケットサイズ(60バイト)に近いので、制御や短いデータ(小さいリクエストパケット)の可能性があります。
🟢 Interface id: 0 (\Device\NPF_{…})
- このパケットは、Wiresharkが使用しているネットワークインターフェイス(例: 有線LAN、仮想ネットワークカード)上でキャプチャされました。
- そのIDが
0F0CA621-1947-4E3A-81CB-D5506A2CE640
です。
🟣 Arrival Time
- ローカル時間(東京標準時): 2025年6月9日 18:54:29.258
- UTC時間: 2025年6月9日 09:54:29.258
- 参考:Epoch(秒数): 1749462869.258
これは解析時にタイムラインを確認するのに便利です。
🔵 Frame Length / Capture Length
- 65 bytes = 520 bits
- Frame Length: パケット全体の物理長
- Capture Length: Wiresharkが実際に取り込んだ長さ(ここでは同じ)
🟡 Protocols in frame
eth:ethertype:ip:udp:bvlc:bacnet:bacapp
- Ethernet → IP → UDP → BACnet/IP(bvlc)→ BACnet Application(bacapp)
- Node-REDのBACnet-Writeノードで送信したか、デバイスが応答したBACnet/IPパケットだと思われます。

Building Automation and Control Netwokr NPDUについて確認します。
🔎 NPDUとは?
NPDU(Network Protocol Data Unit) は、BACnetプロトコルスタックの中で「ネットワーク層」に相当する部分のデータ単位です。
BACnet/IPやMSTPなど、BACnetの通信プロトコルで必ず使用されるデータ構造で、BACnetパケットの配送先(アドレス情報)や制御フラグ、後続のAPDU(Application Protocol Data Unit)を包含します。
BACnetはOSI参照モデルをベースに設計されていて、簡略化するとこんなイメージです。
項目 | 内容 |
---|---|
バージョン | BACnetプロトコルのバージョン番号(通常1) |
制御フラグ | メッセージの種別(例: ネットワーク層だけ or アプリケーション層まで含む) |
DNET(宛先ネットワーク) | 宛先BACnetネットワーク番号(ルーター経由の場合) |
DLEN(宛先MAC長) | 宛先MACアドレス長 |
DADR(宛先MACアドレス) | 宛先MACアドレス(BACnet/IPならIP+ポート) |
SNET(送信元ネットワーク) | 送信元BACnetネットワーク番号 |
SLEN(送信元MAC長) | 送信元MACアドレス長 |
SADR(送信元MACアドレス) | 送信元MACアドレス |
Hop Count | ルーティングのホップ数(デフォルト255) |
APDU | BACnet Application Protocol Data Unit(BACnetの実データ) |
🛠️ NPDUの役割
- ルーティング: BACnet/IPだけでなく、MSTPやARCNETなど異なるネットワーク間でもBACnetルーターでNPDUを中継します。
- アドレス情報: 宛先や送信元のBACnetネットワーク情報を含めることで、異なる物理ネットワーク間でBACnet通信が可能になります。
- アプリケーション層の包み紙: NPDUの中にAPDU(データ操作コマンドやオブジェクトデータ)を格納して送信します。

以上のようにNPDUはネットワークに関するデータのようなので、先ほどのNode-REDで発生したエラーは次のAPDUを調べればわかりそうです。
APDUについて
Building Automation and Control Network APDU
0000 .... = APDU Type: Confirmed-REQ (0)
.... 0000 = PDU Flags: 0x0
.... 0... = Segmented Request: Unsegmented Request
.... .0.. = More Segments: No More Segments Follow
.... ..0. = SA: Segmented Response not accepted
.111 .... = Max Response Segments accepted: Greater than 64 segments (7)
.... 0101 = Size of Maximum ADPU accepted: Up to 1476 octets (fits in an ISO 8802-3 frame) (5)
Invoke ID: 13
Service Choice: writeProperty (15)
ObjectIdentifier: binary-value, 256
Context Tag: 0, Length/Value/Type: 4
0000 0001 01.. .... .... .... .... .... = Object Type: binary-value (5)
.... .... ..00 0000 0000 0001 0000 0000 = Instance Number: 256
Property Identifier: present-value (85)
{[3]
Present Value (enum index): 0
Application Tag: Enumerated, Length/Value/Type: 1
}[3]
.... 1... = Tag Class: Context Specific Tag
0011 .... = Context Tag Number: 3
.... .111 = Named Tag: Closing Tag (7)
Priority: (Unsigned) 16
Context Tag: 4, Length/Value/Type: 1
.... 1... = Tag Class: Context Specific Tag
0100 .... = Context Tag Number: 4
Length Value Type: 1
このAPDUはBACnetクライアントからデバイスに送信される「writeProperty」リクエストです。
📦 まず全体像
このパケットはBACnet/IP通信でよく見られる Confirmed-REQ (0)(アプリケーション層の確認応答付きリクエスト)です。
サービス要求内容は「binary-valueオブジェクト(インスタンス256)のpresent-valueを書き込みたい」です。
🔹 APDU Type: Confirmed-REQ (0)
- 意味: BACnetのAPDUタイプは4種類あります。
- 0: Confirmed Request(応答を期待する)
- 1: Unconfirmed Request(応答不要)
- 2: SimpleACK(成功応答)
- 3: ComplexACK(成功応答・分割)
- 4: SegmentACK(分割応答)
- 5: Error(エラー応答)
- 6: Reject(拒否応答)
- 7: Abort(中止応答)
- ここでは Confirmed Request なので、デバイスからACKが必要です。

ここにConfirmedRequestが表示されています。
🔸 PDU Flags: 0x0
各ビットの意味:
- Segmented Request: Unsegmented(分割なし)
- More Segments: No More Segments Follow(最後のセグメント)
- SA: Segmented Response not accepted(分割応答不要)

🔹 Max Response Segments accepted: 7
- クライアントがデバイスに対して「最大何個のセグメントなら受け取れるか」を伝えています。
- 7 → 「64セグメント以上OK」


途中いろいろ省略
項目 | 内容 |
---|---|
APDU Type | Confirmed Request(応答必要) |
Service | writeProperty(プロパティ書き込み) |
Object | binary-value, Instance=256 |
Property | present-value(85) |
Value | 0(inactive) |
Application Tag | Enumerated(整数型) |
Priority | 16(最低優先度) |
という状況でした。
Node-REDのコマンドをWireSharkでキャプチャ

コマンドをおくりました。
項目 | 内容 |
---|---|
送信元 | 192.168.1.14(Node-REDやBACnetクライアント) |
送信先 | 192.168.1.100(BACnetデバイス) |
プロトコル | BACnet/IP(UDP 47808) |
BVLC Function | Original-Unicast-NPDU(単一デバイス宛) |
APDU Type | Confirmed Request(応答が必要) |
サービス | writeProperty(プロパティ書き込み) |
オブジェクト | binary-value(256) |
書き込み先 | present-value(85) |
書き込み値 | True(bool) |
Priority | 16 |
⚠️ 注意点
もしここでBACnetデバイスから Error Class: PROPERTY (2) Code: INVALID_DATA_TYPE (9)
のようなエラーが返る場合、原因として:
- 実は binary-value.present-value が Enumerated(0 or 1)として実装されているデバイスの場合。
- → Application Tag を Enumerated(App-Tag=9)にしなければならない。
- デバイスがBoolean型をサポートしていない場合。
- → Application Tag を変更する必要がある。
とのメッセージ。

App-Tagを9:ENUMERATEDに変更して実行

無事に空調機をBACnetからONにすることができました。
Node-REDからBACnetでCoolMasterのON/OFFをする方法


単純にON/OFFするには、App-Tagを9にして、Valueを0と1のBACnet Writeノードをつなげればよい。
でも、これはValueで渡したいですよね。
Node-REDからValueで渡してBACnetでON/OFFする方法

[{"id":"a3ae6e1135ec2c44","type":"BACnet-Write","z":"11b5d970f1ab28c1","name":"","objectType":"5","instance":"d6dff7e9f9703782","valueTag":"9","valueValue":"","propertyId":"85","priority":"16","device":"54de1b76e537f00b","server":"cd9b93738b4a729c","multipleWrite":false,"x":620,"y":1000,"wires":[["debug"]]},{"id":"e740e03b5766af4e","type":"function","z":"11b5d970f1ab28c1","name":"Format Payload","func":"msg.payload = {\n values: [\n {\n type: 9,\n value: msg.payload\n }\n ]\n};\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":400,"y":1000,"wires":[["a3ae6e1135ec2c44"]]},{"id":"95a39f71c0add7cd","type":"inject","z":"11b5d970f1ab28c1","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":170,"y":980,"wires":[["e740e03b5766af4e"]]},{"id":"4fa378d03d7fd8a3","type":"inject","z":"11b5d970f1ab28c1","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":170,"y":1020,"wires":[["e740e03b5766af4e"]]},{"id":"d6dff7e9f9703782","type":"BACnet-Instance","name":"ON/OFF","instanceAddress":"256"},{"id":"54de1b76e537f00b","type":"BACnet-Device","name":"CoolMaster","deviceAddress":"192.168.1.100"},{"id":"cd9b93738b4a729c","type":"BACnet-Client","name":"PC(Node-RED)","adpuTimeout":"6000","port":"47808","interface":"","broadcastAddress":"192.168.1.14"}]
フローはこのとおり

InjectノードではON:1、OFF:0にします。

msg.payload = {
values: [
{
type: 9,
value: msg.payload
}
]
};
return msg;
Functionノードには、TYPEはApp-Tagの値で9:Enumerated。
送る値はmsg.payloadで渡しています。

BACnet WriteノードはApp-Tagを空にするとエラーがでるのでこのようにします。
ちなみに、ここにApp-Tagを記載しても、Functionノードから送られる値に上書きされるので、ここはなんでも大丈夫そうです。
まとめ
以上、Node-REDからCoolMasterにBACnetでON/OFFする方法をご紹介しました。
値を動的に送る際のフォーマットがわからず、ここでかなり時間を費やしました。