-
Notifications
You must be signed in to change notification settings - Fork 266
Expand file tree
/
Copy pathREADME.developer
More file actions
172 lines (155 loc) · 10.1 KB
/
README.developer
File metadata and controls
172 lines (155 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
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), a single Device Object, and a Network Port object
(protocol-revision 17 and later). 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. After determining
which services you want in your device, add files to your project or makefile
from the following BACnet services (messages) provided by this BACnet stack:
* abort.c - BACnet Abort service encode/decode
* bacerror.c - BACnet Error service encode/decode
* reject.c - BACnet Reject service encode/decode
* arf.c - AtomicReadFile service encode/decode
* awf.c - AtomicWriteFile service encode/decode
* rp.c - BACnet ReadProperty 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
* wpm.c - WritePropertyMultiple 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
* event.c - EventNotification service encode/decode
* get_alarm_sum.c - GetAlarmSummary service encode/decode
* getevent.c - GetEventInformation service encode/decode
* lso.c - LifeSafetyOperation service encode/decode
* ptransfer.c - PrivateTransfer service encode/deco
* readrange.c - ReadRange service encode/decode
Adding additional services is a matter of adding the encoding and decoding for
the service into/from meaningful data, and unit testing, a basic
handler and send function, as well as a basic command line example.
For each service that you add to your project or makefile, you will need to
add a handler and possibly a sending function. Some example handlers
and send functions for the services that the stack supports include:
* basic/service/h_alarm_ack.c - Alarm ACK service handler example
* basic/service/h_arf.c - AtomicReadFile service handler example
* basic/service/h_arf_a.c - AtomicReadFile ACK service handler example
* basic/service/h_awf.c - AtomicWriteFile service handler example
* basic/service/h_ccov.c - ConfirmedCOVNotification service handler example
* basic/service/h_cov.c - SubscribeCOV service handler example
* basic/service/h_dcc.c - DeviceCommuncationControl service handler example
* basic/service/h_get_alarm_sum.c - GetAlarmSummary service handler example
* basic/service/h_get_event.c - GetEventInformation service handler example
* basic/service/h_iam.c - I-Am service handler example
* basic/service/h_ihave.c - I-Have service handler example
* basic/service/h_lso.c - LifeSafetyOperation service handler example
* basic/service/h_pt.c - PrivateTransfer service handler example
* basic/service/h_pt_a.c - PrivateTransfer ACK service handler example
* basic/service/h_rp.c - ReadProperty service handler example
* basic/service/h_rp_a.c - ReadProperty ACK service handler example
* basic/service/h_rpm.c - ReadPropertyMultiple service handler example
* basic/service/h_rpm_a.c - ReadPropertyMultiple ACK service handler example
* basic/service/h_rr.c - ReadRange service handler example
* basic/service/h_rr_a.c - ReadRange ACK service handler example
* basic/service/h_ts.c - TimeSynchronization service handler example
* basic/service/h_ucov.c - UnconfirmedCOV service handler example
* basic/service/h_upt.c - UnconfirmedPrivateTransfer service handler example
* basic/service/h_whohas.c - WhoHas service handler example
* basic/service/h_whois.c - Who-Is service handler example
* basic/service/h_wp.c - WriteProperty ACK service handler example
* basic/service/h_wpm.c - WritePropertyMultiple service handler example
* basic/service/h_noserv.c - unrecognized service handler 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. Some tips
for adding a new object include:
* Copy an existing BACnet object that is similar in functionality,
and search/replace the names of the API.
* Copy an existing BACnet object unit test in the test/ folder
for the similar object and search/replace the names of the API.
Use the unit test for verifying functionality and code coverage.
* There is a BACnet property list file that includes all the object
REQUIRED and OPTIONAL property enumerations and those can be used
as a guide for the BACnet properties in a basic example object.
* Add the BACnet object C file to the CMakeLists.txt file and the
apps/server/Makefile and others as needed.
* Add the BACnet object API to the device object(s) modules.
Some example object files in the BACnet stack include:
* basic/object/ai.c - analog input object example
* basic/object/ao.c - analog output object example
* basic/object/av.c - analog value object example
* basic/object/bacfile.c - File object example
* basic/object/device.c - device object example
* basic/object/bi.c - binary input object example
* basic/object/bo.c - binary output object example
* basic/object/bv.c - binary value object example
* basic/object/lc.c - load control object example
* basic/object/lsp.c - life safety point object example
* basic/object/mso.c - multi-state output object example
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
* bacint.c - primitive BACnet integer datatype encoding and decoding
* bacreal.c - primitive BACnet REAL datatype encoding and decoding
* bacstr.c - primative BACnet string datatype encoding and decoding
* bacapp.c - application data encoding and decoding
* npdu.c - encoding and decoding of the NPDU layer data
* basic/service/h_npdu.c - handles dispatching of the network message
to the apdu dispatcher.
The DataLink Layer controls orderly access to the physical medium.
The stack, by default, supports one datalink layer at a time, and uses a
macro defined in config.h or your makefile/project to choose the macro
functions defined in datalink.h. The datalink common files are in
the src/bacnet/datalink folder, and port specific files are in ports/xx.
There are a few dozen demonstration applications in the apps/ directory,
along with many demonstation objects and service handlers. All the demos
accept command line options and have been tested under Win32 and Linux.
There is an apps/Makefile that is common for all the apps using GNU Make
build, and a Makefile in each respective apps/xx directory for the specific
application. The root Makefile is typically used for pipeline builds, tests,
and other convenience builds for the entire library. There is also
a CMakeLists.txt file that can be used to build the library and all
the applications.
The simplest demonstration is to run apps/server/bacserv on one PC (or
virtual PC), and run the other client demonstration applications one
at time on another PC (or virtual PC). Monitor the network communications
using Wireshark protocol analyzer, or interact with the BACnet server using
YABE - see https://sourceforge.net/projects/yetanotherbacnetexplorer/