Release BACnet Protocol Stack 0.3.0

This commit is contained in:
skarg
2007-02-23 13:19:57 +00:00
parent 6c5b409dcf
commit 63e18a0f1f
315 changed files with 57198 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
BACnet Stack
Developer Build
This BACnet Stack is designed as a library for an embedded product.
However, there are a number of example applications in the demo/ directory
that show how it can be used for client and server applications.
The demos can be built using makefiles in the root directory, or by
using individual makefiles in the demo directories.
+103
View File
@@ -0,0 +1,103 @@
This BACnet stack is service driven. It handles the services (BACnet requests
like WhoIs, I-Am, ReadProperty, etc) to/from the network layer to functions that
handle the application layer. There are a bunch of functions that facilitate
encoding and decoding to/from the network message data to/from something
meaningful in the program.
A BACnet device is supposed to support, at a minimum, ReadProperty service
(server) and a single Device Object. This even applies to a BACnet client on a
PC that is used for reading other BACnet devices.
There are a number of core files that you will need. Services such as
ReadProperty, I-Am, and Reject are consided core files. The following BACnet
services (messages) are provided by this BACnet stack files:
* abort.c - BACnet Abort service encode/decode
* bacerror.c - BACnet Error service encode/decode
* reject.c - BACnet Reject service encode/decode
* rp.c - BACnet ReadProperty service encode/decode
* arf.c - AtomicReadFile service encode/decode
* awf.c - AtomicWriteFile service encode/decode
* rpm.c - ReadPropertyMultiple service encode/decode
* iam.c - I-Am service encode/decode
* whois.c - WhoIs service encode/decode
* wp.c - WriteProperty service encode/decode
* dcc.c - DeviceCommunicationControl service encode/decode
* ihave.c - I-Have service encode/decode
* rd.c - ReinitializedDevice service encode/decode
* timesync.c - TimeSynchronization service encode/decode
* whohas.c - WhoHas service encode/decode
Adding additional services is a matter of adding the encoding and decoding for
the service into/from meaningful data, and I like to add unit testing, a demo
handler and send function, as well as a demo command line example.
The BACnet stack also includes files for handling client functionality, which
requires Confirmed messages, and utilizes something called binding. Binding is a
way of acquiring a Device Object Instance's MAC address by sending a broadcast
Who-Is to that Device Object and waiting for the I-Am from that Device Object.
When the I-Am arrives, the MAC address can be stored and used to send unicast
messages to that Device Object and its member objects or properties. Here are
the files that handle BACnet binding:
* address.c - This module is used to handle the address binding that occurs
in BACnet. A device id is bound to a MAC address. The normal method is using
Who-Is, and binding with the data from I-Am. This is needed for client
functionality.
* tsm.c - Transaction State Machine handles resending messages if a timeout
occurs, and is needed for client functionality. The transaction state machine is
used for Confirmed messages and segmentation. For confirmed messages, it
automatically (via tsm_timer_milliseconds) handles the retries and the timeout.
It uses the InvokeID as the unique key (although officially it should be the
combination of InvokeID, DeviceID, and service). So if you tried to send a
confirmed request to a device that was taken offline, you would see the retry go
out after every apdu_timeout until apdu retries had completed. Then the
transaction would self-delete (free). The stack as it is written (and most
stacks are written this way) has a limited amount of transactions, and if you
are sending alot of confirmed data, it can be a bottleneck if they are not freed
in a timely manner.
This BACnet stack includes a number of example objects. The reason that they are
examples is because your device and its objects and their properties will
undoubtedly be unique to your product. The example objects in this BACnet stack
are the same and contiguous for each object represented - but this is not
required. This stack does not include an example of every type of BACnet object
or property - but have no fear! Adding a new object type is mostly just a matter
of adding all the data encoding/decoding for that object for each service and
property supported. When a new object is added, it must also add some API hooks
in the Device Object, since the Device Object contains an object list. The
example object files in the BACnet stack include:
* demo/object/ai.c - analog input object demo
* demo/object/ao.c - analog output object demo
* demo/object/bacfile.c - File object demo
* demo/object/device.c - device object demo
* demo/object/bi.c - binary input object demo
* demo/object/bo.c - binary output object demo
* demo/object/lsp.c - life safety point demo
The BACnet stack includes a number of core files that handle the service packets
that come in from the datalink layer. The core files include:
* apdu.c - handles dispatching the services to the proper handlers
* bacdcode.c - primitive BACnet datatype encoding and decoding
* bacstr.c - BACnet string encoding and decoding
* bigend.c - determines if CPU is bigendian
* datalink.c - generic API for all datalink layers
* npdu.c - handles dispatching of the network message to the apdu
dispatcher. It would be where routing is handled if the stack supported more
than one physical layer.
The DataLink Layer controls orderly access to the physical medium. The following
files are used for the datalink handling in this BACnet stack:
* bip.c - BACnet/IP functionality - depends on bip_init.c in port/xx
* dllmstp.h - MS/TP datalink layer (see also dlmstp.c,mstp.c,crc.c)
* arcnet.h - ARCNET datalink layer functionality API
* ethernet.h - BACnet Ethernet datalink layer functionality API
There are several demonstration applications in the demo directory, along with
several demonstation objects and handlers. All the demos accept command line
options and have been tested under Win32 and Linux. There is a makefile in the
respective demo directory for Linux and for Borland C++ compilers, and a master
makefile at the root level (Makefile=Linux, makefile.b32=Borland).
+76
View File
@@ -0,0 +1,76 @@
BACnet Stack - SourceForge.net
Build for Visual C++ 6.0
When building the BACnet stack using Visual C++ compiler,
there are some settings that are important.
Q. MSVC refuses to open bacnet.dsw and bacnet.dsp.
A. bacnet.dsw and bacnet.dsp are text files that were retrieved
from CVS on a unix client and are now in unix text file format since
they end with a "\r\n" rather than "\n". Use the unix2dos commandline
tool to convert them back to dos:
unix2dos bacnet.dsw
unix2dos bacnet.dsp
Q. error LNK2001: unresolved external symbol _WinMain@16
A. The demo ports/win32/main.c was designed as a Win32 Console
Application. If you want to change it to a Windows GUI application,
you will have to add all the Windows GUI code, including WinMain().
I recommend that you use a framework, such as WxWidgets/WxWindows,
but this has not been done yet.
Q. error C1083: Cannot open include file: 'stdint.h': No such file
A. The BACnet stack uses some header files, and Visual C++ needs to know
where they are:
1. Select "Project" menu
2. Select "Settings..."
3. Select the "C/C++" tab (3rd Tab)
4. Select the Category: Preprocessor
5. You can see the "Additional include directories:" box
6. Type the path to stdint.h in that edit box (using a comma if necessary)
7. Type the path to bacdcode.h in that edit box (using a comma if necessary)
In my system, the paths look like:
c:\code\bacnet-stack\,c:\code\bacnet-stack\ports\win32\,
c:\code\bacnet-stack\demo\handler\,c:\code\bacnet-stack\demo\object\
8. Press OK
9. Compile the project again...
Q. error C2065: 'MAX_MPDU' : undeclared identifier
A. The BACnet stack uses a preprocessor define to configure
its datalink layer. In Visual C++, add a Preprocessor Definition by:
1. Select "Project" menu
2. Select "Settings..."
3. Select the "C/C++" tab (3rd Tab)
4. Select the Category: General
5. You can see the "Preprocessor Definitions:" box
6. Type BACDL_BIP=1 in that edit box (using a comma if necessary)
7. Press OK
8. Compile the entire project again...
Q. error LNK2001: unresolved external symbol __imp__closesocket@4
A. Visual C++ needs to have the Winsock library to be happy:
1. Select "Project" menu
2. Select "Settings..."
3. Select the "Link" tab (4th Tab)
4. You can see "Object/library modules:" edit box
5. Type Wsock32.LIB in that edit box
6. Press OK
7. Compile the entire project again...
Q. error C2061: in file tsm.c
A. The BACnet stack uses a preprocessor define to configure
client functionality in the Transaction State Machine (TSM).
In Visual C++, add a Preprocessor Definition by:
1. Select "Project" menu
2. Select "Settings..."
3. Select the "C/C++" tab (3rd Tab)
4. Select the Category: General
5. You can see the "Preprocessor Definitions:" box
6. Type TSM_ENABLED=1 in that edit box (using a comma if necessary)
7. Press OK
8. Compile the entire project again...
+67
View File
@@ -0,0 +1,67 @@
SourceForge Release Checklist for the BACnet Embedded Stack Project
written by Steve Karg (using a similar doc by Kim Gräsman as a guide)
Verify that the test build is clean. Test code with clean directory.
Get a clean build (no warnings or errors).
The program must be functional (it works).
Clean up the object files and binaries to prepare for tar
$ make clean
Make the source code look the same
$ indent -kr -nut -nlp *.c *.h
Verify that the code compiles and runs the demos without error or
warnings:
$ make all
$ demo/server 123 (etc)
Verify that the unit tests compile and pass:
$ ./unittest.sh
$ cat test.log | grep Failed
Commit any changes to subversion.
$ svn commit
$ svn update
Create the change log
$ svn log --xml --verbose | xsltproc svn2cl.xsl - > ChangeLog
Set a tag on the "bacnet-stack" module called "bacnet-stack-0-0-0"
$ svn copy https://svn.sourceforge.net/svnroot/bacnet/current https://svn.sourceforge.net/svnroot/bacnet/tags/bacnet-stack-0-0-0
Get a clean version out of subversion that doesn't have subversion in it.
$ svn export https://svn.sourceforge.net/svnroot/bacnet/trunk/bacnet-stack bacnet-stack
tar and gzip the clean directory from one directory up.
$ tar -cvvzf bacnet-stack-0.0.0.tgz bacnet-stack/
Put the new release up on SourceForge
Connect to ftp://upload.sourceforge.net/ as anonymous
Upload the tarball to the incoming directory.
Go to http://sourceforge.net/projects/bacnet/
Admin -> File Releases
Add Release
Release Name "bacnet-stack-0.0.0"
Set status to Hidden (for now).
Create a change log (use svn log)
[Submit/Refresh]
Attach the tarball that was uploaded (should be listed)
[Add Files and/or Refresh View]
Set file metadata
Processor: Platform Independent
Release Date: Today's date
File Type: Source .gz
[Update/Refresh]
Activate Release
Set status to Active
[Submit/Refresh]
[Send Notice]
Update the website (if necessary)
Add release notes under What's New on SourceForge.
The release notes should include project details
for someone unfamiliar with the project or BACnet.
+31
View File
@@ -0,0 +1,31 @@
SLOC Directory SLOC-by-Language (Sorted)
12610 top_dir ansic=12435,sh=175
8317 ports ansic=8317
7762 demo ansic=7762
187 test ansic=187
0 doc (none)
0 license (none)
0 utils (none)
Totals grouped by language (dominant language first):
ansic: 28701 (99.39%)
sh: 175 (0.61%)
Total Physical Source Lines of Code (SLOC) = 28,876
Development Effort Estimate, Person-Years (Person-Months) = 6.83 (81.99)
(Basic COCOMO model, Person-Months = 2.4 * (KSLOC**1.05))
Schedule Estimate, Years (Months) = 1.11 (13.34)
(Basic COCOMO model, Months = 2.5 * (person-months**0.38))
Estimated Average Number of Developers (Effort/Schedule) = 6.15
Total Estimated Cost to Develop = $ 923,008
(average salary = $56,286/year, overhead = 2.40).
SLOCCount, Copyright (C) 2001-2004 David A. Wheeler
SLOCCount is Open Source Software/Free Software, licensed under the GNU GPL.
SLOCCount comes with ABSOLUTELY NO WARRANTY, and you are welcome to
redistribute it under certain conditions as specified by the GNU GPL license;
see the documentation for details.
Please credit this data as "generated using David A. Wheeler's 'SLOCCount'."
+221
View File
@@ -0,0 +1,221 @@
This software runs on many platforms, and can be compiled with a number of
different compilers; here are some rules for writing code that will work
on multiple platforms.
Regarding tabs, indenting, and code style: we run "indent -kr -nut -nlp"
on the code prior to releasing it. This ensures a standard look and feel
to the code regardless of the authors preferred style. You may certainly
adjust the code to your preferred style using the indent tool. We use the
script indent.sh to adjust all the .c and .h files.
Don't use C++-style comments (comments beginning with "//" and running
to the end of the line) for modules that are written in C. The module
may run through C rather than C++ compilers, and not all C compilers
support C++-style comments (GCC does, but IBM's C compiler for AIX, for
example, doesn't do so by default). Note: there is an application
called usr/bin/ccmtcnvt in the liwc package that converts the C++
comments to C comments. There is a script utilizing ccmtcnvt called
comment.sh created for this project that searches all the c and h files
for C++ headers and converts them.
Don't initialize variables in their declaration with non-constant
values. Not all compilers support this. E.g. don't use
uint32_t i = somearray[2];
use
uint32_t i;
i = somearray[2];
instead.
Don't use zero-length arrays; not all compilers support them. If an
array would have no members, just leave it out.
Don't declare variables in the middle of executable code; not all C
compilers support that. Variables should be declared at the beginning
of a function or compound statement, or outside a function
Don't use "inline"; not all compilers support it.
Use the C99 stdint.h and stdbool.h definitions for declaring variables
when needed. If they are not defined for your compiler, put those files
into the ports directory for your compiler with the proper definitions.
Sometimes scalable code should just use an int or unsigned declaration.
8-bit unsigned = uint8_t
8-bit signed = int8_t
16-bit unsigned = uint16_t
16-bit signed = int16_t
32-bit unsigned = uint32_t
32-bit signed = int32_t
boolean = bool
Don't use "long" to mean "signed 32-bit integer", and don't use
"unsigned long" to mean "unsigned 32-bit integer"; "long"s are 64 bits
long on many platforms. Use "int32_t" for signed 32-bit integers and use
"uint32_t" for unsigned 32-bit integers.
Don't use "long" to mean "signed 64-bit integer" and don't use "unsigned
long" to mean "unsigned 64-bit integer"; "long"s are 32 bits long on
many other platforms. Don't use "long long" or "unsigned long long",
either, as not all platforms support them; use "int64_t" or "uint64_t",
which need to be defined as the appropriate types for 64-bit signed and
unsigned integers.
Don't use a label without a statement following it. For example,
something such as
if (...) {
...
done:
}
will not work with all compilers - you have to do
if (...) {
...
done:
;
}
with some statements, even if it's a null statement, after the label.
Don't use "bzero()", "bcopy()", or "bcmp()"; instead, use the ANSI C
routines
"memset()" (with zero as the second argument, so that it sets
all the bytes to zero);
"memcpy()" or "memmove()" (note that the first and second
arguments to "memcpy()" are in the reverse order to the
arguments to "bcopy()"; note also that "bcopy()" is typically
guaranteed to work on overlapping memory regions, while
"memcpy()" isn't, so if you may be copying from one region to a
region that overlaps it, use "memmove()", not "memcpy()" - but
"memcpy()" might be faster as a result of not guaranteeing
correct operation on overlapping memory regions);
and "memcmp()" (note that "memcmp()" returns 0, 1, or -1, doing
an ordered comparison, rather than just returning 0 for "equal"
and 1 for "not equal", as "bcmp()" does).
Not all platforms necessarily have "bzero()"/"bcopy()"/"bcmp()", and
those that do might not declare them in the header file on which they're
declared on your platform.
Don't use "index()" or "rindex()"; instead, use the ANSI C equivalents,
"strchr()" and "strrchr()". Not all platforms necessarily have
"index()" or "rindex()", and those that do might not declare them in the
header file on which they're declared on your platform.
Don't fetch data from packets by getting a pointer to data in the
packet, casting that pointer to a pointer to a structure,
and dereferencing that pointer. That pointer won't necessarily be aligned
on the proper boundary, which can cause crashes on some platforms (even
if it doesn't crash on an x86-based PC). This means that you cannot
safely cast it to any data type other than a pointer to "char",
"unsigned char", "uint8_t", or other one-byte data types. You cannot,
for example, safely cast it to a pointer to a structure, and then access
the structure members directly; on some systems, unaligned accesses to
integral data types larger than 1 byte, and floating-point data types,
cause a trap, which will, at best, result in the OS slowly performing an
unaligned access for you, and will, on at least some platforms, cause
the program to be terminated.
The data in a packet is not necessarily in the byte order of
the machine on which this software is running. Make use of
big_endian() which returns non-zero on big_endian machines.
Use "ntohs()", "ntohl()", "htons()", or "htonl()" only in the ports
directories since the header files required to define or declare
them differ between platforms. There are some common functions in
the bacdcode library for converting to and from long and short.
Don't put a comma after the last element of an enum - some compilers may
either warn about it (producing extra noise) or refuse to accept it.
When opening a file with "fopen()", "freopen()", or "fdopen()", if the
file contains ASCII text, use "r", "w", "a", and so on as the open mode
- but if it contains binary data, use "rb", "wb", and so on. On
Windows, if a file is opened in a text mode, writing a byte with the
value of octal 12 (newline) to the file causes two bytes, one with the
value octal 15 (carriage return) and one with the value octal 12, to be
written to the file, and causes bytes with the value octal 15 to be
discarded when reading the file (to translate between C's UNIX-style
lines that end with newline and Windows' DEC-style lines that end with
carriage return/line feed).
In addition, that also means that when opening or creating a binary
file, you must use "open()" (with O_CREAT and possibly O_TRUNC if the
file is to be created if it doesn't exist), and OR in the O_BINARY flag.
That flag is not present on most, if not all, UNIX systems, so you must
also do
#ifndef O_BINARY
#define O_BINARY 0
#endif
to properly define it for UNIX (it's not necessary on UNIX).
Don't use forward declarations of static arrays without a specified size
in a fashion such as this:
static const value_string foo_vals[];
...
static const value_string foo_vals[] = {
{ 0, "Red" },
{ 1, "Green" },
{ 2, "Blue" },
{ 0, NULL }
};
as some compilers will reject the first of those statements. Instead,
initialize the array at the point at which it's first declared, so that
the size is known.
Don't put declarations in the middle of a block; put them before all
code. Not all compilers support declarations in the middle of code,
such as
int i;
i = foo();
int j;
For #define names and enum member names, prefix the names with a tag so
as to avoid collisions with other names - this might be more of an issue
on Windows, as it appears to #define names such as DELETE and
OPTIONAL.
Don't use "variadic macros", such as
#define DBG(format, args...) fprintf(stderr, format, ## args)
as not all C compilers support them. Use macros that take a fixed
number of arguments, such as
#define DBG0(format) fprintf(stderr, format)
#define DBG1(format, arg1) fprintf(stderr, format, arg1)
#define DBG2(format, arg1, arg2) fprintf(stderr, format, arg1, arg2)
...
or something such as
#define DBG(args) printf args
Instead of tmpnam(), use mkstemp(). tmpnam is insecure and should
not be used any more. Note: mkstemp does not accept NULL as a parameter.
Try to write code portably whenever possible, however; note that
there are some routines in the software that are platform-dependent
implementations. The platform independent API is declared in the
header file, and the dependent routine is placed in a ports directory.
Reference: The cross platform aspect of this coding standard is based
on the developer coding standard for Ethereal and has been modified
by Steve Karg for this project. Thank you, Ethereal!
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

+483
View File
@@ -0,0 +1,483 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=windows-1252">
<TITLE>BACnet stack - open source BACnet protocol stack</TITLE>
</HEAD>
<BODY LANG="en-US">
<h1>BACnet Stack</h1>
<h2>An open source BACnet protocol stack for embedded systems</h2>
<hr>
<h2>About this Project</h2>
<P><a href="http://sourceforge.net/projects/bacnet/">This BACnet protocol stack library</a>
provides a BACnet application layer, network layer and media access (MAC)
layer communications services for an embedded system.</p>
<P>BACnet - A Data Communication Protocol for Building
Automation and Control Networks - see <a
href="http://www.bacnet.org/">bacnet.org</a>. BACnet is a standard data
communication protocol for Building Automation and Control Networks. BACnet
is an open protocol, which means anyone can contribute to the standard, and
anyone may use it. The only caveat is that the BACnet standard document
itself is copyrighted by ASHRAE, and they sell the document to help defray
costs of developing and maintaining the standard (just like IEEE or ANSI or
ISO).</P>
<P>For software developers, the BACnet protocol is a standard way to send and
receive messages on the wire containing data that is understood by other
BACnet compliant devices. The BACnet standard defines a standard way to
communicate over a number of wires, known as Data Link/Physical Layers:
Ethernet, EIA-485, EIA-232, ARCNET, and LonTalk. The BACnet standard also
defines a standard way to communicate using UDP, IP and HTTP (Web
Services).</P>
There are other open source projects for BACnet:</p>
<ul>
<li><a href="http://vts.sourceforge.net/">VTS</a> - visual test shell for
Win32, used for Visually testing a BACnet implementation. It also includes
a detailed network sniffer for BACnet messages, and the ability to send
any BACnet services. The source code is in the public domain. </li>
<li><a href="http://www.wireshark.org/">Wireshark</a> - an open source,
cross platform protocol analyzer with BACnet support. The detailed BACnet
support in began in version 0.10.11 released on May 4, 2005 when Wireshark
was known as Ethereal.</li>
<li><a href="http://bacnet4linux.sourceforge.net/">BACnet4Linux</a> - a
LGPL BACnet application that requires Linux as the OS.</li>
<li><a href="http://bfr.sourceforge.net/">BACnet Firewall Router</a> -an
application that combines BACnet routing capability with traffic management
functions to carefully control access to building automation and control
networks.</li>
<li><a href="http://bacpypes.sourceforge.net/">BACpypes</a> - a
BACnet stack written in Python.</li>
</ul>
<p>There are also commercial BACnet protocol source code libraries for BACnet
that are designed for embedded use:</p>
<ul>
<li><a href="http://www.cimetrics.com">Cimetrics</a><font
size="-2"><sup>TM</sup></font> - has a source library
called BACstac/32 as part of their BACNet Protocol Stack SDK.</li>
<li><a href="http://www.polarsoft.biz">Polarsoft</a> - has a
protocol stack source library for embedded use called FreeRange<font
size="-2"><sup>TM</sup></font> and PolarSoft&#174; FreeRange VSB (Very
Small BACnet stack).</li>
<li><a href="http://www.scadaengine.com/">SCADA Engine</a> - The BACnet
Linux Server is a complete BACnet Device running on the linux platform.
The entire source code is available for custom applications and has been
written in ANSI C which has been succesfully ported to Unix,
VxWorks etc. </li>
</ul>
<h2>Licensing</h2>
<p>Our BACnet protocol stack implementation is specifically designed for the
embedded BACnet appliance, using a GPL with exception license (like <a
href="http://ecos.sourceware.org/">eCos</a>),
which means that any changes to the core code that are distributed are
made available, but the BACnet library can be linked to
proprietary code without it becoming GPL.
See the <a href="http://ecos.sourceware.org/license-overview.html">eCos license overview</a> for
easy to read details about this exception to the GPL.
The license does <i>not</i> require users to release the source code of any
<i>applications</i> that are developed with this BACnet stack.<p>
<p>The text of the GPL exception included in each source file is as
follows:</p>
<blockquote>
<p>"As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License."<p>
</blockquote>
<h2>The source code</h2>
<p>The source code is written in C for portability, and includes
unit tests (PC based unit tests) and example application code.
Since the code is designed to be
portable, it compiles with GCC as well as other compilers,
such as Borland C++, Visual C++, MinGW, or MicroChip C18.
The source code is also designed to be readable, understandable,
and most importantly, easy to use.</p>
<p>The BACnet protocol is an ASHRAE/ANSI/ISO standard, so this library
adheres to that standard. BACnet has no royalties or licensing restrictions,
and <a href="http://www.bacnet.org/VendorID/">registration for a BACnet
vendor ID</a> is free.</p>
<h2>What the code does</h2>
<p>The stack comes with unit tests and demo applications
that can be run under Linux, Win32, RTOS-32, or just about any embedded
microcontroller.</p>
<p>The unit tests can be run in a command shell on Linux using the
unittest.sh script, or using individual .mak files. They were tested under
<a href="http://www.debian.org/">Debian GNU/Linux</a> and <a href="http://www.ubuntu.com/">Ubuntu Linux</a>.</p>
<p>The BACnet stack was functionally tested
using <a href="http://vts.sourceforge.net/">VTS (Visual Test Shell)</a>,
another project hosted on SourceForge, as well as various BACnet controllers,
BACnet workstations, and through BACnet routers.<p>
<p>Using a master Makefile in the project root directory, a dozen
demo applications can be created that run under Linux or Win32.
Linux supports BACnet Ethernet, BACnet/IP, or ARCNET data link layer
for communication, and BACnet/IP is supported under Win32. BACnet Ethernet
can also be used under Win32 with the <a href="http://www.winpcap.org/">WinPcap library</a>.
Root priveleges are required to run the Ethernet or ARCNET interfaces
on Linux, but not needed to run BACnet/IP.</p>
<code>
$ make clean all<br>
$ demo/server/bacsrv 123<br>
BACnet Server Demo - Device #123<br>
<br>
$ demo/readprop/bacrp<br>
bacrp device-instance object-type object-instance property [index]<br>
<br>
$ demo/writeprop/bacwp<br>
bacwp device-instance object-type object-instance property tag value [priority] [index]<br>
<br>
$ demo/readfile/bacarf<br>
bacarf device-instance file-instance local-name<br>
<br>
$ demo/writefile/bacawf<br>
bacawf device-instance file-instance local-name<br>
<br>
$ demo/reinit/bacrd<br>
Usage: bacrd device-instance state [password]<br>
Send BACnet ReinitializeDevice service to device.<br>
<br>
$ demo/whohas/bacwh<br>
Usage: bacwh object-type object-instance | object-name<br>
Send BACnet WhoHas request to devices, and wait for responses.<br>
<br>
$ demo/dcc/bacdcc<br>
Usage: bacdcc device-instance state timeout [password]<br>
Send BACnet DeviceCommunicationControl service to device.<br>
<br>
$ demo/timesync/bacts<br>
Received TimeSyncronization Request<br>
2006/8/30 07:10:45.00<br>
<br>
$ demo/ucov/bacucov<br>
Usage: bacucov pid device-id object-type object-instance time property tag value [priority] [index]<br>
<br>
$ demo/whois/bacwi<br>
Usage: bacwi device-instance | device-instance-min device-instance-max<br>
Send BACnet WhoIs request to devices, and wait for responses.<br>
<br>
The device-instance can be 0 to 4194303, or -1 for ALL.<br>
The device-instance can also be specified as a range.<br>
<br>
</code>
<p>The demos can be compiled under Win32 using <a href="http://www.borland.com/bcppbuilder/freecompiler/">Borland C++</a> or
<a href="http://msdn.microsoft.com/visualc/vctoolkit2003/">Microsoft Visual C++</a>, both of which
are free (as in beer) command line compilers. Be sure to pick up the free
<a href="http://info.borland.com/devsupport/bcppbuilder/patches/#freecompiler55">patches (service packs) for the Borland C++ compiler</a> (<a href="http://info.borland.com/devsupport/bcppbuilder/patches/bcc55/bcc55sp1.zip">SP1</a>, <a href="http://info.borland.com/devsupport/bcppbuilder/patches/bcc55/bcc55sp2.exe">SP2</a>), as well as the free turbo debugger. It might also be possible to create Win32 projects using the free <a href="http://msdn.microsoft.com/vstudio/express/">Visual Studio Express Edition</a> or <a href="http://www.mingw.org/">MinGW - Minimalist GNU for Windows</a>, but I have haven't tried it. I have used <a href="http://codeblocks.org/">Code::Blocks</a> for compiling the unit tests using the MinGW compiler, but have not tried to get the demos working with MinGW. I have used <a href="http://codeblocks.org/">Code::Blocks</a> with the Borland C++ compiler and it successfully compiles the code.</p>
<p>There is a Makefile in the ports/rtos32 directory, and a sample
application that runs under <a href="http://www.on-time.com/">RTOS-32</a>.
It currently uses the BACnet/IP data link layer for communication, and also
has an MS/TP datalink layer sample application.
It compiles using <a href="http://borland.com/">Borland C++</a>.</p>
<p>There is a project in the ports/pic18 directory, and a sample
application that can be build using <a href="http://microchip.com">MP-Lab</a>
and the Microchip compiler MCC18. The MS/TP portion is now working,
and had a good showing at the BACnet International plugfest.</p>
<TABLE border="1" width="100%" cellpadding="1" cellspacing="0"
summary="BACnet services supported matrix">
<TBODY>
<TR><H2>BACnet services supported matrix</H2>
<p>The BACnet stack currently implements the following services listed in the
the table. We plan to add the rest of the services as we go.
With the services that are implemented, you could build a BACnet device
that meets the standardized profile for a BACnet Smart Sensor,
BACnet Smart Actuator, or a BACnet Application Specific Controller.</p></TR>
<TR>
<TD bgcolor="#CCF6F6" width="50%" valign="top"><b>BACnet Service</b></td>
<TD bgcolor="#CCF6F6" width="25%" align="center" valign="top"><b>Initiate</b></td>
<TD bgcolor="#CCF6F6" width="25%" align="center" valign="top"><b>Execute</b></td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Who Is</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">I Am</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Who Has</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">I Have</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Read Property</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Write Property</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Device Communication Control</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">ReinitializeDevice</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Atomic Read File</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Atomic Write File</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Time Synchronization</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">UTC Time Synchronization</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Subscribe COV</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Confirmed COV Notification</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Unconfirmed COV Notification</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">Yes</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Read Property Multiple</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Read Property Conditional</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Read Range</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Write Property Multiple</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Get Alarm Summary</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Get Event Information</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Get Enrollment Summary</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Acknowledge Alarm</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Confirmed Event Notification</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Unconfirmed Event Notification</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Unconfirmed Text Message</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Confirmed Text Message</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Add List Element</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Remove List Element</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Create Object</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Delete Object</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Unconfirmed Private Transfer</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">Confirmed Private Transfer</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">VT Open</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">VT Data</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
<TR>
<TD bgcolor="#FFFFDD" width="50%" valign="top">VT Close</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
<TD bgcolor="#FFFFDD" width="25%" align="center" valign="top">-</td>
</TR>
</TBODY>
</TABLE>
<h2>BACnet Objects</h2>
<p>The BACnet stack currently implements a Device Object, and
handles all of the ReadProperty inquiries for the required
Device Object properties. The stack handles Who-Is inquiries
with an I-Am, WhoHas with I-Have, and handles reject messages for
services not currently supported. There is built in handling for
DeviceCommunicationControl.</p>
<p>The example handlers interact with example objects, including
Analog Input, Analog Output, Analog Value, Binary Input,
Binary Output, Binary Value, Life Safety Point,
and Multi-state Output objects.
The objects can be accessed using WriteProperty,
ReadProperty, or Who-Has services. Adding other BACnet objects
is only a matter of setting up ReadProperty, WriteProperty, or
I-Have handling for the required properties and any other
properties that you want to support.</p>
<p>File Objects are conditionally included in the demonstation
applications. The files can be access using WriteProperty,
ReadProperty, Who-Has, AtomicWriteFile, or AtomicReadFile services.</p>
<h2>Getting Involved</h2>
<p>If you want to help out on this project, join the <a href="http://lists.sourceforge.net/mailman/listinfo/bacnet-developers">developers mailing list</a>, introduce yourself, and tell us what you would like to do.
If you are trying to implement a BACnet device or service using this project,
you are welcome to join the <a href="http://lists.sourceforge.net/mailman/listinfo/bacnet-developers">developers mailing list</a> as well.</p>
<p>More details about the project can be found on
the <a href="http://sourceforge.net/projects/bacnet/">BACnet Source Forge Project Page</a></p>
<p>There is documentation that <a href="http://sourceforge.net/docman/display_doc.php?docid=33182&group_id=117598">describes the mechanisms in the BACnet Stack</a>.
I wrote up some <a href="http://sourceforge.net/docman/display_doc.php?docid=35583&group_id=117598">answers to some frequently asked questions</a>. Of course,
there are a handful of text files in the doc directory of the project.</p>
<p><a
href="http://sourceforge.net/project/showfiles.php?group_id=117598&package_id=140172">BACnet
Stack file download</a></p>
<h2>BACnet Developer Resources</h2>
There are a number of resources that can help you develop a BACnet product or project.
<ul>
<li><a href="http://vts.sourceforge.net/">VTS</a> - visual test shell for
Win32, used for Visually testing a BACnet implementation. It also includes
a detailed network sniffer for BACnet messages, and the ability to send
any BACnet services. The source code is in the public domain. </li>
<li><a href="http://www.wireshark.org/">Wireshark</a> - an open source,
cross platform protocol analyzer with BACnet support. The detailed BACnet
support in began in version 0.10.11 released on May 4, 2005 when Wireshark
was known as Ethereal.</li>
<li><a href="http://www.ubuntu.com/">Ubuntu Linux</a> or
<a href="http://www.debian.org/">Debian Linux</a> - my
development platforms of choice.
Linux makes a great development platform
because all the necessary development tools are included.</li>
<li><a href="http://www.codeblocks.org/">Code::Blocks</a> - a free cross-platform
open source C/C++ IDE. Includes the MinGW compiler for Win32.</li>
</ul>
<p><a href="http://www.bacnet.org/Developer/index.html">BACnet Developer Help</a></p>
<p><a href="http://www.bacnetassociation.org/DevRes.htm">BACnet® International Developer Resources</a></p>
<h2>Products and Projects that use this BACnet Stack</h2>
<p>Did you develop a product using this BACnet stack? <a href="mailto:skarg@users.sourceforge.net">Let us know</a>, and you
can get a little recognition for your hard work!</p>
<p><a href="http://sensors.scinterface.com/">SCInterface&trade; = Sensor Control Interface</a> - middleware
platform for managing legacy and modern-day sensors through a centralized
interface</p>
<p><a href="http://sourceforge.net/projects/bacnet-sim/">BACnetSim</a> - a
portable implementation of the BACnet data communication protocol.
BACnetSim is meant for embedded devices and use MS/TP as the media
access layer. BACnetSim is a fork of bacnet-stack-0.0.1</p>
<hr>
<A href="http://sourceforge.net"> <IMG
src="http://sourceforge.net/sflogo.php?group_id=117598&amp;type=5"
width="210" height="62" border="0" alt="SourceForge.net Logo" /></A>
<p><font size="-2"><b>ASHRAE<sup>&reg;</sup></b> and
<b>BACnet<sup>&reg;</sup></b> are registered trademarks of the American
Society of Heating, Refrigerating and Air-Conditioning Engineers, Inc.,
1791 Tullie Circle NE, Atlanta, GA 30329.</font> </p>
<p>Updated 24-Oct-2006 by <a href="mailto:skarg@users.sourceforge.net">Steve Karg</a></p>
</BODY>
</HTML>