FAQ - Frequently Asked Questions about the BACnet Stack

Q-1: Do you know the typical footprint of the stack (MS/TP use)?

A-1: It fits on a PIC18F6720 (128K bytes flash 3840 bytes RAM) and
there is lots of room for the application. In one device with 8 Binary
Value objects, 8 Binary Input objects, 1 Analog Input object, and
supporting ReadProperty, WriteProperty, DeviceCommunicationControl,
TimeSync, ReinitializeDevice, Who-Is, I-Am services, the BACnet stack
used about 32K words of the code space.

Q-2: The homepage used to say that the MS/TP code does not work. Still
true?

A-2: MS/TP works correctly as of the 0.2.6 release. I spent a several
days correcting it while working on the RTOS-32 port, and then a full
day fine-tuning it while working on the PIC18F6720 that I used at the
BACnet International plugfest. The only issue at the plugfest was that
our unit didn't work at 76800, and that was probably due to me setting
the UART on the PIC incorrectly.

Q-3: Does the stack have some specific requirements regarding the
hardware (e.g. non-volatile memory, 32-bit CPU, ...)?

A-3: Not really. The specific stuff is in the ports/ directory, and
that is expected to be modified by the end user if necessary. Big
Endian and Little Endian used to be automatic, but that took up too
much code space, so there is a BIG_ENDIAN define in the makefile. Most
of the variables are defined using the ANSI C-99 uint8_t, uint16_t,
uint32_t, int8_t, int16_t, int32_t from stdint.h, along with bool from
stdbool.h. Most of the APDU size returns are int.

Q-4: Does the stack have some specific requirements regarding OS? What
OS features are used (threads, timers, semaphors, events, mutexes...)?

A-4: No, I did not use any OS features (except for the port/rtos32/
which uses some tasks). Since my target was embedded, I kept every
thing single-threaded (but multithread safe except where noted) to
keep it easy to follow and easy to implement in a microcontroller just
running a main() loop. I expect that when I finish the port to
RTOS-32, I will have some OS specific stuff, but that will end up in
the ports/rtos32/ directory.

I started to port the MS/TP state machine to RTOS-32 and it is
currently a single task (other than a timer task). However, it really
needs to have some queues and become multithreaded for effeciency.
Since the 0.2.6 release, I moved the MS/TP files (mstp.c, mstp.h,
dlmstp.c, dlmstp.h, rs485.c, rs485.h) into the ports/ directory so
that the code can be modified to suit the port.

Q-5: What is the difference between the two datalink layers BACnet/IP
and BACnet Ethernet? In BACnet/IP, is the MAC address needed?

A-5: The BACnet/IP uses the BACnet Virtual Link Control (BVLC) for
networking using UDP/IP. The IPv4 address (x.x.x.x) and the port
number (0xBAC0) is stored as the MAC address. IPv6 would store more
bytes, and devices should be able to store them. See Annex J or bip.c
in the BACnet stack.

BACnet Ethernet uses the Ethernet MAC address, and communicates using
the IEEE 802.2/802.3 (see ANSI/ASHRAE 135-2004-7 Data Link/Physical
Layers: ISO 8802-3 ("Ethernet") LAN). See ethernet.c in the BACnet
stack.

Q-6: What do I need to do to learn about BACnet? Can this project
help?

A-6: Open source projects are great since they allow you to look over
the internals of a program or library. However, sometimes you just
want to see something work. I created about a dozen example
applications for testing. One of the applications is
demo/server/bacserv that acts like a BACnet server device. Run it on
one PC or hardware platform, and then use the other example
applications on another PC to interact with it. Monitor the BACnet
network activity with the WireShark protocol analyzer. Modify the
example applications - "Take chances, make mistakes, get messy." Have
fun! Join the BACnet developers mailing list and ask lots of questions
so others can learn and help too!

Q-7: The stack is working fine with demo/server/bacserv. But in the
WireShark protocol analyzer, I am able to see only 'Who-Is' and 'I
-Am' query/responses. The ReadProperty query/responses are not there
in the capture viewer. Why?

