Discovering, Reading and Writing Properties#
The bacnetclient utility provides a simple way to discover BACnet/IP
devices and objects, read and write object properties, and
subscribe to Change-of-Value (COV) notifications against a BACnet/IP
network.
Usage#
bacnetclient.py [OPTIONS] [command [args...]]
By default, bacnetclient binds to all local interfaces using
BACpypes3’s own address resolution. Use -a/--address to bind a specific
local address (CIDR form, e.g. 192.168.1.50/24); this is required when
more than one local interface could otherwise be selected, or when the
default BACnet/IP port (47808) is already in use locally.
--name/--instance/--vendor-id configure the local device object
identity (defaults: icspacket/999/999); --foreign/
--foreign-ttl register the local device as a foreign device with a
remote BBMD, and --bbmd instead configures the local device to act as a
BBMD itself with the given Broadcast Distribution Table entries.
bacnetclient.py
bacnet> whois <address>
bacnet> read <address> analog-value,1 present-value
bacnet> exit
Discovering Devices and Objects#
bacnetclient.py whois
bacnetclient.py whois <address>
bacnetclient.py whois --low 1000 --high 2000
bacnetclient.py whohas <address> -o analog-value,1
bacnetclient.py whohas <address> -n "ANALOG VALUE 1"
whois (alias wi) sends a Who-Is request and reports every device
that answers with an I-Am, either broadcast on the local network (default)
or unicast to a single <address>. -l/--low and -u/--high narrow
the query to a device instance range.
bacnet> whois <address>
+-------------+------------+----------+-----------------+-----------+
| Device | Address | Max APDU | Segmentation | Vendor ID |
+=============+============+==========+=================+===========+
| device,4000 | <address> | 1476 | no-segmentation | 260 |
+-------------+------------+----------+-----------------+-----------+
whohas (alias wh) discovers which device(s) hold a given object,
searching by either -o/--object-id or -n/--name (mutually
exclusive).
Reading and Writing Properties#
bacnetclient.py read <address> analog-value,1 present-value
bacnetclient.py write <address> analog-value,1 present-value 72.5 -p 8
bacnetclient.py write <address> binary-value,1 present-value active -p 8
bacnetclient.py identify <address>
read/write (aliases r/w) operate on a single object
property, addressed by object identifier (e.g. analog-value,1) and
property identifier (e.g. present-value). -i/--index selects an
array element for array-valued properties, and -p/--priority sets a
commandable priority (1-16) for write.
bacnet> write <address> analog-value,1 present-value 72.5 -p 8
[I] Writing 72.5 to analog-value,1.present-value on <address>...
[I] Write operation succeeded
bacnet> read <address> analog-value,1 present-value
[I] Reading analog-value,1.present-value from <address>...
analog-value,1.present-value = 72.5
identify (alias id) reads a device’s identification properties
(vendor-name, model-name, firmware-revision, …), resolving
the device identifier automatically via whois unless -d/--device-id
is given.
Reading and Writing Multiple Properties at Once#
bacnetclient.py rpm <address> -o analog-value,1:present-value,units -o device,4000:vendor-name
bacnetclient.py wpm <address> -w analog-value,1:present-value:72.5::8 -w binary-value,1:present-value:active::8
rpm issues a single ReadPropertyMultiple request. Repeat
-o/--object for each object to read, in
OBJECT:PROP[,PROP...] form (comma-separated property list).
Browsing a Device’s Objects#
bacnetclient.py objects <address>
bacnetclient.py objects <address> --values
bacnet> objects <address> --values
+-----------------+----------------+-------+
| Object | Name | Value |
+=================+================+=======+
| device,4000 | icspacket-... | |
| analog-value,1 | ANALOG VALUE 1 | 72.5 |
| binary-value,1 | BINARY VALUE 1 | ... |
+-----------------+----------------+-------+
(truncated - a real device typically reports many more objects)
Change-of-Value Subscriptions#
bacnetclient.py subscribe <address> analog-value,1
bacnetclient.py subscribe <address> analog-value,1 --confirmed --duration 30
bacnetclient.py subscribe <address> analog-value,1 --count 5
subscribe (alias sub) subscribes to Change-of-Value notifications
for a single object and prints each notification as it arrives, until
--duration seconds elapse, --count notifications have been
received, or Ctrl+C is pressed (whichever comes first; the default is to
run indefinitely).
Pass -c/--confirmed to request confirmed
notifications instead of the default unconfirmed ones, and
-l/--lifetime to request a specific subscription lifetime in seconds
instead of BACpypes3’s default (which most implementations, including
bacnet-stack, treat as an indefinite subscription).
Most servers send an immediate notification reflecting the object’s current value as soon as the subscription is accepted, before any further change actually occurs:
bacnet> subscribe <address> analog-value,1 --duration 30
[I] Subscribing to analog-value,1 on <address> (confirmed=False)...
present-value = 99.9000015258789
status-flags = <StatusFlags: >
present-value = 123.44999694824219
status-flags = <StatusFlags: >
(the second pair of lines above was produced by writing a new value to
analog-value,1 from a separate client while the subscription above was
still active).
BBMD Broadcast Distribution and Foreign Device Tables#
bacnetclient.py bdt <address>
bacnetclient.py fdt <address>
bdt/fdt read a remote BBMD’s Broadcast Distribution Table /
Foreign Device Table:
bacnet> bdt <address>
+------------+
| Entry |
+============+
| <address> |
+------------+
bacnet> fdt <address>
[W] FDT is empty