BACnet Stack
This BACnet protocol stack library provides a BACnet application layer, network layer and media access (MAC) layer communications services. It is an open source, royalty-free library for an embedded system, Windows, Linux, or other operating system. Example BACnet client and server applications are included.
git clone https://github.com/bacnet-stack/bacnet-stack.git
cd bacnet-stack
apt install make
git checkout bacnet-stack-0.8.6
make clean all
cd bin/
./bacwi
./bacrp 6 0 0 85
Among them, 6 is datatype, the first 0 is the data point object, the second 0 is the corresponding number of the data point object, 85 means the present value.
BACnet Tools
BACnet Tools are binary demo application command line utilities that use BACnet/IP to perform a variety of BACnet services. Some tools use BACnet WhoIs to bind to devices, but can also use a static binding file address_cache.
Most of the tools have help (–help option), and use environment variables to configure the datalink.
The Client Tools use WhoIs to bind to target devices. The WhoIs can be eliminated by using the address_cache file, which is read by each client tool from the current working directory. Having the device address from the address_cache file will greatly improve the throughput and speed of the client tools. The address_cache file can be generated using the standard output of the bacwi tool.
EXAMPLE: bacwi -1 > address_cache
Client Tools
- bacarf - BACnet AtomicReadFile service
- bacawf - BACnet AtomicWriteFile service
- bacdcc - BACnet DeviceCommunicationControl service
- bacepics - BACnet EPICS for Device object.
- bacrd - BACnet ReinitializeDevice service
- bacrp - BACnet ReadProperty service
- bacrpm - BACnet ReadPropertyMultiple service
- bacscov - BACnet SubscribeCOV service
- bacts - BACnet TimeSynchronization service
- bacucov - BACnet UnconfirmedChangeOfValue service
- bacupt - BACnet UnconfirmedPrivateTransfer service
- bacwh - BACnet WhoHas service
- bacwi - BACnet WhoIs service
- bacwp - BACnet WriteProperty service
Server Tools
- bacserv - BACnet Device Simulator
Router Tools
- baciamr - BACnet I-Am-Router to Network message
- bacinitr - BACnet Initialize Router message
- bacwir - BACnet Who-Is Router to Network message
MS/TP Tools
- mstpcap - a tool that is used for capturing MS/TP traffic from an RS-485 serial adapter and saving the packets in a file for viewing by Wireshark.
- mstpcrc - calculates Header CRC or Data CRC for ascii hex or decimal input. Optionally takes the input and saves it to a PCAP format file for viewing in Wireshark.
Environment Variables
- BACNET_APDU_TIMEOUT - set this value in milliseconds to change the APDU timeout. APDU Timeout is how much time a client waits for a response from a BACnet device. Default is 3000ms.
- BACNET_APDU_RETRIES - indicate the maximum number of times that an APDU shall be retransmitted.
- BACNET_IFACE - set this value to dotted IP address (Windows) of the interface (see ipconfig command on Windows) for which you want to bind. On Linux, set this to the /dev interface (i.e. eth0, arc0). Default is eth0 on Linux, and the default interface on Windows. Hence, if there is only a single network interface on Windows, the applications will choose it, and this setting will not be needed.
- BACNET_IP_PORT - UDP/IP port number (0..65534) used for BACnet/IP communications. Default is 47808 (0xBAC0).
- BACNET_BBMD_PORT - UDP/IP port number (0..65534) used for Foreign Device Registration. Defaults to 47808 (0xBAC0).
- BACNET_BBMD_TIMETOLIVE - number of seconds used in Foreign Device Registration (0..65535). Defaults to 60000 seconds.
- BACNET_BBMD_ADDRESS - dotted IPv4 address of the BBMD or Foreign Device Registrar.
- BACNET_BDT_ADDR_1 - dotted IPv4 address of the BBMD table entry 1..128
- BACNET_BDT_PORT_1 - UDP port of the BBMD table entry 1..128 (optional)
- BACNET_BDT_MASK_1 - dotted IPv4 mask of the BBMD table entry 1..128 (optional)
- BACNET_IP_NAT_ADDR - dotted IPv4 address of the public facing router
Example Usage
You can communicate with the virtual BACnet Device by using the other BACnet command line tools. If you are using the same PC, you can use BBMD/FD (Foreign Device registration) to do this - use the bvlc script. You can monitor the interaction and bytes on the wire using Wireshark. Here is an example usage for Window and for Linux.
Windows
The BACnet tools are used from the Command Prompt, or CMD.EXE. From the command prompt window, start the simulated BACnet device:
c:\> bacserv 1234
From another command prompt window, use ipconfig to determine the network interface IP address that bacserv is using:
c:\> ipconfig
Use the default IP address to configure the BBMD and Foreign Device environment variables:
c:\> bvlc.bat 192.168.0.42
bvlc.bat batch file configures environment variables to use BACnet/IP port 47809 for any subsequent BACnet tools run from that command prompt window, and enables the BBMD Foreign Device Registration.
Perform a device discovery:
c:\> bacwi -1
Read all the required properties from the Device 1234 and display their values:
c:\> bacepics -v 1234
Read the Object_Identifier property from the Device 1234:
c:\> bacrp 1234 8 1234 75
Write 100.0 (REAL=4 datatype) to Device 1234 Analog Output (1) One (1) at priority 16 with no index (-1).
c:\> bacwp 1234 1 1 85 16 -1 4 100.0
Each tool has help:
c:\> bacrp --help
Linux
To use the tools from the command line, you need to use the path to the command, or include the path in your PATH environment variable. The dot “.” means current directory. The “/” is used to separate directories. “./” means the path starts from the current directory.
When the tools are built from the Makefile, they are copied to the bin/ directory. So from the root of the project you could run the tools like this using a terminal window:
$ make clean all
$ ./bin/bacserv 1234
In another terminal window use ifconfig to determine the network interface IP address that bacserv is using:
ifconfig
Use that address (likely from eth0) to configure the BBMD and Foreign Device environment variables:
./bin/bvlc.sh 192.168.0.42
bvlc.sh script configures environment variables to use BACnet/IP port 47809 for any subsequent BACnet tools run from that shell, and enables the BBMD Foreign Device Registration.
Perform a device discovery:
./bin/bacwi -1
Read all the required properties from the Device 1234 and display their values:
./bin/bacepics -v 1234
Read the Object_Identifier property from the Device 1234:
./bin/bacrp 1234 8 1234 75
Write 100.0 (REAL=4 datatype) to Device 1234 Analog Output (1) One (1) at priority 16 with no index (-1).
./bin/bacwp 1234 1 1 85 16 -1 4 100.0
Each tool has help:
./bin/bacrp --help
Source Code
The source code and makefiles for the bacnet-tools is included in the BACnet Protocol Stack library and can be found at: http://bacnet.sourceforge.net/
The bacnet-tools source is located in bacnet-stack/apps/project where:
- bacarf - bacnet-stack/apps/readfile
- bacawf - bacnet-stack/apps/writefile
- bacdcc - bacnet-stack/apps/dcc
- bacepics - bacnet-stack/apps/epics
- bacrd - bacnet-stack/apps/reinit
- bacrp - bacnet-stack/apps/readprop
- bacrpm - bacnet-stack/apps/readpropm
- bacscov - bacnet-stack/apps/scov
- bacts - bacnet-stack/apps/timesync
- bacucov - bacnet-stack/apps/ucov
- bacupt - bacnet-stack/apps/uptransfer
- bacwh - bacnet-stack/apps/whohas
- bacwi - bacnet-stack/apps/whois
- bacwp - bacnet-stack/apps/writeprop
- bacserv - bacnet-stack/apps/server etc.
bacnet write mlutiple
Usage: bacwpm device-instance object-type object-instance property[index] priority tag value [ property[index] priority tag value] [–version][–help] Write one or more properties to one or more objects in a BACnet device.
device-instance: BACnet Device Object Instance number that you are trying to communicate to. This number will be used to try and bind with the device using Who-Is and I-Am services. For example, if you were writing Device Object 123, the device-instance would be 123.
object-type: The object type is object that you are reading. It can be defined either as the object-type name string as defined in the BACnet specification, or as the integer value of the enumeration BACNET_OBJECT_TYPE in bacenum.h. For example if you were reading Analog Output 2, the object-type would be analog-output or 1.
object-instance: This is the object instance number of the object that you are writing. For example, if you were writing Analog Output 2, the object-instance would be 2.
property: The property is an integer value of the enumeration BACNET_PROPERTY_ID in bacenum.h. It is the property you are writing. For example, if you were writing the Present Value property, use 85 as the property.
priority: This parameter is used for setting the priority of the write. If Priority 0 is given, no priority is sent. The BACnet standard states that the value is written at the lowest priority (16) if the object property supports priorities when no priority is sent.
index: This integer parameter is the index number of an array. If the property is an array, individual elements can be written to if supported. If this parameter is -1, the index is ignored.
tag: Tag is the integer value of the enumeration BACNET_APPLICATION_TAG in bacenum.h. It is the data type of the value that you are writing. For example, if you were writing a REAL value, you would use a tag of 4. Context tags are created using two tags in a row. The context tag is preceded by a C. Ctag tag. C2 4 creates a context 2 tagged REAL.
value: The value is an ASCII representation of some type of data that you are writing. It is encoded using the tag information provided. For example, if you were writing a REAL value of 100.0, you would use 100.0 as the value.
Here is a brief overview of BACnet property and tags: Certain properties are expected to be written with certain application tags, so you probably need to know which ones to use with each property of each object. It is almost safe to say that given a property and an object and a table, the tag could be looked up automatically. There may be a few exceptions to this, such as the Any property type in the schedule object and the Present Value accepting REAL, BOOLEAN, NULL, etc. Perhaps it would be simpler for the demo to use this kind of table - but I also wanted to be able to do negative testing by passing the wrong tag and have the server return a reject message.
Example: If you want send a value of 100 to the Present-Value in Analog Output 44 and 45 of Device 123 at priority 16, send the following command:
bacwpm 123 1 44 85 16 4 100 1 45 85 16 4 100
bacnet write
bacwp device-instance object-type object-instance property priority index tag value [tag value…] device-instance: BACnet Device Object Instance number that you are trying to communicate to. This number will be used to try and bind with the device using Who-Is and I-Am services. For example, if you were writing to Device Object 123, the device-instance would be 123.
object-type: The object type is object that you are reading. It can be defined either as the object-type name string as defined in the BACnet specification, or as the integer value of the enumeration BACNET_OBJECT_TYPE in bacenum.h. For example if you were reading Analog Output 2, the object-type would be analog-output or 1.
object-instance: This is the object instance number of the object that you are writing to. For example, if you were writing to Analog Output 2, the object-instance would be 2.
property: The property of the object that you are reading. It can be defined either as the property name string as defined in the BACnet specification, or as an integer value of the enumeration BACNET_PROPERTY_ID in bacenum.h. For example, if you were reading the Present Value property, use present-value or 85 as the property.
priority: This parameter is used for setting the priority of the write. If Priority 0 is given, no priority is sent. The BACnet standard states that the value is written at the lowest priority (16) if the object property supports priorities when no priority is sent.
index: This integer parameter is the index number of an array. If the property is an array, individual elements can be written to if supported. If this parameter is -1, the index is ignored.
tag: Tag is the integer value of the enumeration BACNET_APPLICATION_TAG in bacenum.h. It is the data type of the value that you are writing. For example, if you were writing a REAL value, you would use a tag of 4. Context tags are created using two tags in a row. The context tag is preceded by a C, and followed by the application tag. Ctag atag. C2 4 creates a context 2 tagged REAL.
value: The value is an ASCII representation of some type of data that you are writing. It is encoded using the tag information provided. For example, if you were writing a REAL value of 100.0, you would use 100.0 as the value.
Example: If you want send a value of 100 to the Present-Value in Analog Output 0 of Device 123 at priority 16, send the one of following commands:
# bacwp 123 analog-output 0 present-value 16 -1 4 100
bacwp 123 1 0 85 16 -1 4 100
To send a relinquish command to the same object:
# bacwp 123 analog-output 0 present-value 16 -1 0 0
bacwp 123 1 0 85 16 -1 0 0