updated the FAQ document from the website.
This commit is contained in:
+228
-40
@@ -1,79 +1,267 @@
|
||||
FAQ - Frequently Asked Questions about the BACnet Stack
|
||||
|
||||
Q: Do you know the typical footprint of the stack (MS/TP use)?
|
||||
Q-1: Do you know the typical footprint of the stack (MS/TP use)?
|
||||
|
||||
A: 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 bytes of the code space.
|
||||
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: The homepage used to say that the MS/TP code does not work. Still true?
|
||||
Q-2: The homepage used to say that the MS/TP code does not work. Still
|
||||
true?
|
||||
|
||||
A: 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.
|
||||
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: Does the stack have some specific requirements regarding the hardware (e.g. non-volatile memory, 32-bit CPU, ...)?
|
||||
Q-3: Does the stack have some specific requirements regarding the
|
||||
hardware (e.g. non-volatile memory, 32-bit CPU, ...)?
|
||||
|
||||
A: 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.
|
||||
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: Does the stack have some specific requirements regarding OS? What OS features are used (threads, timers, semaphors, events, mutexes...)?
|
||||
Q-4: Does the stack have some specific requirements regarding OS? What
|
||||
OS features are used (threads, timers, semaphors, events, mutexes...)?
|
||||
|
||||
A: 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.
|
||||
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.
|
||||
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: What is the difference between the two datalink layers BACnet/IP and BACnet Ethernet? In BACnet/IP, is the MAC address needed?
|
||||
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: 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.
|
||||
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.
|
||||
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: What do I need to do to learn about BACnet? Can this project help?
|
||||
Q-6: What do I need to do to learn about BACnet? Can this project
|
||||
help?
|
||||
|
||||
A: 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!
|
||||
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: 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?
|
||||
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: 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.
|
||||
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: 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?
|
||||
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: You describe what the BACnet committee just published recently: Addendum 135-2004c, BACnet Web Services, which has been approved by ASHRAE and ANSI.
|
||||
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.
|
||||
I don't have web services implemented in the BACnet stack at
|
||||
SourceForge, but you could certainly use the stack do so.
|
||||
|
||||
Q: How do I create the required objects (analog inputs, analog outputs, binary inputs, binary outputs) to support the hardware on my board?
|
||||
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: 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.
|
||||
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:
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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: Since each Device object must have an object identifier that is unique internetwork-wide, how is this ID determined?
|
||||
Q-10: Since each Device object must have an object identifier that is
|
||||
unique internetwork-wide, how is this ID determined?
|
||||
|
||||
A: 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.
|
||||
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.
|
||||
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: 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?
|
||||
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: 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.
|
||||
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.
|
||||
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: 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".
|
||||
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: 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.
|
||||
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: 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?
|
||||
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: 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.
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user