A-7: If you are only able to see broadcast messages like Who-Is and
I-Am, then you are probably networking using an Ethernet switch
(bridge) to connect WireShark to the devices. The Ethernet switch
(bridge) actually routes the unicast messages between ports and does
not send them to all ports (unless configured to do so). If you use an
Ethernet Hub or run WireShark from one of the devices under test, you
will then see the ReadProperty messages.

Q-8: I intend to write a little program to implement the comunication
between Bacnet devices and tcp/ip devices, but not use PAD and
BACnet/IP. Can I do that in a standard way?

A-8: You describe what the BACnet committee just published recently:
Addendum 135-2004c, BACnet Web Services, which has been approved by
ASHRAE and ANSI.

I don't have web services implemented in the BACnet stack at
SourceForge, but you could certainly use the stack do so.

Q-9: How do I create the required objects (analog inputs, analog
outputs, binary inputs, binary outputs) to support the hardware on my
board?

A-9: See the example application demo/server for an example of a
server application with objects included. The simple answer is that
they exist in the Device object in the Object_List property. Every
BACnet device is required to have a Device Object, and one of the
required properties is the Object_List property.

The example objects are in demo/object and those that are included in
the device are in demo/object/device.c as defined in 5 locations in
the file. For each object type:

       1. #include the header file for the object
       2. Device_Object_List_Count() needs to include a call to a
count function from the object type.
       3. Device_Object_List_Identifier() needs to include some code
to get the object instance for each object.
       4. Device_Valid_Object_Id() needs to get the object name for
each object.
       5. PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED needs to set a bit for
each object type supported.

Additionally, for each service that interacts with objects, you will
need to include handling for that object. See demo/handler/h_rp.c to
see how the different objects are accessed for the ReadProperty
service. See demo/handler/h_wp.c to see how the different objects are
accessed for the WriteProperty service. If those are the only services
that you are going to use, then most of the work has been done other
than selecting which object types you are going to support.

As for how many of what object, see the individual object files for
examples of how that works (see demo/object directory). Also note that
there are optional properties of some objects that may or may not have
an example included in this demo code. For example, a Binary Value
object optionally includes a Priority_Array. There is an example in
the demo/object that includes a Priority_Array, and an example in
ports/pic18f6720 that does not have the Priority_Array.

You can read/write to the properties using demo/readprop and
demo/writeprop example client applications that run under Windows or
Linux command line.

Q-10: Since each Device object must have an object identifier that is
unique internetwork-wide, how is this ID determined?

A-10: Device object instance number is normally configured on site
after the device is installed. Therefore, the Device object instance
number should be configurable between 0 and 4194303 inclusive (see
bacdef.h for BACNET_MAX_INSTANCE). If your hardware does not have any
user interface, you can have the device default to 4194303 and
implement WriteProperty service to the Object_Identifier of the Device
object. You could also have some other method for configuring the
Device Object instance number such as an RS-232 terminal interface or
HTTP screen configuration like a home internet router.

Note that 4194303 is known as "unconfigured" and is not really a valid
device instance number. Also, all devices are required to respond with
their own Device object instance number when 4194303 is requested.

Q-11: For the objects supported by the device, they are required to be
unique within the BACnet device that maintains them. Can I start with
an object instance number of 0 or 1 and increment accordingly for each
new object created within the device?

A-11: For each object type, you can create any object instance numbers
between 0 and 4194302 inclusive. How you choose to number them is up
to you.

In the example object in demo/object/ I numbered them sequentially
starting at 0. If you do choose to use some other numbering scheme, be
sure to update the Index_To_Instance(), Valid_Instance(), Count(), and
Name() functions of each object type to correctly handle your
numbering scheme.

Q-12: For the object names, do you really use AV-## or ANALOG VALUE #
in your system? All of our AV values have unique names like
"ACTIVE_ALARM", "REVISION", "DUCT_STATIC".

A-12: As long as your names are unique in your device (i.e. no
duplicate names) you can use your names. In the demo objects, I just
use "AV-1" or "ANALOG VALUE 1" as the Object_Name where 1 is the
object instance number. Update the Name() function for each object
type if you change from the default names.

Q-13: I need to have about 100 Analog Value objects and 100 Binary
Value objects in my device. When I try to define over 15 objects I get
a memory error from the PIC compiler. What is the problem?

A-13: If you are using the unmodified Analog Value or Binary Value
objects from demo/objects, they include a priority array. That means
that each object has 16 Present_Values stored for each object, plus an
Out_Of_Service status. Each object would consume about 17 bytes.
15*17=255 bytes. Limit for udata = 255 bytes on the PIC using the
Microchip compiler.

Output and value objects are not required to have Out_Of_Service
writable. Value objects are not required to have a priority array. If
you need or want to have priority arrays for your objects, then you
might consider storing the Binary Value object Present_Value in some
smaller form (currently it is stored as enumeration which consumes a
byte on a PIC). There are Binary Value and Analog Value object
examples that do not include a priority array in the ports/pic18f6720/
directory.

Q-14: What do I have to do to reduce the size of the firmware made
from this BACnet stack?

A-14: Here are the things that you can do to shrink the firmware size:

       1. For MS/TP, change the state machine to use a fixed memory
structure rather than a pointer to a structure. Some microcontroller
compilers generate more code when having to dereference the structure.
This limits you to a single MS/TP datalink.
       2. Remove unused services by
              * remove the service C file from the makefile
              * remove the function call to setup the service
              * remove the service handler
       3. Remove unnecessary objects by:
              * Remove the demo/object C file from the makefile
              * remove function calls to the demo/object C file.
              * Change the number of objects that you have.
              * Only a Device object is required.
              * Update the Device object
PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED
       4. Remove unused function calls by:
              * #if 0 and #endif around the unused functions
(especially in bacdcode.c)
              * Compile and Link. If the linker fails, then that
function was needed.
              * Some compilers and linkers have garbage collection
              for unused code/functions. GCC has this feature:
              http://gcc.gnu.org/ml/gcc-help/2003-08/msg00128.html

Q-15: I have downloaded the BACnet stack but can't get demo/server to
work. I am using a single computer. In one console window I run
demo/server/bacserv. In another console window I run demo/whois/bacwi.
When I capture packets with WireShark, I see the I-Am broadcast packet
being sent by demo/server/bacserv when it starts. I also see the
Who-Is broadcast packet sent by demo/whois/bacwi. But
demo/server/bacserv never receives any message. How do I make it work?

A-15: This is a common issue with BACnet/IP. The server application
binds to the BACnet/IP UDP port 47808 on that computer, and therefore,
the client application is unable to receive broadcast messages on port
47808 since those packets are only going to the server application.

The correct solution is to use BVLC (BACnet Virtual Link Control)
where the client applications use BACnet Foreign Device Registration,
and some application (probably the server) runs a BBMD (BACnet
Broadcast Management Device). Unfortunately, I don't have bvlc.c
complete at this time, so that won't work for you today.

You can do one of the following:

   1. Use QEMU or Bochs or VMWare or some other virtual machine to
simulate another computer, and run server or client on a virtual
computer.
   2. Finish the bvlc.c code. Add BBMD support in the demo/server
example. Add Foreign device registration in all the client examples
when they are built with BACDL_BIP enabled.
   3. Write npdu router code to route from BACnet/IP to another
datalink layer. Make server application on one datalink layer and make
client applications on another datalink layer.
   4. Add external BACnet router or BACnet devices. Run a BACnet
demo/server on another PC.

Q-16: My Linux computer doesn't use eth0 for for the BACnet connection.
My Windows computer has more than one network connnection.  How can I
choose the interface to use for the demo applications?

A-16: Set the environment variable BACNET_IFACE.  For Windows, set
BACNET_IFACE=169.254.119.240 or whatever the address of the interface
returned by ipconfig command.  For Linux, use BACNET_IFACE=eth0 or whatever
the name of the interface returned by the ifconfig command.
Setting the environment variable under Windows can be done on the command
line:
> set BACNET_IFACE=169.254.119.240
Setting the environment variable under Linux can be done from the command
line:
$ BACNET_IFACE=ath0
$ export BACNET_IFACE
