fixed svn EOL and MIME settings.

This commit is contained in:
skarg
2012-04-06 23:24:43 +00:00
parent 62eea57d4b
commit d1f4e78cba
57 changed files with 11387 additions and 11363 deletions
+50 -50
View File
@@ -1,50 +1,50 @@
@echo off
:Test_Start
echo Test: Read Required Properties of Device Object %1
bacrp.exe %1 8 %1 75
bacrp.exe %1 8 %1 77
bacrp.exe %1 8 %1 79
bacrp.exe %1 8 %1 112
bacrp.exe %1 8 %1 121
bacrp.exe %1 8 %1 120
bacrp.exe %1 8 %1 70
bacrp.exe %1 8 %1 44
bacrp.exe %1 8 %1 12
bacrp.exe %1 8 %1 98
bacrp.exe %1 8 %1 139
bacrp.exe %1 8 %1 97
bacrp.exe %1 8 %1 96
bacrp.exe %1 8 %1 76 0
bacrp.exe %1 8 %1 76
bacrp.exe %1 8 %1 62
bacrp.exe %1 8 %1 107
bacrp.exe %1 8 %1 11
bacrp.exe %1 8 %1 73
bacrp.exe %1 8 %1 30
bacrp.exe %1 8 %1 155
echo Test: Read Optional Properties of Device Object %1
bacrp.exe %1 8 %1 58
bacrp.exe %1 8 %1 28
bacrp.exe %1 8 %1 167
bacrp.exe %1 8 %1 122
bacrp.exe %1 8 %1 5
bacrp.exe %1 8 %1 57
bacrp.exe %1 8 %1 56
bacrp.exe %1 8 %1 119
bacrp.exe %1 8 %1 24
bacrp.exe %1 8 %1 10
bacrp.exe %1 8 %1 55
bacrp.exe %1 8 %1 116
bacrp.exe %1 8 %1 64
bacrp.exe %1 8 %1 63
bacrp.exe %1 8 %1 1
bacrp.exe %1 8 %1 154
bacrp.exe %1 8 %1 157
bacrp.exe %1 8 %1 153
bacrp.exe %1 8 %1 152
bacrp.exe %1 8 %1 172
bacrp.exe %1 8 %1 170
bacrp.exe %1 8 %1 169
bacrp.exe %1 8 %1 171
bacrp.exe %1 8 %1 168
@echo off
:Test_Start
echo Test: Read Required Properties of Device Object %1
bacrp.exe %1 8 %1 75
bacrp.exe %1 8 %1 77
bacrp.exe %1 8 %1 79
bacrp.exe %1 8 %1 112
bacrp.exe %1 8 %1 121
bacrp.exe %1 8 %1 120
bacrp.exe %1 8 %1 70
bacrp.exe %1 8 %1 44
bacrp.exe %1 8 %1 12
bacrp.exe %1 8 %1 98
bacrp.exe %1 8 %1 139
bacrp.exe %1 8 %1 97
bacrp.exe %1 8 %1 96
bacrp.exe %1 8 %1 76 0
bacrp.exe %1 8 %1 76
bacrp.exe %1 8 %1 62
bacrp.exe %1 8 %1 107
bacrp.exe %1 8 %1 11
bacrp.exe %1 8 %1 73
bacrp.exe %1 8 %1 30
bacrp.exe %1 8 %1 155
echo Test: Read Optional Properties of Device Object %1
bacrp.exe %1 8 %1 58
bacrp.exe %1 8 %1 28
bacrp.exe %1 8 %1 167
bacrp.exe %1 8 %1 122
bacrp.exe %1 8 %1 5
bacrp.exe %1 8 %1 57
bacrp.exe %1 8 %1 56
bacrp.exe %1 8 %1 119
bacrp.exe %1 8 %1 24
bacrp.exe %1 8 %1 10
bacrp.exe %1 8 %1 55
bacrp.exe %1 8 %1 116
bacrp.exe %1 8 %1 64
bacrp.exe %1 8 %1 63
bacrp.exe %1 8 %1 1
bacrp.exe %1 8 %1 154
bacrp.exe %1 8 %1 157
bacrp.exe %1 8 %1 153
bacrp.exe %1 8 %1 152
bacrp.exe %1 8 %1 172
bacrp.exe %1 8 %1 170
bacrp.exe %1 8 %1 169
bacrp.exe %1 8 %1 171
bacrp.exe %1 8 %1 168
+14 -14
View File
@@ -1,14 +1,14 @@
@echo off
echo Example of parameters for Foreign Device Registration
echo This CMD window will use port 47809 to communicate
@echo on
set BACNET_IP_PORT=47809
@echo off
echo The BBMD is located at the standard port 47808 and at
echo the dotted IP address passed in on the command line.
echo When the demo client applications see the BBMD address,
echo they register as a Foreign Device to it.
@echo on
set BACNET_BBMD_PORT=47808
set BACNET_BBMD_ADDRESS=%1
@echo off
echo Example of parameters for Foreign Device Registration
echo This CMD window will use port 47809 to communicate
@echo on
set BACNET_IP_PORT=47809
@echo off
echo The BBMD is located at the standard port 47808 and at
echo the dotted IP address passed in on the command line.
echo When the demo client applications see the BBMD address,
echo they register as a Foreign Device to it.
@echo on
set BACNET_BBMD_PORT=47808
set BACNET_BBMD_ADDRESS=%1
+165 -165
View File
@@ -1,165 +1,165 @@
BACnet Tools are binary demo application command line
utilities that use BACnet/IP to perform a variety of
BACnet services. Some tools use BACnet WhoIs to bind to
devices, but can also use a static binding file address_cache.
Most of the tools have help (--help option), and use
environment variables to configure the datalink.
The Client Tools use WhoIs to bind to target devices.
The WhoIs can be eliminated by using the address_cache
file, which is read by each client tool from the current
working directory. Having the device address from the
address_cache file will greatly improve the throughput
and speed of the client tools. The address_cache file
can be generated using the standard output of the bacwi tool.
EXAMPLE:
bacwi -1 > address_cache
Client Tools
------------
bacarf - BACnet AtomicReadFile service
bacawf - BACnet AtomicWriteFile service
bacdcc - BACnet DeviceCommunicationControl service
bacepics - BACnet EPICS for Device object.
bacrd - BACnet ReinitializeDevice service
bacrp - BACnet ReadProperty service
bacrpm - BACnet ReadPropertyMultiple service
bacscov - BACnet SubscribeCOV service
bacts - BACnet TimeSynchronization service
bacucov - BACnet UnconfirmedChangeOfValue service
bacupt - BACnet UnconfirmedPrivateTransfer service
bacwh - BACnet WhoHas service
bacwi - BACnet WhoIs service
bacwp - BACnet WriteProperty service
Server Tools
------------
bacserv - BACnet Device Simulator
Router Tools
------------
baciamr - BACnet I-Am-Router to Network message
bacinitr - BACnet Initialize Router message
bacwir - BACnet Who-Is Router to Network message
MS/TP Capture Tool
------------------
The mstpcap tool is used for capturing MS/TP traffic
from an RS-485 serial adapter and saving the packets
in a file for viewing by Wireshark.
Environment Variables
---------------------
BACNET_APDU_TIMEOUT - set this value in milliseconds to change
the APDU timeout. APDU Timeout is how much time a client
waits for a response from a BACnet device. Default is 3000ms.
BACNET_IFACE - set this value to dotted IP address (Windows) of
the interface (see ipconfig command on Windows) for which you
want to bind. On Linux, set this to the /dev interface
(i.e. eth0, arc0). Default is eth0 on Linux, and the default
interface on Windows. Hence, if there is only a single network
interface on Windows, the applications will choose it, and this
setting will not be needed.
BACNET_IP_PORT - UDP/IP port number (0..65534) used for BACnet/IP
communications. Default is 47808 (0xBAC0).
BACNET_BBMD_PORT - UDP/IP port number (0..65534) used for Foreign
Device Registration. Defaults to 47808 (0xBAC0).
BACNET_BBMD_TIMETOLIVE - number of seconds used in Foreign Device
Registration (0..65535). Defaults to 60000 seconds.
BACNET_BBMD_ADDRESS - dotted IPv4 address of the BBMD or Foreign Device
Registrar.
Example Usage
-------------
You can communicate with the virtual BACnet Device by using the other BACnet
command line tools. If you are using the same PC, you can use BBMD/FD
(Foreign Device registration) to do this - use the bvlc script. You can
monitor the interaction and bytes on the wire using Wireshark. Here is
an example usage for Window and for Linux.
Windows
-------
The BACnet tools are used from the Command Prompt, or CMD.EXE.
From the command prompt window, start the simulated BACnet device:
c:\> bacserv 1234
From another command prompt window, use ipconfig to determine the
network interface IP address that bacserv is using:
c:\> ipconfig
Use the default IP address to configure the BBMD and Foreign Device
environment variables:
c:\> bvlc.bat 192.168.0.42
bvlc.bat batch file configures environment variables to use BACnet/IP
port 47809 for any subsequent BACnet tools run from that command prompt window,
and enables the BBMD Foreign Device Registration.
Perform a device discovery:
c:\> bacwi -1
Read all the required properties from the Device 1234 and display their values:
c:\> bacepics -v 1234
Read the Object_Identifier property from the Device 1234:
c:\> bacrp 1234 8 1234 75
Write 100.0 (REAL=4 datatype) to Device 1234 Analog Output (1) One (1)
at priority 16 with no index (-1).
c:\> bacwp 1234 1 1 85 16 -1 4 100.0
Each tool has help:
c:\> bacrp --help
Linux
-----
To use the tools from the command line, you need to use the path to the command,
or include the path in your PATH environment variable. The dot "." means current
directory. The "/" is used to separate directories. "./" means the path starts
from the current directory.
When the tools are built from the Makefile, they are copied to the bin/ directory.
So from the root of the project you could run the tools like this using a terminal
window:
$ make clean all
$ ./bin/bacserv 1234
In another terminal window use ifconfig to determine the network interface IP
address that bacserv is using:
$ ifconfig
Use that address (likely from eth0) to configure the BBMD and Foreign Device
environment variables:
$./bin/bvlc.sh 192.168.0.42
bvlc.sh script configures environment variables to use BACnet/IP
port 47809 for any subsequent BACnet tools run from that shell,
and enables the BBMD Foreign Device Registration.
Perform a device discovery:
$ ./bin/bacwi -1
Read all the required properties from the Device 1234 and display their values:
$ ./bin/bacepics -v 1234
Read the Object_Identifier property from the Device 1234:
$ ./bin/bacrp 1234 8 1234 75
Write 100.0 (REAL=4 datatype) to Device 1234 Analog Output (1) One (1)
at priority 16 with no index (-1).
$ ./bin/bacwp 1234 1 1 85 16 -1 4 100.0
Each tool has help:
$ ./bin/bacrp --help
Source Code
-----------
The source code for the BACnet-Tools can be found at:
http://bacnet.sourceforge.net/
BACnet Tools are binary demo application command line
utilities that use BACnet/IP to perform a variety of
BACnet services. Some tools use BACnet WhoIs to bind to
devices, but can also use a static binding file address_cache.
Most of the tools have help (--help option), and use
environment variables to configure the datalink.
The Client Tools use WhoIs to bind to target devices.
The WhoIs can be eliminated by using the address_cache
file, which is read by each client tool from the current
working directory. Having the device address from the
address_cache file will greatly improve the throughput
and speed of the client tools. The address_cache file
can be generated using the standard output of the bacwi tool.
EXAMPLE:
bacwi -1 > address_cache
Client Tools
------------
bacarf - BACnet AtomicReadFile service
bacawf - BACnet AtomicWriteFile service
bacdcc - BACnet DeviceCommunicationControl service
bacepics - BACnet EPICS for Device object.
bacrd - BACnet ReinitializeDevice service
bacrp - BACnet ReadProperty service
bacrpm - BACnet ReadPropertyMultiple service
bacscov - BACnet SubscribeCOV service
bacts - BACnet TimeSynchronization service
bacucov - BACnet UnconfirmedChangeOfValue service
bacupt - BACnet UnconfirmedPrivateTransfer service
bacwh - BACnet WhoHas service
bacwi - BACnet WhoIs service
bacwp - BACnet WriteProperty service
Server Tools
------------
bacserv - BACnet Device Simulator
Router Tools
------------
baciamr - BACnet I-Am-Router to Network message
bacinitr - BACnet Initialize Router message
bacwir - BACnet Who-Is Router to Network message
MS/TP Capture Tool
------------------
The mstpcap tool is used for capturing MS/TP traffic
from an RS-485 serial adapter and saving the packets
in a file for viewing by Wireshark.
Environment Variables
---------------------
BACNET_APDU_TIMEOUT - set this value in milliseconds to change
the APDU timeout. APDU Timeout is how much time a client
waits for a response from a BACnet device. Default is 3000ms.
BACNET_IFACE - set this value to dotted IP address (Windows) of
the interface (see ipconfig command on Windows) for which you
want to bind. On Linux, set this to the /dev interface
(i.e. eth0, arc0). Default is eth0 on Linux, and the default
interface on Windows. Hence, if there is only a single network
interface on Windows, the applications will choose it, and this
setting will not be needed.
BACNET_IP_PORT - UDP/IP port number (0..65534) used for BACnet/IP
communications. Default is 47808 (0xBAC0).
BACNET_BBMD_PORT - UDP/IP port number (0..65534) used for Foreign
Device Registration. Defaults to 47808 (0xBAC0).
BACNET_BBMD_TIMETOLIVE - number of seconds used in Foreign Device
Registration (0..65535). Defaults to 60000 seconds.
BACNET_BBMD_ADDRESS - dotted IPv4 address of the BBMD or Foreign Device
Registrar.
Example Usage
-------------
You can communicate with the virtual BACnet Device by using the other BACnet
command line tools. If you are using the same PC, you can use BBMD/FD
(Foreign Device registration) to do this - use the bvlc script. You can
monitor the interaction and bytes on the wire using Wireshark. Here is
an example usage for Window and for Linux.
Windows
-------
The BACnet tools are used from the Command Prompt, or CMD.EXE.
From the command prompt window, start the simulated BACnet device:
c:\> bacserv 1234
From another command prompt window, use ipconfig to determine the
network interface IP address that bacserv is using:
c:\> ipconfig
Use the default IP address to configure the BBMD and Foreign Device
environment variables:
c:\> bvlc.bat 192.168.0.42
bvlc.bat batch file configures environment variables to use BACnet/IP
port 47809 for any subsequent BACnet tools run from that command prompt window,
and enables the BBMD Foreign Device Registration.
Perform a device discovery:
c:\> bacwi -1
Read all the required properties from the Device 1234 and display their values:
c:\> bacepics -v 1234
Read the Object_Identifier property from the Device 1234:
c:\> bacrp 1234 8 1234 75
Write 100.0 (REAL=4 datatype) to Device 1234 Analog Output (1) One (1)
at priority 16 with no index (-1).
c:\> bacwp 1234 1 1 85 16 -1 4 100.0
Each tool has help:
c:\> bacrp --help
Linux
-----
To use the tools from the command line, you need to use the path to the command,
or include the path in your PATH environment variable. The dot "." means current
directory. The "/" is used to separate directories. "./" means the path starts
from the current directory.
When the tools are built from the Makefile, they are copied to the bin/ directory.
So from the root of the project you could run the tools like this using a terminal
window:
$ make clean all
$ ./bin/bacserv 1234
In another terminal window use ifconfig to determine the network interface IP
address that bacserv is using:
$ ifconfig
Use that address (likely from eth0) to configure the BBMD and Foreign Device
environment variables:
$./bin/bvlc.sh 192.168.0.42
bvlc.sh script configures environment variables to use BACnet/IP
port 47809 for any subsequent BACnet tools run from that shell,
and enables the BBMD Foreign Device Registration.
Perform a device discovery:
$ ./bin/bacwi -1
Read all the required properties from the Device 1234 and display their values:
$ ./bin/bacepics -v 1234
Read the Object_Identifier property from the Device 1234:
$ ./bin/bacrp 1234 8 1234 75
Write 100.0 (REAL=4 datatype) to Device 1234 Analog Output (1) One (1)
at priority 16 with no index (-1).
$ ./bin/bacwp 1234 1 1 85 16 -1 4 100.0
Each tool has help:
$ ./bin/bacrp --help
Source Code
-----------
The source code for the BACnet-Tools can be found at:
http://bacnet.sourceforge.net/
+7 -7
View File
@@ -1,7 +1,7 @@
@echo off
echo Build for Borland 5.5 tools
set BORLAND_DIR=c:\borland\bcc55
%BORLAND_DIR%\bin\make -f makefile.b32 clean
%BORLAND_DIR%\bin\make -f makefile.b32 all
@echo off
echo Build for Borland 5.5 tools
set BORLAND_DIR=c:\borland\bcc55
%BORLAND_DIR%\bin\make -f makefile.b32 clean
%BORLAND_DIR%\bin\make -f makefile.b32 all
+17 -17
View File
@@ -1,17 +1,17 @@
@echo off
echo Build with MinGW and MSYS: mingw.sourceforge.net
rem set PATH=C:\MinGW\msys\1.0\bin;C:\MinGW\bin
rem assumes rm, cp, size are already in path
set CC=gcc
set AR=ar
set MAKE=make
make BACNET_PORT=win32 BUILD=release clean all
rem Build for MinGW debug
rem make BACNET_PORT=win32 BUILD=debug clean all
rem Build for MinGW MS/TP
rem make BACNET_PORT=win32 BACDL_DEFINE=-DBACDL_MSTP=1 clean all
rem On Linux, install mingw32 and use this:
rem make BACNET_PORT=win32 CC=i586-mingw32msvc-gcc AR=i586-mingw32msvc-ar clean all
@echo off
echo Build with MinGW and MSYS: mingw.sourceforge.net
rem set PATH=C:\MinGW\msys\1.0\bin;C:\MinGW\bin
rem assumes rm, cp, size are already in path
set CC=gcc
set AR=ar
set MAKE=make
make BACNET_PORT=win32 BUILD=release clean all
rem Build for MinGW debug
rem make BACNET_PORT=win32 BUILD=debug clean all
rem Build for MinGW MS/TP
rem make BACNET_PORT=win32 BACDL_DEFINE=-DBACDL_MSTP=1 clean all
rem On Linux, install mingw32 and use this:
rem make BACNET_PORT=win32 CC=i586-mingw32msvc-gcc AR=i586-mingw32msvc-ar clean all
+9 -1
View File
@@ -9,10 +9,18 @@ TARGET = bacgateway
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)/gw_device.c \
${CORE_SRC} \
${PORT_SRC} \
${HANDLER_SRC} \
${OBJECT_SRC} \
${ROUTING_SRC}
OBJS = ${SRCS:.c=.o}
DEFINES += -DBAC_ROUTING
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
+173 -173
View File
@@ -1,173 +1,173 @@
/**************************************************************************
*
* Copyright (C) 2011 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "config.h"
#include "txbuf.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "apdu.h"
#include "npdu.h"
#include "abort.h"
/* special for this module */
#include "cov.h"
#include "bactext.h"
#include "handlers.h"
#ifndef MAX_COV_PROPERTIES
#define MAX_COV_PROPERTIES 2
#endif
/** @file h_ccov.c Handles Confirmed COV Notifications. */
/* */
/** Handler for an Confirmed COV Notification.
* @ingroup DSCOV
* Decodes the received list of Properties to update,
* and print them out with the subscription information.
* @note Nothing is specified in BACnet about what to do with the
* information received from Confirmed COV Notifications.
*
* @param service_request [in] The contents of the service request.
* @param service_len [in] The length of the service_request.
* @param src [in] BACNET_ADDRESS of the source of the message
* @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information
* decoded from the APDU header of this message.
*/
void handler_ccov_notification(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_NPDU_DATA npdu_data;
BACNET_COV_DATA cov_data;
BACNET_PROPERTY_VALUE property_value[MAX_COV_PROPERTIES];
BACNET_PROPERTY_VALUE *pProperty_value = NULL;
unsigned index = 0;
int len = 0;
int pdu_len = 0;
int bytes_sent = 0;
BACNET_ADDRESS my_address;
/* create linked list to store data if more
than one property value is expected */
pProperty_value = &property_value[0];
while (pProperty_value) {
index++;
if (index < MAX_COV_PROPERTIES) {
pProperty_value->next = &property_value[index];
} else {
pProperty_value->next = NULL;
}
pProperty_value = pProperty_value->next;
}
cov_data.listOfValues = &property_value[0];
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
pdu_len =
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
#if PRINT_ENABLED
fprintf(stderr, "CCOV: Received Notification!\n");
#endif
if (service_data->segmented_message) {
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
#if PRINT_ENABLED
fprintf(stderr, "CCOV: Segmented message. Sending Abort!\n");
#endif
goto CCOV_ABORT;
} /* decode the service request only */
/* decode the service request only */
len =
cov_notify_decode_service_request(service_request, service_len,
&cov_data);
#if PRINT_ENABLED
if (len > 0) {
fprintf(stderr, "CCOV: PID=%u ", cov_data.subscriberProcessIdentifier);
fprintf(stderr, "instance=%u ", cov_data.initiatingDeviceIdentifier);
fprintf(stderr, "%s %u ",
bactext_object_type_name(cov_data.monitoredObjectIdentifier.type),
cov_data.monitoredObjectIdentifier.instance);
fprintf(stderr, "time remaining=%u seconds ", cov_data.timeRemaining);
fprintf(stderr, "\n");
pProperty_value = &property_value[0];
while (pProperty_value) {
fprintf(stderr, "CCOV: ");
if (pProperty_value->propertyIdentifier < 512) {
fprintf(stderr, "%s ",
bactext_property_name
(pProperty_value->propertyIdentifier));
} else {
fprintf(stderr, "proprietary %u ",
pProperty_value->propertyIdentifier);
}
if (pProperty_value->propertyArrayIndex != BACNET_ARRAY_ALL) {
fprintf(stderr, "%u ", pProperty_value->propertyArrayIndex);
}
fprintf(stderr, "\n");
pProperty_value = pProperty_value->next;
}
}
#endif
/* bad decoding or something we didn't understand - send an abort */
if (len <= 0) {
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_OTHER, true);
#if PRINT_ENABLED
fprintf(stderr, "CCOV: Bad Encoding. Sending Abort!\n");
#endif
goto CCOV_ABORT;
} else {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_COV_NOTIFICATION);
#if PRINT_ENABLED
fprintf(stderr, "CCOV: Sending Simple Ack!\n");
#endif
}
CCOV_ABORT:
pdu_len += len;
bytes_sent =
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
pdu_len);
#if PRINT_ENABLED
if (bytes_sent <= 0) {
fprintf(stderr, "CCOV: Failed to send PDU (%s)!\n", strerror(errno));
}
#else
bytes_sent = bytes_sent;
#endif
return;
}
/**************************************************************************
*
* Copyright (C) 2011 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "config.h"
#include "txbuf.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "apdu.h"
#include "npdu.h"
#include "abort.h"
/* special for this module */
#include "cov.h"
#include "bactext.h"
#include "handlers.h"
#ifndef MAX_COV_PROPERTIES
#define MAX_COV_PROPERTIES 2
#endif
/** @file h_ccov.c Handles Confirmed COV Notifications. */
/* */
/** Handler for an Confirmed COV Notification.
* @ingroup DSCOV
* Decodes the received list of Properties to update,
* and print them out with the subscription information.
* @note Nothing is specified in BACnet about what to do with the
* information received from Confirmed COV Notifications.
*
* @param service_request [in] The contents of the service request.
* @param service_len [in] The length of the service_request.
* @param src [in] BACNET_ADDRESS of the source of the message
* @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information
* decoded from the APDU header of this message.
*/
void handler_ccov_notification(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_NPDU_DATA npdu_data;
BACNET_COV_DATA cov_data;
BACNET_PROPERTY_VALUE property_value[MAX_COV_PROPERTIES];
BACNET_PROPERTY_VALUE *pProperty_value = NULL;
unsigned index = 0;
int len = 0;
int pdu_len = 0;
int bytes_sent = 0;
BACNET_ADDRESS my_address;
/* create linked list to store data if more
than one property value is expected */
pProperty_value = &property_value[0];
while (pProperty_value) {
index++;
if (index < MAX_COV_PROPERTIES) {
pProperty_value->next = &property_value[index];
} else {
pProperty_value->next = NULL;
}
pProperty_value = pProperty_value->next;
}
cov_data.listOfValues = &property_value[0];
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
pdu_len =
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
#if PRINT_ENABLED
fprintf(stderr, "CCOV: Received Notification!\n");
#endif
if (service_data->segmented_message) {
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
#if PRINT_ENABLED
fprintf(stderr, "CCOV: Segmented message. Sending Abort!\n");
#endif
goto CCOV_ABORT;
} /* decode the service request only */
/* decode the service request only */
len =
cov_notify_decode_service_request(service_request, service_len,
&cov_data);
#if PRINT_ENABLED
if (len > 0) {
fprintf(stderr, "CCOV: PID=%u ", cov_data.subscriberProcessIdentifier);
fprintf(stderr, "instance=%u ", cov_data.initiatingDeviceIdentifier);
fprintf(stderr, "%s %u ",
bactext_object_type_name(cov_data.monitoredObjectIdentifier.type),
cov_data.monitoredObjectIdentifier.instance);
fprintf(stderr, "time remaining=%u seconds ", cov_data.timeRemaining);
fprintf(stderr, "\n");
pProperty_value = &property_value[0];
while (pProperty_value) {
fprintf(stderr, "CCOV: ");
if (pProperty_value->propertyIdentifier < 512) {
fprintf(stderr, "%s ",
bactext_property_name
(pProperty_value->propertyIdentifier));
} else {
fprintf(stderr, "proprietary %u ",
pProperty_value->propertyIdentifier);
}
if (pProperty_value->propertyArrayIndex != BACNET_ARRAY_ALL) {
fprintf(stderr, "%u ", pProperty_value->propertyArrayIndex);
}
fprintf(stderr, "\n");
pProperty_value = pProperty_value->next;
}
}
#endif
/* bad decoding or something we didn't understand - send an abort */
if (len <= 0) {
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_OTHER, true);
#if PRINT_ENABLED
fprintf(stderr, "CCOV: Bad Encoding. Sending Abort!\n");
#endif
goto CCOV_ABORT;
} else {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_COV_NOTIFICATION);
#if PRINT_ENABLED
fprintf(stderr, "CCOV: Sending Simple Ack!\n");
#endif
}
CCOV_ABORT:
pdu_len += len;
bytes_sent =
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
pdu_len);
#if PRINT_ENABLED
if (bytes_sent <= 0) {
fprintf(stderr, "CCOV: Failed to send PDU (%s)!\n", strerror(errno));
}
#else
bytes_sent = bytes_sent;
#endif
return;
}
+158 -158
View File
@@ -1,158 +1,158 @@
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "config.h"
#include "txbuf.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "bacerror.h"
#include "apdu.h"
#include "npdu.h"
#include "abort.h"
#include "handlers.h"
/** @file h_alarm_sum.c Handles Get Alarm Summary request. */
static get_alarm_summary_function Get_Alarm_Summary[MAX_BACNET_OBJECT_TYPE];
void handler_get_alarm_summary_set(
BACNET_OBJECT_TYPE object_type,
get_alarm_summary_function pFunction)
{
if (object_type < MAX_BACNET_OBJECT_TYPE) {
Get_Alarm_Summary[object_type] = pFunction;
}
}
void handler_get_alarm_summary(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
int len = 0;
int pdu_len = 0;
int apdu_len = 0;
int bytes_sent = 0;
int alarm_value = 0;
unsigned i = 0;
unsigned j = 0;
bool error = false;
BACNET_ADDRESS my_address;
BACNET_NPDU_DATA npdu_data;
BACNET_GET_ALARM_SUMMARY_DATA getalarm_data;
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
pdu_len =
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
if (service_data->segmented_message) {
/* we don't support segmentation - send an abort */
apdu_len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
#if PRINT_ENABLED
fprintf(stderr,
"GetAlarmSummary: Segmented message. Sending Abort!\n");
#endif
goto GET_ALARM_SUMMARY_ABORT;
}
/* init header */
apdu_len = get_alarm_summary_ack_encode_apdu_init(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id);
for (i = 0; i < MAX_BACNET_OBJECT_TYPE; i++) {
if (Get_Alarm_Summary[i]) {
for (j = 0; j < 0xffff; j++) {
alarm_value = Get_Alarm_Summary[i] (j, &getalarm_data);
if (alarm_value > 0) {
len = get_alarm_sumary_ack_encode_apdu_data(
&Handler_Transmit_Buffer[pdu_len + apdu_len],
service_data->max_resp - apdu_len,
&getalarm_data);
if (len <= 0) {
error = true;
goto GET_ALARM_SUMMARY_ERROR;
}
else
apdu_len += len;
}
else if (alarm_value < 0) {
break;
}
}
}
}
#if PRINT_ENABLED
fprintf(stderr, "GetAlarmSummary: Sending response!\n");
#endif
GET_ALARM_SUMMARY_ERROR:
if (error) {
if (len == BACNET_STATUS_ABORT) {
/* BACnet APDU too small to fit data, so proper response is Abort */
apdu_len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
#if PRINT_ENABLED
fprintf(stderr,
"GetAlarmSummary: Reply too big to fit into APDU!\n");
#endif
}
else {
apdu_len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_GET_ALARM_SUMMARY,
ERROR_CLASS_PROPERTY, ERROR_CODE_OTHER);
#if PRINT_ENABLED
fprintf(stderr, "GetAlarmSummary: Sending Error!\n");
#endif
}
}
GET_ALARM_SUMMARY_ABORT:
pdu_len += apdu_len;
bytes_sent =
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
pdu_len);
return;
}
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "config.h"
#include "txbuf.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "bacerror.h"
#include "apdu.h"
#include "npdu.h"
#include "abort.h"
#include "handlers.h"
/** @file h_alarm_sum.c Handles Get Alarm Summary request. */
static get_alarm_summary_function Get_Alarm_Summary[MAX_BACNET_OBJECT_TYPE];
void handler_get_alarm_summary_set(
BACNET_OBJECT_TYPE object_type,
get_alarm_summary_function pFunction)
{
if (object_type < MAX_BACNET_OBJECT_TYPE) {
Get_Alarm_Summary[object_type] = pFunction;
}
}
void handler_get_alarm_summary(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
int len = 0;
int pdu_len = 0;
int apdu_len = 0;
int bytes_sent = 0;
int alarm_value = 0;
unsigned i = 0;
unsigned j = 0;
bool error = false;
BACNET_ADDRESS my_address;
BACNET_NPDU_DATA npdu_data;
BACNET_GET_ALARM_SUMMARY_DATA getalarm_data;
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
pdu_len =
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
if (service_data->segmented_message) {
/* we don't support segmentation - send an abort */
apdu_len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
#if PRINT_ENABLED
fprintf(stderr,
"GetAlarmSummary: Segmented message. Sending Abort!\n");
#endif
goto GET_ALARM_SUMMARY_ABORT;
}
/* init header */
apdu_len = get_alarm_summary_ack_encode_apdu_init(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id);
for (i = 0; i < MAX_BACNET_OBJECT_TYPE; i++) {
if (Get_Alarm_Summary[i]) {
for (j = 0; j < 0xffff; j++) {
alarm_value = Get_Alarm_Summary[i] (j, &getalarm_data);
if (alarm_value > 0) {
len = get_alarm_sumary_ack_encode_apdu_data(
&Handler_Transmit_Buffer[pdu_len + apdu_len],
service_data->max_resp - apdu_len,
&getalarm_data);
if (len <= 0) {
error = true;
goto GET_ALARM_SUMMARY_ERROR;
}
else
apdu_len += len;
}
else if (alarm_value < 0) {
break;
}
}
}
}
#if PRINT_ENABLED
fprintf(stderr, "GetAlarmSummary: Sending response!\n");
#endif
GET_ALARM_SUMMARY_ERROR:
if (error) {
if (len == BACNET_STATUS_ABORT) {
/* BACnet APDU too small to fit data, so proper response is Abort */
apdu_len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
#if PRINT_ENABLED
fprintf(stderr,
"GetAlarmSummary: Reply too big to fit into APDU!\n");
#endif
}
else {
apdu_len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_GET_ALARM_SUMMARY,
ERROR_CLASS_PROPERTY, ERROR_CODE_OTHER);
#if PRINT_ENABLED
fprintf(stderr, "GetAlarmSummary: Sending Error!\n");
#endif
}
}
GET_ALARM_SUMMARY_ABORT:
pdu_len += apdu_len;
bytes_sent =
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
pdu_len);
return;
}
+35 -35
View File
@@ -1,38 +1,38 @@
#Makefile to build BACnet Application for the Linux Port
# tools - only if you need them.
# Most platforms have this already defined
# CC = gcc
TARGET = baciamr
#Makefile to build BACnet Application for the Linux Port
# tools - only if you need them.
# Most platforms have this already defined
# CC = gcc
TARGET = baciamr
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
size $@
cp $@ ../../bin
lib: ${BACNET_LIB_TARGET}
${BACNET_LIB_TARGET}:
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -f core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET} $(TARGET).map
include: .depend
lib: ${BACNET_LIB_TARGET}
${BACNET_LIB_TARGET}:
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -f core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET} $(TARGET).map
include: .depend
+35 -35
View File
@@ -1,38 +1,38 @@
#Makefile to build BACnet Application for the Linux Port
# tools - only if you need them.
# Most platforms have this already defined
# CC = gcc
TARGET = bacinitr
#Makefile to build BACnet Application for the Linux Port
# tools - only if you need them.
# Most platforms have this already defined
# CC = gcc
TARGET = bacinitr
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
size $@
cp $@ ../../bin
lib: ${BACNET_LIB_TARGET}
${BACNET_LIB_TARGET}:
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -f core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET} $(TARGET).map
include: .depend
lib: ${BACNET_LIB_TARGET}
${BACNET_LIB_TARGET}:
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -f core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET} $(TARGET).map
include: .depend
+177 -177
View File
@@ -1,177 +1,177 @@
BACnet MS/TP Capture Tool
This tool captures BACnet MS/TP packets on an RS485 serial interface,
and saves the packets to a file in Wireshark PCAP format for
the BACnet MS/TP dissector to read. The filename has a date and time
code in it, and will contain up to 65535 packets. A new file
will be created at each 65535 packet interval. The tool can
be stopped by using Control-C.
Here is a sample of the tool running (use CTRL-C to quit):
D:\code\bacnet-stack>bin\mstpcap.exe com54 38400
Adjusted interface name to \\.\COM54
mstpcap: Using \\.\COM54 for capture at 38400 bps.
mstpcap: saving capture to mstp_20110413134119.cap
1156 packets
==== MS/TP Frame Counts ====
MAC Tokens PFM RPFM DER Postpd DNER TestReq TestRsp
0 188 4 0 0 0 0 0 0
2 189 0 0 0 0 0 0 0
3 189 9 0 0 0 0 0 0
7 189 60 0 0 0 0 0 0
35 188 140 0 0 0 0 0 0
Node Count: 5
==== MS/TP Usage and Timing Maximums ====
MAC MaxMstr Retries Npoll Self Treply Tusage Trpfm Tder Tpostpd
0 1 0 52 0 11 24 0 0 0
2 0 0 0 0 23 0 0 0 0
3 6 0 50 0 5 100 0 0 0
7 34 0 52 0 5 34 0 0 0
35 127 0 50 0 6 63 0 0 0
Node Count: 5
Invalid Frame Count: 0
The files that are captured can also be scanned to give some statistics:
D:\code\bacnet-stack>bin\mstpcap.exe --scan mstp_20110413134119.cap
Scanning mstp_20110413134119.cap
1156 packets
==== MS/TP Frame Counts ====
MAC Tokens PFM RPFM DER Postpd DNER TestReq TestRsp
0 188 4 0 0 0 0 0 0
2 189 0 0 0 0 0 0 0
3 189 9 0 0 0 0 0 0
7 189 60 0 0 0 0 0 0
35 188 140 0 0 0 0 0 0
Node Count: 5
==== MS/TP Usage and Timing Maximums ====
MAC MaxMstr Retries Npoll Self Treply Tusage Trpfm Tder Tpostpd
0 1 0 52 0 11 24 0 0 0
2 0 0 0 0 23 0 0 0 0
3 6 0 50 0 5 100 0 0 0
7 34 0 52 0 5 34 0 0 0
35 127 0 50 0 6 63 0 0 0
Node Count: 5
Invalid Frame Count: 0
The BACnet MS/TP capture tool also includes statistics which are
listed for any MAC addresses found passing a token,
or any MAC address replying to a DER message.
The statistics are emitted when Control-C is pressed, or when
65535 packets are captured and the new file is created.
The statistics are cleared when the new file is created.
The statistics can be emitted from a file using the "--scan" option.
The MS/TP Frame counts use the following abbreviations:
Tokens = number of Token frames sent from this MAC address.
PFM = number of Poll-For-Master frames sent from this MAC address.
RPFM = number of Reply-To-Poll-For-Master frames sent from this MAC address.
DER = number of Data-Expecting-Reply frames sent from this MAC address.
Postpd = number of Reply-Postponed frames sent from this MAC address.
DNER = number of Data-Not-Expecting-Reply frames sent from this MAC address.
TestReq = number of Test-Request frames sent from this MAC address.
TestRsp = number of Test-Response frames sent from this MAC address.
The MS/TP Usage and Timing Maximums use the following abbreviations:
MaxMstr = highest destination MAC address during PFM
Retries = number of second tokens sent to this MAC address.
Npoll = number of Tokens between Poll-For-Master
Self = number of Tokens sent to self (Addendum 135-2008v)
Treply = maximum number of milliseconds it took to reply with
a token after receiving a token. Treply is required to be less
than 25ms (but the mstpcap tool may not have that good of
resolution on Windows).
Tusage = the maximum number of milliseconds the
device waits for a ReplyToPollForMaster or Token retry.
Tusage is required to be between 20ms and 100ms.
Trpfm = maximum number of milliseconds to respond to PFM with RPFM. It is
required to be less than 25ms.
Tder = maximum number of milliseconds that a device takes to
respond to a DataExpectingReply request. Tder is required to be less
than 250ms.
Tpostpd = maximum number of milliseconds to respond to
DataExpectingReply request with ReplyPostponed. Tpostpd is
required to be less than 250ms.
==== FTDI chip RS-485 converter 76800 baud tricks ====
If you are using FTDI chip in your RS485 converter, you can
alias an existing baud rate on Windows in the FTDIPORT.INF file
in order to acheive non-standard 76800 bps:
HKR,,"ConfigData",1,11,00,3F,3F,27,C0,00,00,27,00,00,00,C4,09,00,00,E2,04,00,00,71,02,00,00,38,41,00,00,9C,80,00,00,4E,C0,00,00,34,00,00,00,1A,00,00,00,0D,00,00,00,06,40,00,00,03,80,00,00,00,00,00,00,D0,80,00,00
replace the 10,27,00,00 => divisor = 10000, rate = 300 bps alias
hex values actual
----------- ---------
27,C0,00,00 - 76923 bps => divisor=39.125
27,00,00,00 - 76677 bps => divisor=39.000
Windows XP (from koby3101)
1) Plug in and locate your USB/RSS85 in Device Manager under ports. Right click
on it and select Properties. Click Details tab and from the drop down select
Device Instance Id.
2) Click Start, Run and then type regedit.
Follow this path in the registry
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\FTDIBUS
Locate the folder that has the same name as what you found earlier Device Instance
Id in step 1. Click on 0000 folder and then Device Parameters. On the right
side you will see ConfigData. Right click and select Modify Binary Data.
Locate the 10 27 which in my case were in 5th and 6th position and replace with
27 C0.
This will make the RS485 go to 76800 baud (76923 baud) baud when you ask it
to be 300 baud.
So to capture at 76800 baud type: mstpcap.exe COM2 300
Linux (used with Debian Lenny and Fedora 15)
http://www.connecttech.com/KnowledgeDatabase/kdb309.htm
As root:
Change USB so I can use it later as normal user:
# chmod 777 /dev/ttyUSB0 -
Print current info about the device:
# setserial /dev/ttyUSB0 a
/dev/ttyUSB0, Line 0, UART: unknown, Port: 0x0000, IRQ: 0
Baud_base: 24000000, close_delay: 0, divisor: 0
closing_wait: infinte
Flags: spd_normal low_latency
Make custom speed:
# setserial /dev/ttyUSB0 spd_cust
24000000/312 gives 76923 baudrate:
# setserial /dev/ttyUSB0 divisor 312
Print to make sure changes got applied:
# setserial /dev/ttyUSB0 a
/dev/ttyUSB0, Line 0, UART: unknown, Port: 0x0000, IRQ: 0
Baud_base: 24000000, close_delay: 0, divisor: 312
closing_wait: infinte
Flags: spd_cust low_latency
Now as normal user running the mstpcap which uses the default 38400 baud it
will actually capture at 76800 baud. (76923)
Just navigate (cd bin) to bin folder in the project and type:
$ ./mstpcap
BACnet MS/TP Capture Tool
This tool captures BACnet MS/TP packets on an RS485 serial interface,
and saves the packets to a file in Wireshark PCAP format for
the BACnet MS/TP dissector to read. The filename has a date and time
code in it, and will contain up to 65535 packets. A new file
will be created at each 65535 packet interval. The tool can
be stopped by using Control-C.
Here is a sample of the tool running (use CTRL-C to quit):
D:\code\bacnet-stack>bin\mstpcap.exe com54 38400
Adjusted interface name to \\.\COM54
mstpcap: Using \\.\COM54 for capture at 38400 bps.
mstpcap: saving capture to mstp_20110413134119.cap
1156 packets
==== MS/TP Frame Counts ====
MAC Tokens PFM RPFM DER Postpd DNER TestReq TestRsp
0 188 4 0 0 0 0 0 0
2 189 0 0 0 0 0 0 0
3 189 9 0 0 0 0 0 0
7 189 60 0 0 0 0 0 0
35 188 140 0 0 0 0 0 0
Node Count: 5
==== MS/TP Usage and Timing Maximums ====
MAC MaxMstr Retries Npoll Self Treply Tusage Trpfm Tder Tpostpd
0 1 0 52 0 11 24 0 0 0
2 0 0 0 0 23 0 0 0 0
3 6 0 50 0 5 100 0 0 0
7 34 0 52 0 5 34 0 0 0
35 127 0 50 0 6 63 0 0 0
Node Count: 5
Invalid Frame Count: 0
The files that are captured can also be scanned to give some statistics:
D:\code\bacnet-stack>bin\mstpcap.exe --scan mstp_20110413134119.cap
Scanning mstp_20110413134119.cap
1156 packets
==== MS/TP Frame Counts ====
MAC Tokens PFM RPFM DER Postpd DNER TestReq TestRsp
0 188 4 0 0 0 0 0 0
2 189 0 0 0 0 0 0 0
3 189 9 0 0 0 0 0 0
7 189 60 0 0 0 0 0 0
35 188 140 0 0 0 0 0 0
Node Count: 5
==== MS/TP Usage and Timing Maximums ====
MAC MaxMstr Retries Npoll Self Treply Tusage Trpfm Tder Tpostpd
0 1 0 52 0 11 24 0 0 0
2 0 0 0 0 23 0 0 0 0
3 6 0 50 0 5 100 0 0 0
7 34 0 52 0 5 34 0 0 0
35 127 0 50 0 6 63 0 0 0
Node Count: 5
Invalid Frame Count: 0
The BACnet MS/TP capture tool also includes statistics which are
listed for any MAC addresses found passing a token,
or any MAC address replying to a DER message.
The statistics are emitted when Control-C is pressed, or when
65535 packets are captured and the new file is created.
The statistics are cleared when the new file is created.
The statistics can be emitted from a file using the "--scan" option.
The MS/TP Frame counts use the following abbreviations:
Tokens = number of Token frames sent from this MAC address.
PFM = number of Poll-For-Master frames sent from this MAC address.
RPFM = number of Reply-To-Poll-For-Master frames sent from this MAC address.
DER = number of Data-Expecting-Reply frames sent from this MAC address.
Postpd = number of Reply-Postponed frames sent from this MAC address.
DNER = number of Data-Not-Expecting-Reply frames sent from this MAC address.
TestReq = number of Test-Request frames sent from this MAC address.
TestRsp = number of Test-Response frames sent from this MAC address.
The MS/TP Usage and Timing Maximums use the following abbreviations:
MaxMstr = highest destination MAC address during PFM
Retries = number of second tokens sent to this MAC address.
Npoll = number of Tokens between Poll-For-Master
Self = number of Tokens sent to self (Addendum 135-2008v)
Treply = maximum number of milliseconds it took to reply with
a token after receiving a token. Treply is required to be less
than 25ms (but the mstpcap tool may not have that good of
resolution on Windows).
Tusage = the maximum number of milliseconds the
device waits for a ReplyToPollForMaster or Token retry.
Tusage is required to be between 20ms and 100ms.
Trpfm = maximum number of milliseconds to respond to PFM with RPFM. It is
required to be less than 25ms.
Tder = maximum number of milliseconds that a device takes to
respond to a DataExpectingReply request. Tder is required to be less
than 250ms.
Tpostpd = maximum number of milliseconds to respond to
DataExpectingReply request with ReplyPostponed. Tpostpd is
required to be less than 250ms.
==== FTDI chip RS-485 converter 76800 baud tricks ====
If you are using FTDI chip in your RS485 converter, you can
alias an existing baud rate on Windows in the FTDIPORT.INF file
in order to acheive non-standard 76800 bps:
HKR,,"ConfigData",1,11,00,3F,3F,27,C0,00,00,27,00,00,00,C4,09,00,00,E2,04,00,00,71,02,00,00,38,41,00,00,9C,80,00,00,4E,C0,00,00,34,00,00,00,1A,00,00,00,0D,00,00,00,06,40,00,00,03,80,00,00,00,00,00,00,D0,80,00,00
replace the 10,27,00,00 => divisor = 10000, rate = 300 bps alias
hex values actual
----------- ---------
27,C0,00,00 - 76923 bps => divisor=39.125
27,00,00,00 - 76677 bps => divisor=39.000
Windows XP (from koby3101)
1) Plug in and locate your USB/RSS85 in Device Manager under ports. Right click
on it and select Properties. Click Details tab and from the drop down select
Device Instance Id.
2) Click Start, Run and then type regedit.
Follow this path in the registry
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\FTDIBUS
Locate the folder that has the same name as what you found earlier Device Instance
Id in step 1. Click on 0000 folder and then Device Parameters. On the right
side you will see ConfigData. Right click and select Modify Binary Data.
Locate the 10 27 which in my case were in 5th and 6th position and replace with
27 C0.
This will make the RS485 go to 76800 baud (76923 baud) baud when you ask it
to be 300 baud.
So to capture at 76800 baud type: mstpcap.exe COM2 300
Linux (used with Debian Lenny and Fedora 15)
http://www.connecttech.com/KnowledgeDatabase/kdb309.htm
As root:
Change USB so I can use it later as normal user:
# chmod 777 /dev/ttyUSB0 -
Print current info about the device:
# setserial /dev/ttyUSB0 a
/dev/ttyUSB0, Line 0, UART: unknown, Port: 0x0000, IRQ: 0
Baud_base: 24000000, close_delay: 0, divisor: 0
closing_wait: infinte
Flags: spd_normal low_latency
Make custom speed:
# setserial /dev/ttyUSB0 spd_cust
24000000/312 gives 76923 baudrate:
# setserial /dev/ttyUSB0 divisor 312
Print to make sure changes got applied:
# setserial /dev/ttyUSB0 a
/dev/ttyUSB0, Line 0, UART: unknown, Port: 0x0000, IRQ: 0
Baud_base: 24000000, close_delay: 0, divisor: 312
closing_wait: infinte
Flags: spd_cust low_latency
Now as normal user running the mstpcap which uses the default 38400 baud it
will actually capture at 76800 baud. (76923)
Just navigate (cd bin) to bin folder in the project and type:
$ ./mstpcap
+9 -9
View File
@@ -1,9 +1,9 @@
@echo off
echo Build with MinGW and MSYS: mingw.sourceforge.net
rem set PATH=C:\MinGW\msys\1.0\bin;C:\MinGW\bin
rem assumes rm, cp, size are already in path
set CC=gcc
set AR=ar
set MAKE=make
set TARGET_EXT=.exe
make clean all
@echo off
echo Build with MinGW and MSYS: mingw.sourceforge.net
rem set PATH=C:\MinGW\msys\1.0\bin;C:\MinGW\bin
rem assumes rm, cp, size are already in path
set CC=gcc
set AR=ar
set MAKE=make
set TARGET_EXT=.exe
make clean all
+17 -17
View File
@@ -1,20 +1,20 @@
BACnet MS/TP CRC Calculator
BACnet MS/TP CRC Calculator
This tool receives MS/TP bytes and generates a CRC for those bytes
mstpcrc [options] <00 00 00 00...>
perform MS/TP CRC on data bytes.
options:
[-x] interprete the arguments as ascii hex (default)
[-d] interprete the argument as ascii decimal
[-8] calculate the MS/TP 8-bit Header CRC (default)
[-16] calculate the MS/TP 16-bit Data CRC
Here is a sample of the tool running (use CTRL-C to quit):
D:\code\bacnet-stack\demo\mstpcrc>mstpcrc 06 ff 01 00 15
0x06
0xFF
0x01
0x00
0x15
mstpcrc [options] <00 00 00 00...>
perform MS/TP CRC on data bytes.
options:
[-x] interprete the arguments as ascii hex (default)
[-d] interprete the argument as ascii decimal
[-8] calculate the MS/TP 8-bit Header CRC (default)
[-16] calculate the MS/TP 16-bit Data CRC
Here is a sample of the tool running (use CTRL-C to quit):
D:\code\bacnet-stack\demo\mstpcrc>mstpcrc 06 ff 01 00 15
0x06
0xFF
0x01
0x00
0x15
0x8E Header CRC
+6
View File
@@ -112,6 +112,12 @@ extern "C" {
uint32_t object_instance,
float value);
bool Analog_Input_Out_Of_Service(
uint32_t object_instance);
void Analog_Input_Out_Of_Service_Set(
uint32_t object_instance,
bool oos_flag);
/* note: header of Intrinsic_Reporting function is required
even when INTRINSIC_REPORTING is not defined */
void Analog_Input_Intrinsic_Reporting(
File diff suppressed because it is too large Load Diff
+94 -94
View File
@@ -1,94 +1,94 @@
/**************************************************************************
*
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef CSV_H
#define CSV_H
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "rp.h"
#include "wp.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void CharacterString_Value_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool CharacterString_Value_Valid_Instance(
uint32_t object_instance);
unsigned CharacterString_Value_Count(
void);
uint32_t CharacterString_Value_Index_To_Instance(
unsigned index);
unsigned CharacterString_Value_Instance_To_Index(
uint32_t instance);
int CharacterString_Value_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata);
bool CharacterString_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data);
/* optional API */
bool CharacterString_Value_Object_Instance_Add(
uint32_t instance);
bool CharacterString_Value_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name);
bool CharacterString_Value_Name_Set(
uint32_t object_instance,
char *new_name);
bool CharacterString_Value_Present_Value(
uint32_t object_instance,
BACNET_CHARACTER_STRING * value);
bool CharacterString_Value_Present_Value_Set(
uint32_t object_instance,
BACNET_CHARACTER_STRING * value);
bool CharacterString_Value_Description_Set(
uint32_t object_instance,
char *text_string);
void CharacterString_Value_Init(
void);
#ifdef TEST
#include "ctest.h"
void testCharacterStringValue(
Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef CSV_H
#define CSV_H
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "rp.h"
#include "wp.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void CharacterString_Value_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool CharacterString_Value_Valid_Instance(
uint32_t object_instance);
unsigned CharacterString_Value_Count(
void);
uint32_t CharacterString_Value_Index_To_Instance(
unsigned index);
unsigned CharacterString_Value_Instance_To_Index(
uint32_t instance);
int CharacterString_Value_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata);
bool CharacterString_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data);
/* optional API */
bool CharacterString_Value_Object_Instance_Add(
uint32_t instance);
bool CharacterString_Value_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name);
bool CharacterString_Value_Name_Set(
uint32_t object_instance,
char *new_name);
bool CharacterString_Value_Present_Value(
uint32_t object_instance,
BACNET_CHARACTER_STRING * value);
bool CharacterString_Value_Present_Value_Set(
uint32_t object_instance,
BACNET_CHARACTER_STRING * value);
bool CharacterString_Value_Description_Set(
uint32_t object_instance,
char *text_string);
void CharacterString_Value_Init(
void);
#ifdef TEST
#include "ctest.h"
void testCharacterStringValue(
Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
File diff suppressed because it is too large Load Diff
+107 -107
View File
@@ -1,107 +1,107 @@
/**************************************************************************
*
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef MULTISTATE_VALUE_H
#define MULTISTATE_VALUE_H
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "rp.h"
#include "wp.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void Multistate_Value_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool Multistate_Value_Valid_Instance(
uint32_t object_instance);
unsigned Multistate_Value_Count(
void);
uint32_t Multistate_Value_Index_To_Instance(
unsigned index);
unsigned Multistate_Value_Instance_To_Index(
uint32_t instance);
int Multistate_Value_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata);
bool Multistate_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data);
/* optional API */
bool Multistate_Value_Object_Instance_Add(
uint32_t instance);
bool Multistate_Value_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name);
bool Multistate_Value_Name_Set(
uint32_t object_instance,
char *new_name);
uint32_t Multistate_Value_Present_Value(
uint32_t object_instance);
bool Multistate_Value_Present_Value_Set(
uint32_t object_instance,
uint32_t value);
bool Multistate_Value_Out_Of_Service(
uint32_t object_instance);
void Multistate_Value_Out_Of_Service_Set(
uint32_t object_instance,
bool value);
bool Multistate_Value_Description_Set(
uint32_t object_instance,
char *text_string);
bool Multistate_Value_State_Text_Set(
uint32_t object_instance,
uint32_t state_index,
char *new_name);
bool Multistate_Value_Max_States_Set(
uint32_t instance,
uint32_t max_states_requested);
void Multistate_Value_Init(
void);
#ifdef TEST
#include "ctest.h"
void testMultistateValue(
Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
/**************************************************************************
*
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef MULTISTATE_VALUE_H
#define MULTISTATE_VALUE_H
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "rp.h"
#include "wp.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void Multistate_Value_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool Multistate_Value_Valid_Instance(
uint32_t object_instance);
unsigned Multistate_Value_Count(
void);
uint32_t Multistate_Value_Index_To_Instance(
unsigned index);
unsigned Multistate_Value_Instance_To_Index(
uint32_t instance);
int Multistate_Value_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata);
bool Multistate_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data);
/* optional API */
bool Multistate_Value_Object_Instance_Add(
uint32_t instance);
bool Multistate_Value_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name);
bool Multistate_Value_Name_Set(
uint32_t object_instance,
char *new_name);
uint32_t Multistate_Value_Present_Value(
uint32_t object_instance);
bool Multistate_Value_Present_Value_Set(
uint32_t object_instance,
uint32_t value);
bool Multistate_Value_Out_Of_Service(
uint32_t object_instance);
void Multistate_Value_Out_Of_Service_Set(
uint32_t object_instance,
bool value);
bool Multistate_Value_Description_Set(
uint32_t object_instance,
char *text_string);
bool Multistate_Value_State_Text_Set(
uint32_t object_instance,
uint32_t state_index,
char *new_name);
bool Multistate_Value_Max_States_Set(
uint32_t instance,
uint32_t max_states_requested);
void Multistate_Value_Init(
void);
#ifdef TEST
#include "ctest.h"
void testMultistateValue(
Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+20 -20
View File
@@ -1,20 +1,20 @@
The BACnet Scriptable (using Perl) Tool.
* Running this tool assumes that the library has been already built. The
library should be built with a command similar to
CC=/mingw/bin/gcc BACNET_DEFINES="-DPRINT_ENABLED -DBACAPP_ALL -DBACFILE
-DINTRINSIC_REPORTING" BBMD_DEFINE=-DBBMD_ENABLED\=1 BACNET_PORT=win32 make
clean library
* Currently, the tool assumes only win32 port, but should be easily modifiable
for any port build.
* This tool has to be run from a path without any spaces. The presence of the
.Inline directory is required.
* Run the tool without any arguments to see usage instructions
* To run the example ReapProperty script (which reads Analog Value 0 Present
Value) for Device at instance 1234 run the following command
perl bacnet.pl --script example_readprop.pl -- 1234
The BACnet Scriptable (using Perl) Tool.
* Running this tool assumes that the library has been already built. The
library should be built with a command similar to
CC=/mingw/bin/gcc BACNET_DEFINES="-DPRINT_ENABLED -DBACAPP_ALL -DBACFILE
-DINTRINSIC_REPORTING" BBMD_DEFINE=-DBBMD_ENABLED\=1 BACNET_PORT=win32 make
clean library
* Currently, the tool assumes only win32 port, but should be easily modifiable
for any port build.
* This tool has to be run from a path without any spaces. The presence of the
.Inline directory is required.
* Run the tool without any arguments to see usage instructions
* To run the example ReapProperty script (which reads Analog Value 0 Present
Value) for Device at instance 1234 run the following command
perl bacnet.pl --script example_readprop.pl -- 1234
+44 -44
View File
@@ -1,44 +1,44 @@
#Makefile to build BACnet Application using GCC compiler
# tools - only if you need them.
# Most platforms have this already defined
# CC = gcc
# AR = ar
# MAKE = make
# SIZE = size
#
# Assumes rm and cp are available
# Executable file name
TARGET = ptransfer
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
size $@
cp $@ ../../bin
lib: ${BACNET_LIB_TARGET}
${BACNET_LIB_TARGET}:
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -rf core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET}
include: .depend
#Makefile to build BACnet Application using GCC compiler
# tools - only if you need them.
# Most platforms have this already defined
# CC = gcc
# AR = ar
# MAKE = make
# SIZE = size
#
# Assumes rm and cp are available
# Executable file name
TARGET = ptransfer
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
size $@
cp $@ ../../bin
lib: ${BACNET_LIB_TARGET}
${BACNET_LIB_TARGET}:
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -rf core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET}
include: .depend
+139 -139
View File
@@ -1,139 +1,139 @@
#
# Simple makefile to build an executable for Win32
#
# This makefile assumes Borland bcc32 development environment
# on Windows NT/9x/2000/XP
#
!ifndef BORLAND_DIR
BORLAND_DIR_Not_Defined:
@echo .
@echo You must define environment variable BORLAND_DIR to compile.
!endif
PRODUCT = ptransfer
PRODUCT_EXE = $(PRODUCT).exe
# tools
CC = $(BORLAND_DIR)\bin\bcc32
MAKE=$(BORLAND_DIR)\bin\make.exe
#LINK = $(BORLAND_DIR)\bin\tlink32
LINK = $(BORLAND_DIR)\bin\ilink32
BACNET_LIB_DIR = ..\..\lib
BACNET_LIB = $(BACNET_LIB_DIR)\bacnet.lib
# directories
BACNET_PORT = ..\..\ports\win32
BACNET_INCLUDE = ..\..\include
BACNET_OBJECT = ..\object
BACNET_HANDLER = ..\handler
INCLUDES = \
-I$(BACNET_INCLUDE) \
-I$(BACNET_PORT) \
-I$(BACNET_OBJECT) \
-I$(BACNET_HANDLER) \
-I$(BORLAND_DIR)\include
#
BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
#BACDL_DEFINE=-DBACDL_MSTP=1
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
#
# Compiler definitions
#
BCC_CFG = bcc32.cfg
#
# Include directories
#
CFLAGS = $(INCLUDES) $(DEFINES)
#
# Libraries
#
C_LIB_DIR = $(BORLAND_DIR)\lib
LIBS = $(BACNET_LIB) \
$(C_LIB_DIR)\IMPORT32.lib \
$(C_LIB_DIR)\CW32MT.lib \
#
# Main target
#
# This should be the first one in the makefile
all : $(BACNET_LIB) $(BCC_CFG) $(OBJS) $(PRODUCT_EXE)
del $(BCC_CFG)
install: $(PRODUCT_EXE)
copy $(PRODUCT_EXE) ..\..\bin\$(PRODUCT_EXE)
# Linker specific: the link below is for BCC linker/compiler. If you link
# with a different linker - please change accordingly.
#
# need a temp response file (@&&| ... |) because command line is too long
# $** lists each dependency
# $< target name
# $* target name without extension
$(PRODUCT_EXE) : $(OBJS)
@echo Running Linker for $(PRODUCT_EXE)
$(LINK) -L$(C_LIB_DIR) -L$(BACNET_LIB_DIR) -m -c -s -v @&&|
$(BORLAND_DIR)\lib\c0x32.obj $**
$<
$*.map
$(LIBS)
|
#
# Utilities
clean :
del $(OBJS)
del $(PRODUCT_EXE)
del $(PRODUCT).map
del $(PRODUCT).ilc
del $(PRODUCT).ild
del $(PRODUCT).ilf
del $(PRODUCT).ils
del $(PRODUCT).tds
del $(BCC_CFG)
#
# Generic rules
#
.SUFFIXES: .cpp .c .sbr .obj
#
# cc generic rule
#
.c.obj:
$(CC) +$(BCC_CFG) -o$@ $<
# Compiler configuration file
$(BCC_CFG) :
Copy &&|
$(CFLAGS)
-c
-y #include line numbers in OBJ's
-v #include debug info
-w+ #turn on all warnings
-Od #disable all optimizations
#-a4 #32 bit data alignment
#-M # generate link map
#-ls # linker options
#-WM- #not multithread
-WM #multithread
-w-aus # ignore warning assigned a value that is never used
-w-sig # ignore warning conversion may lose sig digits
| $@
# EOF: makefile
#
# Simple makefile to build an executable for Win32
#
# This makefile assumes Borland bcc32 development environment
# on Windows NT/9x/2000/XP
#
!ifndef BORLAND_DIR
BORLAND_DIR_Not_Defined:
@echo .
@echo You must define environment variable BORLAND_DIR to compile.
!endif
PRODUCT = ptransfer
PRODUCT_EXE = $(PRODUCT).exe
# tools
CC = $(BORLAND_DIR)\bin\bcc32
MAKE=$(BORLAND_DIR)\bin\make.exe
#LINK = $(BORLAND_DIR)\bin\tlink32
LINK = $(BORLAND_DIR)\bin\ilink32
BACNET_LIB_DIR = ..\..\lib
BACNET_LIB = $(BACNET_LIB_DIR)\bacnet.lib
# directories
BACNET_PORT = ..\..\ports\win32
BACNET_INCLUDE = ..\..\include
BACNET_OBJECT = ..\object
BACNET_HANDLER = ..\handler
INCLUDES = \
-I$(BACNET_INCLUDE) \
-I$(BACNET_PORT) \
-I$(BACNET_OBJECT) \
-I$(BACNET_HANDLER) \
-I$(BORLAND_DIR)\include
#
BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
#BACDL_DEFINE=-DBACDL_MSTP=1
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
#
# Compiler definitions
#
BCC_CFG = bcc32.cfg
#
# Include directories
#
CFLAGS = $(INCLUDES) $(DEFINES)
#
# Libraries
#
C_LIB_DIR = $(BORLAND_DIR)\lib
LIBS = $(BACNET_LIB) \
$(C_LIB_DIR)\IMPORT32.lib \
$(C_LIB_DIR)\CW32MT.lib \
#
# Main target
#
# This should be the first one in the makefile
all : $(BACNET_LIB) $(BCC_CFG) $(OBJS) $(PRODUCT_EXE)
del $(BCC_CFG)
install: $(PRODUCT_EXE)
copy $(PRODUCT_EXE) ..\..\bin\$(PRODUCT_EXE)
# Linker specific: the link below is for BCC linker/compiler. If you link
# with a different linker - please change accordingly.
#
# need a temp response file (@&&| ... |) because command line is too long
# $** lists each dependency
# $< target name
# $* target name without extension
$(PRODUCT_EXE) : $(OBJS)
@echo Running Linker for $(PRODUCT_EXE)
$(LINK) -L$(C_LIB_DIR) -L$(BACNET_LIB_DIR) -m -c -s -v @&&|
$(BORLAND_DIR)\lib\c0x32.obj $**
$<
$*.map
$(LIBS)
|
#
# Utilities
clean :
del $(OBJS)
del $(PRODUCT_EXE)
del $(PRODUCT).map
del $(PRODUCT).ilc
del $(PRODUCT).ild
del $(PRODUCT).ilf
del $(PRODUCT).ils
del $(PRODUCT).tds
del $(BCC_CFG)
#
# Generic rules
#
.SUFFIXES: .cpp .c .sbr .obj
#
# cc generic rule
#
.c.obj:
$(CC) +$(BCC_CFG) -o$@ $<
# Compiler configuration file
$(BCC_CFG) :
Copy &&|
$(CFLAGS)
-c
-y #include line numbers in OBJ's
-v #include debug info
-w+ #turn on all warnings
-Od #disable all optimizations
#-a4 #32 bit data alignment
#-M # generate link map
#-ls # linker options
#-WM- #not multithread
-WM #multithread
-w-aus # ignore warning assigned a value that is never used
-w-sig # ignore warning conversion may lose sig digits
| $@
# EOF: makefile
+5 -5
View File
@@ -1,9 +1,9 @@
#Makefile to build BACnet Application for the Linux Port
# tools - only if you need them.
# Most platforms have this already defined
# CC = gcc
# tools - only if you need them.
# Most platforms have this already defined
# CC = gcc
# Executable file name
TARGET = bacrpm
+139 -139
View File
@@ -1,139 +1,139 @@
#
# Simple makefile to build an executable for Win32
#
# This makefile assumes Borland bcc32 development environment
# on Windows NT/9x/2000/XP
#
!ifndef BORLAND_DIR
BORLAND_DIR_Not_Defined:
@echo .
@echo You must define environment variable BORLAND_DIR to compile.
!endif
PRODUCT = bacrr
PRODUCT_EXE = $(PRODUCT).exe
# tools
CC = $(BORLAND_DIR)\bin\bcc32
MAKE=$(BORLAND_DIR)\bin\make.exe
#LINK = $(BORLAND_DIR)\bin\tlink32
LINK = $(BORLAND_DIR)\bin\ilink32
BACNET_LIB_DIR = ..\..\lib
BACNET_LIB = $(BACNET_LIB_DIR)\bacnet.lib
# directories
BACNET_PORT = ..\..\ports\win32
BACNET_INCLUDE = ..\..\include
BACNET_OBJECT = ..\object
BACNET_HANDLER = ..\handler
INCLUDES = \
-I$(BACNET_INCLUDE) \
-I$(BACNET_PORT) \
-I$(BACNET_OBJECT) \
-I$(BACNET_HANDLER) \
-I$(BORLAND_DIR)\include
#
BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
#BACDL_DEFINE=-DBACDL_MSTP=1
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
#
# Compiler definitions
#
BCC_CFG = bcc32.cfg
#
# Include directories
#
CFLAGS = $(INCLUDES) $(DEFINES)
#
# Libraries
#
C_LIB_DIR = $(BORLAND_DIR)\lib
LIBS = $(BACNET_LIB) \
$(C_LIB_DIR)\IMPORT32.lib \
$(C_LIB_DIR)\CW32MT.lib \
#
# Main target
#
# This should be the first one in the makefile
all : $(BACNET_LIB) $(BCC_CFG) $(OBJS) $(PRODUCT_EXE)
del $(BCC_CFG)
install: $(PRODUCT_EXE)
copy $(PRODUCT_EXE) ..\..\bin\$(PRODUCT_EXE)
# Linker specific: the link below is for BCC linker/compiler. If you link
# with a different linker - please change accordingly.
#
# need a temp response file (@&&| ... |) because command line is too long
# $** lists each dependency
# $< target name
# $* target name without extension
$(PRODUCT_EXE) : $(OBJS)
@echo Running Linker for $(PRODUCT_EXE)
$(LINK) -L$(C_LIB_DIR) -L$(BACNET_LIB_DIR) -m -c -s -v @&&|
$(BORLAND_DIR)\lib\c0x32.obj $**
$<
$*.map
$(LIBS)
|
#
# Utilities
clean :
del $(OBJS)
del $(PRODUCT_EXE)
del $(PRODUCT).map
del $(PRODUCT).ilc
del $(PRODUCT).ild
del $(PRODUCT).ilf
del $(PRODUCT).ils
del $(PRODUCT).tds
del $(BCC_CFG)
#
# Generic rules
#
.SUFFIXES: .cpp .c .sbr .obj
#
# cc generic rule
#
.c.obj:
$(CC) +$(BCC_CFG) -o$@ $<
# Compiler configuration file
$(BCC_CFG):
Copy &&|
$(CFLAGS)
-c
-y #include line numbers in OBJ's
-v #include debug info
-w+ #turn on all warnings
-Od #disable all optimizations
#-a4 #32 bit data alignment
#-M # generate link map
#-ls # linker options
#-WM- #not multithread
-WM #multithread
-w-aus # ignore warning assigned a value that is never used
-w-sig # ignore warning conversion may lose sig digits
| $@
# EOF: makefile
#
# Simple makefile to build an executable for Win32
#
# This makefile assumes Borland bcc32 development environment
# on Windows NT/9x/2000/XP
#
!ifndef BORLAND_DIR
BORLAND_DIR_Not_Defined:
@echo .
@echo You must define environment variable BORLAND_DIR to compile.
!endif
PRODUCT = bacrr
PRODUCT_EXE = $(PRODUCT).exe
# tools
CC = $(BORLAND_DIR)\bin\bcc32
MAKE=$(BORLAND_DIR)\bin\make.exe
#LINK = $(BORLAND_DIR)\bin\tlink32
LINK = $(BORLAND_DIR)\bin\ilink32
BACNET_LIB_DIR = ..\..\lib
BACNET_LIB = $(BACNET_LIB_DIR)\bacnet.lib
# directories
BACNET_PORT = ..\..\ports\win32
BACNET_INCLUDE = ..\..\include
BACNET_OBJECT = ..\object
BACNET_HANDLER = ..\handler
INCLUDES = \
-I$(BACNET_INCLUDE) \
-I$(BACNET_PORT) \
-I$(BACNET_OBJECT) \
-I$(BACNET_HANDLER) \
-I$(BORLAND_DIR)\include
#
BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
#BACDL_DEFINE=-DBACDL_MSTP=1
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
#
# Compiler definitions
#
BCC_CFG = bcc32.cfg
#
# Include directories
#
CFLAGS = $(INCLUDES) $(DEFINES)
#
# Libraries
#
C_LIB_DIR = $(BORLAND_DIR)\lib
LIBS = $(BACNET_LIB) \
$(C_LIB_DIR)\IMPORT32.lib \
$(C_LIB_DIR)\CW32MT.lib \
#
# Main target
#
# This should be the first one in the makefile
all : $(BACNET_LIB) $(BCC_CFG) $(OBJS) $(PRODUCT_EXE)
del $(BCC_CFG)
install: $(PRODUCT_EXE)
copy $(PRODUCT_EXE) ..\..\bin\$(PRODUCT_EXE)
# Linker specific: the link below is for BCC linker/compiler. If you link
# with a different linker - please change accordingly.
#
# need a temp response file (@&&| ... |) because command line is too long
# $** lists each dependency
# $< target name
# $* target name without extension
$(PRODUCT_EXE) : $(OBJS)
@echo Running Linker for $(PRODUCT_EXE)
$(LINK) -L$(C_LIB_DIR) -L$(BACNET_LIB_DIR) -m -c -s -v @&&|
$(BORLAND_DIR)\lib\c0x32.obj $**
$<
$*.map
$(LIBS)
|
#
# Utilities
clean :
del $(OBJS)
del $(PRODUCT_EXE)
del $(PRODUCT).map
del $(PRODUCT).ilc
del $(PRODUCT).ild
del $(PRODUCT).ilf
del $(PRODUCT).ils
del $(PRODUCT).tds
del $(BCC_CFG)
#
# Generic rules
#
.SUFFIXES: .cpp .c .sbr .obj
#
# cc generic rule
#
.c.obj:
$(CC) +$(BCC_CFG) -o$@ $<
# Compiler configuration file
$(BCC_CFG):
Copy &&|
$(CFLAGS)
-c
-y #include line numbers in OBJ's
-v #include debug info
-w+ #turn on all warnings
-Od #disable all optimizations
#-a4 #32 bit data alignment
#-M # generate link map
#-ls # linker options
#-WM- #not multithread
-WM #multithread
-w-aus # ignore warning assigned a value that is never used
-w-sig # ignore warning conversion may lose sig digits
| $@
# EOF: makefile
+44 -44
View File
@@ -1,44 +1,44 @@
#Makefile to build BACnet Application using GCC compiler
# tools - only if you need them.
# Most platforms have this already defined
# CC = gcc
# AR = ar
# MAKE = make
# SIZE = size
#
# Assumes rm and cp are available
# Executable file name
TARGET = bacscov
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
size $@
cp $@ ../../bin
lib: ${BACNET_LIB_TARGET}
${BACNET_LIB_TARGET}:
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -rf core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET}
include: .depend
#Makefile to build BACnet Application using GCC compiler
# tools - only if you need them.
# Most platforms have this already defined
# CC = gcc
# AR = ar
# MAKE = make
# SIZE = size
#
# Assumes rm and cp are available
# Executable file name
TARGET = bacscov
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
size $@
cp $@ ../../bin
lib: ${BACNET_LIB_TARGET}
${BACNET_LIB_TARGET}:
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -rf core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET}
include: .depend
+394 -394
View File
@@ -1,394 +1,394 @@
/*************************************************************************
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* command line tool that sends a BACnet service, and displays the reply */
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h> /* for time */
#include <ctype.h> /* for toupper */
#define PRINT_ENABLED 1
#include "bacdef.h"
#include "config.h"
#include "bactext.h"
#include "bacerror.h"
#include "iam.h"
#include "arf.h"
#include "tsm.h"
#include "address.h"
#include "npdu.h"
#include "apdu.h"
#include "device.h"
#include "net.h"
#include "datalink.h"
#include "whois.h"
/* some demo stuff needed */
#include "filename.h"
#include "handlers.h"
#include "client.h"
#include "txbuf.h"
#include "dlenv.h"
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
/* converted command line arguments */
static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE;
/* Process identifier for matching replies */
static uint32_t Target_Device_Process_Identifier = 0;
/* the invoke id is needed to filter incoming messages */
static uint8_t Request_Invoke_ID = 0;
/* MAC and SNET address of target */
static BACNET_ADDRESS Target_Address;
/* indication of error, reject, or abort */
static bool Error_Detected = false;
/* data used in COV subscription request */
BACNET_SUBSCRIBE_COV_DATA *COV_Subscribe_Data = NULL;
static void MyErrorHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
{
if (address_match(&Target_Address, src) &&
(invoke_id == Request_Invoke_ID)) {
printf("BACnet Error: %s: %s\r\n",
bactext_error_class_name((int) error_class),
bactext_error_code_name((int) error_code));
Error_Detected = true;
}
}
void MyAbortHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
{
(void) server;
if (address_match(&Target_Address, src) &&
(invoke_id == Request_Invoke_ID)) {
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name((int) abort_reason));
Error_Detected = true;
}
}
void MyRejectHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t reject_reason)
{
if (address_match(&Target_Address, src) &&
(invoke_id == Request_Invoke_ID)) {
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name((int) reject_reason));
Error_Detected = true;
}
}
static void Init_Service_Handlers(
void)
{
Device_Init(NULL);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the data coming back from COV subscriptions */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_COV_NOTIFICATION,
handler_ccov_notification);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_COV_NOTIFICATION,
handler_ucov_notification);
/* handle any errors coming back */
apdu_set_error_handler(SERVICE_CONFIRMED_SUBSCRIBE_COV, MyErrorHandler);
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
void cleanup(
void)
{
BACNET_SUBSCRIBE_COV_DATA *cov_data = NULL;
BACNET_SUBSCRIBE_COV_DATA *cov_data_old = NULL;
cov_data = COV_Subscribe_Data;
while (cov_data) {
cov_data_old = cov_data;
cov_data = cov_data->next;
free(cov_data_old);
}
}
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = {
0
}; /* address where message came from */
uint16_t pdu_len = 0;
unsigned timeout = 100; /* milliseconds */
unsigned max_apdu = 0;
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
time_t delta_seconds = 0;
bool found = false;
char *filename = NULL;
bool print_usage_terse = false;
bool print_usage_verbose = false;
BACNET_SUBSCRIBE_COV_DATA *cov_data = NULL;
int argi = 0;
int arg_remaining = 0;
if (argc < 6) {
print_usage_terse = true;
}
if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
print_usage_terse = true;
print_usage_verbose = true;
}
if (print_usage_terse) {
filename = filename_remove_path(argv[0]);
printf("Usage: %s device-id object-type object-instance "
"process-id <confirmed lifetime|cancel>\r\n",
filename);
if (!print_usage_verbose) {
return 0;
}
}
if (print_usage_verbose) {
printf("\r\n"
"device-id:\r\n"
"The subscriber BACnet Device Object Instance number.\r\n"
"\r\n"
"object-type:\r\n"
"The monitored object type is the integer value of the\r\n"
"enumeration BACNET_OBJECT_TYPE in bacenum.h. For example,\r\n"
"if you were monitoring Analog Output 2, the object-type\r\n"
"would be 1.\r\n"
"\r\n"
"object-instance:\r\n"
"The monitored object instance number.\r\n"
"\r\n"
"process-id:\r\n"
"Process Identifier for this COV subscription.\r\n"
"\r\n"
"confirmed:\r\n"
"Optional flag to subscribe using Confirmed notifications.\r\n"
"Use the word \'confirmed\' or \'unconfirmed\'.\r\n"
"\r\n"
"lifetime:\r\n"
"Optional subscription lifetime is conveyed in seconds.\r\n"
"\r\n"
"cancel:\r\n"
"Use the word \'cancel\' instead of confirm and lifetime.\r\n"
"This shall indicate a cancellation request.\r\n"
"\r\n"
"Example:\r\n"
"If you want subscribe to Device 123 Analog Input 9 object\r\n"
"using confirmed COV notifications for 5 minutes,\r\n"
"you could send the following command:\r\n"
"%s 123 0 9 1 confirmed 600\r\n"
"To send the same COV subscription request for unconfirmed\r\n"
"notifications, send the following command:\r\n"
"%s 123 0 9 1 unconfirmed 600\r\n"
"To cancel the same COV subscription request,\r\n"
"send the following command:\r\n"
"%s 123 0 9 1 cancel\r\n",
filename, filename, filename);
return 0;
}
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
return 1;
}
atexit(cleanup);
COV_Subscribe_Data = calloc(1, sizeof(BACNET_SUBSCRIBE_COV_DATA));
cov_data = COV_Subscribe_Data;
argi = 2;
while (cov_data) {
cov_data->monitoredObjectIdentifier.type =
strtol(argv[argi], NULL, 0);
if (cov_data->monitoredObjectIdentifier.type >= MAX_BACNET_OBJECT_TYPE) {
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
cov_data->monitoredObjectIdentifier.type, MAX_BACNET_OBJECT_TYPE);
return 1;
}
argi++;
cov_data->monitoredObjectIdentifier.instance =
strtol(argv[argi], NULL, 0);
if (cov_data->monitoredObjectIdentifier.instance > BACNET_MAX_INSTANCE) {
fprintf(stderr, "object-instance=%u - it must be less than %u\r\n",
cov_data->monitoredObjectIdentifier.instance,
BACNET_MAX_INSTANCE + 1);
return 1;
}
argi++;
cov_data->subscriberProcessIdentifier =
strtol(argv[argi], NULL, 0);
argi++;
if (strcmp(argv[argi],"cancel") == 0) {
cov_data->cancellationRequest = true;
argi++;
} else {
cov_data->cancellationRequest = false;
if (strcmp(argv[argi],"confirmed") == 0) {
cov_data->issueConfirmedNotifications = true;
} else if (strcmp(argv[argi],"unconfirmed") == 0) {
cov_data->issueConfirmedNotifications = false;
} else {
fprintf(stderr, "unknown option: %s\r\n",
argv[argi]);
return 1;
}
argi++;
arg_remaining = argc - argi;
if (arg_remaining > 0) {
cov_data->lifetime = strtol(argv[argi], NULL, 0);
argi++;
} else {
cov_data->lifetime = 0;
}
}
arg_remaining = argc - argi;
if (arg_remaining < 5) {
break;
} else {
cov_data->next = calloc(1, sizeof(BACNET_SUBSCRIBE_COV_DATA));
cov_data = cov_data->next;
}
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
dlenv_init();
atexit(datalink_cleanup);
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();
/* try to bind with the device */
found =
address_bind_request(Target_Device_Object_Instance, &max_apdu,
&Target_Address);
if (!found) {
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
}
/* start at the beginning of the subscribe list */
cov_data = COV_Subscribe_Data;
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
current_seconds = time(NULL);
/* at least one second has passed */
if (current_seconds != last_seconds) {
/* increment timer - exit if timed out */
delta_seconds = current_seconds - last_seconds;
elapsed_seconds += delta_seconds;
tsm_timer_milliseconds((delta_seconds * 1000));
/* keep track of time for next check */
last_seconds = current_seconds;
}
if (Error_Detected)
break;
/* wait until the device is bound, or timeout and quit */
if (!found) {
found =
address_bind_request(Target_Device_Object_Instance, &max_apdu,
&Target_Address);
}
if (found) {
if (Request_Invoke_ID == 0) {
Target_Device_Process_Identifier =
cov_data->subscriberProcessIdentifier;
Request_Invoke_ID = Send_COV_Subscribe(
Target_Device_Object_Instance,
cov_data);
if (!cov_data->cancellationRequest &&
(timeout_seconds < cov_data->lifetime)) {
/* increase the timeout to the longest lifetime */
timeout_seconds = cov_data->lifetime;
}
printf("Sent SubscribeCOV request. Waiting %u seconds.\r\n",
(unsigned)(timeout_seconds - elapsed_seconds));
} else if (tsm_invoke_id_free(Request_Invoke_ID)) {
if (cov_data->next) {
cov_data = cov_data->next;
Request_Invoke_ID = 0;
} else {
/* do nothing - wait for lifetime value to expire */
}
} else if (tsm_invoke_id_failed(Request_Invoke_ID)) {
fprintf(stderr, "\rError: TSM Timeout!\r\n");
tsm_free_invoke_id(Request_Invoke_ID);
Error_Detected = true;
/* try again or abort? */
break;
}
} else {
/* exit if timed out */
if (elapsed_seconds > timeout_seconds) {
Error_Detected = true;
printf("\rError: APDU Timeout!\r\n");
break;
}
}
/* returns 0 bytes on timeout */
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
if (Error_Detected) {
break;
}
/* COV - so just wait until lifetime value expires */
if (elapsed_seconds > timeout_seconds) {
break;
}
}
if (Error_Detected)
return 1;
return 0;
}
/*************************************************************************
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* command line tool that sends a BACnet service, and displays the reply */
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h> /* for time */
#include <ctype.h> /* for toupper */
#define PRINT_ENABLED 1
#include "bacdef.h"
#include "config.h"
#include "bactext.h"
#include "bacerror.h"
#include "iam.h"
#include "arf.h"
#include "tsm.h"
#include "address.h"
#include "npdu.h"
#include "apdu.h"
#include "device.h"
#include "net.h"
#include "datalink.h"
#include "whois.h"
/* some demo stuff needed */
#include "filename.h"
#include "handlers.h"
#include "client.h"
#include "txbuf.h"
#include "dlenv.h"
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
/* converted command line arguments */
static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE;
/* Process identifier for matching replies */
static uint32_t Target_Device_Process_Identifier = 0;
/* the invoke id is needed to filter incoming messages */
static uint8_t Request_Invoke_ID = 0;
/* MAC and SNET address of target */
static BACNET_ADDRESS Target_Address;
/* indication of error, reject, or abort */
static bool Error_Detected = false;
/* data used in COV subscription request */
BACNET_SUBSCRIBE_COV_DATA *COV_Subscribe_Data = NULL;
static void MyErrorHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
{
if (address_match(&Target_Address, src) &&
(invoke_id == Request_Invoke_ID)) {
printf("BACnet Error: %s: %s\r\n",
bactext_error_class_name((int) error_class),
bactext_error_code_name((int) error_code));
Error_Detected = true;
}
}
void MyAbortHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
{
(void) server;
if (address_match(&Target_Address, src) &&
(invoke_id == Request_Invoke_ID)) {
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name((int) abort_reason));
Error_Detected = true;
}
}
void MyRejectHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t reject_reason)
{
if (address_match(&Target_Address, src) &&
(invoke_id == Request_Invoke_ID)) {
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name((int) reject_reason));
Error_Detected = true;
}
}
static void Init_Service_Handlers(
void)
{
Device_Init(NULL);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the data coming back from COV subscriptions */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_COV_NOTIFICATION,
handler_ccov_notification);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_COV_NOTIFICATION,
handler_ucov_notification);
/* handle any errors coming back */
apdu_set_error_handler(SERVICE_CONFIRMED_SUBSCRIBE_COV, MyErrorHandler);
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
void cleanup(
void)
{
BACNET_SUBSCRIBE_COV_DATA *cov_data = NULL;
BACNET_SUBSCRIBE_COV_DATA *cov_data_old = NULL;
cov_data = COV_Subscribe_Data;
while (cov_data) {
cov_data_old = cov_data;
cov_data = cov_data->next;
free(cov_data_old);
}
}
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = {
0
}; /* address where message came from */
uint16_t pdu_len = 0;
unsigned timeout = 100; /* milliseconds */
unsigned max_apdu = 0;
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
time_t delta_seconds = 0;
bool found = false;
char *filename = NULL;
bool print_usage_terse = false;
bool print_usage_verbose = false;
BACNET_SUBSCRIBE_COV_DATA *cov_data = NULL;
int argi = 0;
int arg_remaining = 0;
if (argc < 6) {
print_usage_terse = true;
}
if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
print_usage_terse = true;
print_usage_verbose = true;
}
if (print_usage_terse) {
filename = filename_remove_path(argv[0]);
printf("Usage: %s device-id object-type object-instance "
"process-id <confirmed lifetime|cancel>\r\n",
filename);
if (!print_usage_verbose) {
return 0;
}
}
if (print_usage_verbose) {
printf("\r\n"
"device-id:\r\n"
"The subscriber BACnet Device Object Instance number.\r\n"
"\r\n"
"object-type:\r\n"
"The monitored object type is the integer value of the\r\n"
"enumeration BACNET_OBJECT_TYPE in bacenum.h. For example,\r\n"
"if you were monitoring Analog Output 2, the object-type\r\n"
"would be 1.\r\n"
"\r\n"
"object-instance:\r\n"
"The monitored object instance number.\r\n"
"\r\n"
"process-id:\r\n"
"Process Identifier for this COV subscription.\r\n"
"\r\n"
"confirmed:\r\n"
"Optional flag to subscribe using Confirmed notifications.\r\n"
"Use the word \'confirmed\' or \'unconfirmed\'.\r\n"
"\r\n"
"lifetime:\r\n"
"Optional subscription lifetime is conveyed in seconds.\r\n"
"\r\n"
"cancel:\r\n"
"Use the word \'cancel\' instead of confirm and lifetime.\r\n"
"This shall indicate a cancellation request.\r\n"
"\r\n"
"Example:\r\n"
"If you want subscribe to Device 123 Analog Input 9 object\r\n"
"using confirmed COV notifications for 5 minutes,\r\n"
"you could send the following command:\r\n"
"%s 123 0 9 1 confirmed 600\r\n"
"To send the same COV subscription request for unconfirmed\r\n"
"notifications, send the following command:\r\n"
"%s 123 0 9 1 unconfirmed 600\r\n"
"To cancel the same COV subscription request,\r\n"
"send the following command:\r\n"
"%s 123 0 9 1 cancel\r\n",
filename, filename, filename);
return 0;
}
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
return 1;
}
atexit(cleanup);
COV_Subscribe_Data = calloc(1, sizeof(BACNET_SUBSCRIBE_COV_DATA));
cov_data = COV_Subscribe_Data;
argi = 2;
while (cov_data) {
cov_data->monitoredObjectIdentifier.type =
strtol(argv[argi], NULL, 0);
if (cov_data->monitoredObjectIdentifier.type >= MAX_BACNET_OBJECT_TYPE) {
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
cov_data->monitoredObjectIdentifier.type, MAX_BACNET_OBJECT_TYPE);
return 1;
}
argi++;
cov_data->monitoredObjectIdentifier.instance =
strtol(argv[argi], NULL, 0);
if (cov_data->monitoredObjectIdentifier.instance > BACNET_MAX_INSTANCE) {
fprintf(stderr, "object-instance=%u - it must be less than %u\r\n",
cov_data->monitoredObjectIdentifier.instance,
BACNET_MAX_INSTANCE + 1);
return 1;
}
argi++;
cov_data->subscriberProcessIdentifier =
strtol(argv[argi], NULL, 0);
argi++;
if (strcmp(argv[argi],"cancel") == 0) {
cov_data->cancellationRequest = true;
argi++;
} else {
cov_data->cancellationRequest = false;
if (strcmp(argv[argi],"confirmed") == 0) {
cov_data->issueConfirmedNotifications = true;
} else if (strcmp(argv[argi],"unconfirmed") == 0) {
cov_data->issueConfirmedNotifications = false;
} else {
fprintf(stderr, "unknown option: %s\r\n",
argv[argi]);
return 1;
}
argi++;
arg_remaining = argc - argi;
if (arg_remaining > 0) {
cov_data->lifetime = strtol(argv[argi], NULL, 0);
argi++;
} else {
cov_data->lifetime = 0;
}
}
arg_remaining = argc - argi;
if (arg_remaining < 5) {
break;
} else {
cov_data->next = calloc(1, sizeof(BACNET_SUBSCRIBE_COV_DATA));
cov_data = cov_data->next;
}
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
dlenv_init();
atexit(datalink_cleanup);
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();
/* try to bind with the device */
found =
address_bind_request(Target_Device_Object_Instance, &max_apdu,
&Target_Address);
if (!found) {
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
}
/* start at the beginning of the subscribe list */
cov_data = COV_Subscribe_Data;
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
current_seconds = time(NULL);
/* at least one second has passed */
if (current_seconds != last_seconds) {
/* increment timer - exit if timed out */
delta_seconds = current_seconds - last_seconds;
elapsed_seconds += delta_seconds;
tsm_timer_milliseconds((delta_seconds * 1000));
/* keep track of time for next check */
last_seconds = current_seconds;
}
if (Error_Detected)
break;
/* wait until the device is bound, or timeout and quit */
if (!found) {
found =
address_bind_request(Target_Device_Object_Instance, &max_apdu,
&Target_Address);
}
if (found) {
if (Request_Invoke_ID == 0) {
Target_Device_Process_Identifier =
cov_data->subscriberProcessIdentifier;
Request_Invoke_ID = Send_COV_Subscribe(
Target_Device_Object_Instance,
cov_data);
if (!cov_data->cancellationRequest &&
(timeout_seconds < cov_data->lifetime)) {
/* increase the timeout to the longest lifetime */
timeout_seconds = cov_data->lifetime;
}
printf("Sent SubscribeCOV request. Waiting %u seconds.\r\n",
(unsigned)(timeout_seconds - elapsed_seconds));
} else if (tsm_invoke_id_free(Request_Invoke_ID)) {
if (cov_data->next) {
cov_data = cov_data->next;
Request_Invoke_ID = 0;
} else {
/* do nothing - wait for lifetime value to expire */
}
} else if (tsm_invoke_id_failed(Request_Invoke_ID)) {
fprintf(stderr, "\rError: TSM Timeout!\r\n");
tsm_free_invoke_id(Request_Invoke_ID);
Error_Detected = true;
/* try again or abort? */
break;
}
} else {
/* exit if timed out */
if (elapsed_seconds > timeout_seconds) {
Error_Detected = true;
printf("\rError: APDU Timeout!\r\n");
break;
}
}
/* returns 0 bytes on timeout */
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
if (Error_Detected) {
break;
}
/* COV - so just wait until lifetime value expires */
if (elapsed_seconds > timeout_seconds) {
break;
}
}
if (Error_Detected)
return 1;
return 0;
}
+143 -143
View File
@@ -1,143 +1,143 @@
#
# Simple makefile to build an executable for Win32
#
# This makefile assumes Borland bcc32 development environment
# on Windows NT/9x/2000/XP
#
!ifndef BORLAND_DIR
BORLAND_DIR_Not_Defined:
@echo .
@echo You must define environment variable BORLAND_DIR to compile.
!endif
PRODUCT = bacscov
PRODUCT_EXE = $(PRODUCT).exe
# tools
CC = $(BORLAND_DIR)\bin\bcc32
MAKE=$(BORLAND_DIR)\bin\make.exe
#LINK = $(BORLAND_DIR)\bin\tlink32
LINK = $(BORLAND_DIR)\bin\ilink32
BACNET_LIB_DIR = ..\..\lib
BACNET_LIB = $(BACNET_LIB_DIR)\bacnet.lib
# directories
BACNET_PORT = ..\..\ports\win32
BACNET_INCLUDE = ..\..\include
BACNET_OBJECT = ..\object
BACNET_HANDLER = ..\handler
INCLUDES = \
-I$(BACNET_INCLUDE) \
-I$(BACNET_PORT) \
-I$(BACNET_OBJECT) \
-I$(BACNET_HANDLER) \
-I$(BORLAND_DIR)\include
#
BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
#BACDL_DEFINE=-DBACDL_MSTP=1
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
# by default bacupt can handle 64 tag/value pairs
BUILD_DEFINE = -DMAX_PROPERTY_VALUES=64
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) $(BUILD_DEFINE)
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
#
# Compiler definitions
#
BCC_CFG = bcc32.cfg
#
# Include directories
#
CFLAGS = $(INCLUDES) $(DEFINES)
#
# Libraries
#
C_LIB_DIR = $(BORLAND_DIR)\lib
LIBS = $(BACNET_LIB) \
$(C_LIB_DIR)\IMPORT32.lib \
$(C_LIB_DIR)\CW32MT.lib \
#
# Main target
#
# This should be the first one in the makefile
all : $(BACNET_LIB) $(BCC_CFG) $(OBJS) $(PRODUCT_EXE)
del $(BCC_CFG)
install: $(PRODUCT_EXE)
copy $(PRODUCT_EXE) ..\..\bin\$(PRODUCT_EXE)
# Linker specific: the link below is for BCC linker/compiler. If you link
# with a different linker - please change accordingly.
#
# need a temp response file (@&&| ... |) because command line is too long
# $** lists each dependency
# $< target name
# $* target name without extension
$(PRODUCT_EXE) : $(OBJS)
@echo Running Linker for $(PRODUCT_EXE)
$(LINK) -L$(C_LIB_DIR) -L$(BACNET_LIB_DIR) -m -c -s -v @&&|
$(BORLAND_DIR)\lib\c0x32.obj $**
$<
$*.map
$(LIBS)
|
#
# Utilities
clean :
del $(OBJS)
del $(PRODUCT_EXE)
del $(PRODUCT).map
del $(PRODUCT).ilc
del $(PRODUCT).ild
del $(PRODUCT).ilf
del $(PRODUCT).ils
del $(PRODUCT).tds
del $(BCC_CFG)
#
# Generic rules
#
.SUFFIXES: .cpp .c .sbr .obj
#
# cc generic rule
#
.c.obj:
$(CC) +$(BCC_CFG) -o$@ $<
# Compiler configuration file
$(BCC_CFG) :
Copy &&|
$(CFLAGS)
-c
-y #include line numbers in OBJ's
-v #include debug info
-w+ #turn on all warnings
-Od #disable all optimizations
#-a4 #32 bit data alignment
#-M # generate link map
#-ls # linker options
#-WM- #not multithread
-WM #multithread
-w-aus # ignore warning assigned a value that is never used
-w-sig # ignore warning conversion may lose sig digits
| $@
# EOF: makefile
#
# Simple makefile to build an executable for Win32
#
# This makefile assumes Borland bcc32 development environment
# on Windows NT/9x/2000/XP
#
!ifndef BORLAND_DIR
BORLAND_DIR_Not_Defined:
@echo .
@echo You must define environment variable BORLAND_DIR to compile.
!endif
PRODUCT = bacscov
PRODUCT_EXE = $(PRODUCT).exe
# tools
CC = $(BORLAND_DIR)\bin\bcc32
MAKE=$(BORLAND_DIR)\bin\make.exe
#LINK = $(BORLAND_DIR)\bin\tlink32
LINK = $(BORLAND_DIR)\bin\ilink32
BACNET_LIB_DIR = ..\..\lib
BACNET_LIB = $(BACNET_LIB_DIR)\bacnet.lib
# directories
BACNET_PORT = ..\..\ports\win32
BACNET_INCLUDE = ..\..\include
BACNET_OBJECT = ..\object
BACNET_HANDLER = ..\handler
INCLUDES = \
-I$(BACNET_INCLUDE) \
-I$(BACNET_PORT) \
-I$(BACNET_OBJECT) \
-I$(BACNET_HANDLER) \
-I$(BORLAND_DIR)\include
#
BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
#BACDL_DEFINE=-DBACDL_MSTP=1
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
# by default bacupt can handle 64 tag/value pairs
BUILD_DEFINE = -DMAX_PROPERTY_VALUES=64
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) $(BUILD_DEFINE)
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
#
# Compiler definitions
#
BCC_CFG = bcc32.cfg
#
# Include directories
#
CFLAGS = $(INCLUDES) $(DEFINES)
#
# Libraries
#
C_LIB_DIR = $(BORLAND_DIR)\lib
LIBS = $(BACNET_LIB) \
$(C_LIB_DIR)\IMPORT32.lib \
$(C_LIB_DIR)\CW32MT.lib \
#
# Main target
#
# This should be the first one in the makefile
all : $(BACNET_LIB) $(BCC_CFG) $(OBJS) $(PRODUCT_EXE)
del $(BCC_CFG)
install: $(PRODUCT_EXE)
copy $(PRODUCT_EXE) ..\..\bin\$(PRODUCT_EXE)
# Linker specific: the link below is for BCC linker/compiler. If you link
# with a different linker - please change accordingly.
#
# need a temp response file (@&&| ... |) because command line is too long
# $** lists each dependency
# $< target name
# $* target name without extension
$(PRODUCT_EXE) : $(OBJS)
@echo Running Linker for $(PRODUCT_EXE)
$(LINK) -L$(C_LIB_DIR) -L$(BACNET_LIB_DIR) -m -c -s -v @&&|
$(BORLAND_DIR)\lib\c0x32.obj $**
$<
$*.map
$(LIBS)
|
#
# Utilities
clean :
del $(OBJS)
del $(PRODUCT_EXE)
del $(PRODUCT).map
del $(PRODUCT).ilc
del $(PRODUCT).ild
del $(PRODUCT).ilf
del $(PRODUCT).ils
del $(PRODUCT).tds
del $(BCC_CFG)
#
# Generic rules
#
.SUFFIXES: .cpp .c .sbr .obj
#
# cc generic rule
#
.c.obj:
$(CC) +$(BCC_CFG) -o$@ $<
# Compiler configuration file
$(BCC_CFG) :
Copy &&|
$(CFLAGS)
-c
-y #include line numbers in OBJ's
-v #include debug info
-w+ #turn on all warnings
-Od #disable all optimizations
#-a4 #32 bit data alignment
#-M # generate link map
#-ls # linker options
#-WM- #not multithread
-WM #multithread
-w-aus # ignore warning assigned a value that is never used
-w-sig # ignore warning conversion may lose sig digits
| $@
# EOF: makefile
+44 -44
View File
@@ -1,44 +1,44 @@
#Makefile to build BACnet Application using GCC compiler
# tools - only if you need them.
# Most platforms have this already defined
# CC = gcc
# AR = ar
# MAKE = make
# SIZE = size
#
# Assumes rm and cp are available
# Executable file name
TARGET = bacupt
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
size $@
cp $@ ../../bin
lib: ${BACNET_LIB_TARGET}
${BACNET_LIB_TARGET}:
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -rf core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET}
include: .depend
#Makefile to build BACnet Application using GCC compiler
# tools - only if you need them.
# Most platforms have this already defined
# CC = gcc
# AR = ar
# MAKE = make
# SIZE = size
#
# Assumes rm and cp are available
# Executable file name
TARGET = bacupt
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
size $@
cp $@ ../../bin
lib: ${BACNET_LIB_TARGET}
${BACNET_LIB_TARGET}:
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -rf core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET}
include: .depend
+353 -353
View File
@@ -1,353 +1,353 @@
/*************************************************************************
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* command line tool that sends a BACnet service, and displays the reply */
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h> /* for time */
#include <ctype.h> /* for toupper */
#define PRINT_ENABLED 1
#include "bacdef.h"
#include "config.h"
#include "bactext.h"
#include "bacerror.h"
#include "iam.h"
#include "arf.h"
#include "tsm.h"
#include "address.h"
#include "npdu.h"
#include "apdu.h"
#include "device.h"
#include "net.h"
#include "datalink.h"
#include "whois.h"
/* some demo stuff needed */
#include "filename.h"
#include "handlers.h"
#include "client.h"
#include "txbuf.h"
#include "dlenv.h"
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
/* converted command line arguments */
static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE;
static uint16_t Target_Vendor_Identifier = 260;
static uint32_t Target_Service_Number = 0;
/* property value encodings */
#ifndef MAX_PROPERTY_VALUES
#define MAX_PROPERTY_VALUES 64
#endif
static BACNET_APPLICATION_DATA_VALUE
Target_Object_Property_Value[MAX_PROPERTY_VALUES];
/* buffer for service parameters */
static uint8_t Service_Parameters[MAX_APDU];
/* the invoke id is needed to filter incoming messages */
static uint8_t Request_Invoke_ID = 0;
static BACNET_ADDRESS Target_Address;
static bool Error_Detected = false;
static void MyErrorHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
{
if (address_match(&Target_Address, src) &&
(invoke_id == Request_Invoke_ID)) {
printf("BACnet Error: %s: %s\r\n",
bactext_error_class_name((int) error_class),
bactext_error_code_name((int) error_code));
Error_Detected = true;
}
}
void MyAbortHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
{
(void) server;
if (address_match(&Target_Address, src) &&
(invoke_id == Request_Invoke_ID)) {
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name((int) abort_reason));
Error_Detected = true;
}
}
void MyRejectHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t reject_reason)
{
if (address_match(&Target_Address, src) &&
(invoke_id == Request_Invoke_ID)) {
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name((int) reject_reason));
Error_Detected = true;
}
}
static void Init_Service_Handlers(
void)
{
Device_Init(NULL);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the data coming back from requests */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_PRIVATE_TRANSFER,
handler_unconfirmed_private_transfer);
/* handle any errors coming back */
apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY, MyErrorHandler);
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = {
0
}; /* address where message came from */
uint16_t pdu_len = 0;
unsigned timeout = 100; /* milliseconds */
unsigned max_apdu = 0;
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
time_t delta_seconds = 0;
bool found = false;
char *filename = NULL;
char *value_string = NULL;
bool status = false;
int args_remaining = 0, tag_value_arg = 0, i = 0;
BACNET_APPLICATION_TAG property_tag;
uint8_t context_tag = 0;
BACNET_PRIVATE_TRANSFER_DATA private_data = {0};
int len = 0;
bool sent_message = false;
if (argc < 6) {
filename = filename_remove_path(argv[0]);
printf("Usage: %s device-instance vendor-id service-number "
"tag value [tag value...]\r\n", filename);
if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
printf("device-instance:\r\n"
"BACnet Device Object Instance number that you are\r\n"
"trying to communicate to. This number will be used\r\n"
"to try and bind with the device using Who-Is and\r\n"
"I-Am services. For example, if you were transferring to\r\n"
"Device Object 123, the device-instance would be 123.\r\n"
"\r\n"
"vendor_id:\r\n"
"the unique vendor identification code for the type of\r\n"
"vendor proprietary service to be performed.\r\n"
"\r\n"
"service-number (Unsigned32):\r\n"
"the desired proprietary service to be performed.\r\n"
"\r\n"
"tag:\r\n"
"Tag is the integer value of the enumeration \r\n"
"BACNET_APPLICATION_TAG in bacenum.h.\r\n"
"It is the data type of the value that you are sending.\r\n"
"For example, if you were transfering a REAL value, you would \r\n"
"use a tag of 4.\r\n"
"Context tags are created using two tags in a row.\r\n"
"The context tag is preceded by a C. Ctag tag.\r\n"
"C2 4 creates a context 2 tagged REAL.\r\n"
"\r\n"
"value:\r\n"
"The value is an ASCII representation of some type of data\r\n"
"that you are transfering.\r\n"
"It is encoded using the tag information provided.\r\n"
"For example, if you were transferring a REAL value of 100.0,\r\n"
"you would use 100.0 as the value.\r\n"
"If you were transferring an object identifier for Device 123,\r\n"
"you would use 8:123 as the value.\r\n"
"\r\n"
"Example:\r\n"
"If you want to transfer a REAL value of 1.1 to service 23 of \r\n"
"vendor 260 in Device 99, you could send the following command:\r\n"
"%s 99 260 23 4 1.1\r\n", filename);
}
return 0;
}
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
Target_Vendor_Identifier = strtol(argv[2], NULL, 0);
Target_Service_Number = strtol(argv[3], NULL, 0);
if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
return 1;
}
args_remaining = (argc - (6-2));
for (i = 0; i < MAX_PROPERTY_VALUES; i++) {
tag_value_arg = (6-2) + (i * 2);
/* special case for context tagged values */
if (toupper(argv[tag_value_arg][0]) == 'C') {
context_tag = strtol(&argv[tag_value_arg][1], NULL, 0);
tag_value_arg++;
args_remaining--;
Target_Object_Property_Value[i].context_tag = context_tag;
Target_Object_Property_Value[i].context_specific = true;
} else {
Target_Object_Property_Value[i].context_specific = false;
}
property_tag = strtol(argv[tag_value_arg], NULL, 0);
args_remaining--;
if (args_remaining <= 0) {
fprintf(stderr, "Error: not enough tag-value pairs\r\n");
return 1;
}
value_string = argv[tag_value_arg + 1];
args_remaining--;
/* printf("tag[%d]=%u value[%d]=%s\r\n",
i, property_tag, i, value_string); */
if (property_tag >= MAX_BACNET_APPLICATION_TAG) {
fprintf(stderr, "Error: tag=%u - it must be less than %u\r\n",
property_tag, MAX_BACNET_APPLICATION_TAG);
return 1;
}
status =
bacapp_parse_application_data(property_tag, value_string,
&Target_Object_Property_Value[i]);
if (!status) {
/* FIXME: show the expected entry format for the tag */
fprintf(stderr, "Error: unable to parse the tag value\r\n");
return 1;
}
Target_Object_Property_Value[i].next = NULL;
if (i > 0) {
Target_Object_Property_Value[i - 1].next =
&Target_Object_Property_Value[i];
}
if (args_remaining <= 0) {
break;
}
}
if (args_remaining > 0) {
fprintf(stderr, "Error: Exceeded %d tag-value pairs.\r\n",
MAX_PROPERTY_VALUES);
return 1;
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
dlenv_init();
atexit(datalink_cleanup);
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();
/* try to bind with the device */
found =
address_bind_request(Target_Device_Object_Instance, &max_apdu,
&Target_Address);
if (!found) {
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
}
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
current_seconds = time(NULL);
/* at least one second has passed */
if (current_seconds != last_seconds) {
/* increment timer - exit if timed out */
delta_seconds = current_seconds - last_seconds;
elapsed_seconds += delta_seconds;
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
}
if (Error_Detected)
break;
/* wait until the device is bound, or timeout and quit */
if (!found) {
found =
address_bind_request(Target_Device_Object_Instance, &max_apdu,
&Target_Address);
}
if (!sent_message) {
if (found) {
len = bacapp_encode_data(&Service_Parameters[0],
&Target_Object_Property_Value[0]);
private_data.serviceParameters = &Service_Parameters[0];
private_data.serviceParametersLen = len;
private_data.vendorID = Target_Vendor_Identifier;
private_data.serviceNumber = Target_Service_Number;
Send_UnconfirmedPrivateTransfer(
&Target_Address,
&private_data);
printf("Sent PrivateTransfer. Waiting %u seconds.\r\n",
(unsigned)(timeout_seconds - elapsed_seconds));
sent_message = true;
} else {
if (elapsed_seconds > timeout_seconds) {
printf("\rError: APDU Timeout!\r\n");
Error_Detected = true;
break;
}
}
}
/* returns 0 bytes on timeout */
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
if (Error_Detected) {
break;
}
/* unconfirmed - so just wait until our timeout value */
if (elapsed_seconds > timeout_seconds) {
break;
}
/* keep track of time for next check */
last_seconds = current_seconds;
}
if (Error_Detected)
return 1;
return 0;
}
/*************************************************************************
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* command line tool that sends a BACnet service, and displays the reply */
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h> /* for time */
#include <ctype.h> /* for toupper */
#define PRINT_ENABLED 1
#include "bacdef.h"
#include "config.h"
#include "bactext.h"
#include "bacerror.h"
#include "iam.h"
#include "arf.h"
#include "tsm.h"
#include "address.h"
#include "npdu.h"
#include "apdu.h"
#include "device.h"
#include "net.h"
#include "datalink.h"
#include "whois.h"
/* some demo stuff needed */
#include "filename.h"
#include "handlers.h"
#include "client.h"
#include "txbuf.h"
#include "dlenv.h"
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
/* converted command line arguments */
static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE;
static uint16_t Target_Vendor_Identifier = 260;
static uint32_t Target_Service_Number = 0;
/* property value encodings */
#ifndef MAX_PROPERTY_VALUES
#define MAX_PROPERTY_VALUES 64
#endif
static BACNET_APPLICATION_DATA_VALUE
Target_Object_Property_Value[MAX_PROPERTY_VALUES];
/* buffer for service parameters */
static uint8_t Service_Parameters[MAX_APDU];
/* the invoke id is needed to filter incoming messages */
static uint8_t Request_Invoke_ID = 0;
static BACNET_ADDRESS Target_Address;
static bool Error_Detected = false;
static void MyErrorHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
{
if (address_match(&Target_Address, src) &&
(invoke_id == Request_Invoke_ID)) {
printf("BACnet Error: %s: %s\r\n",
bactext_error_class_name((int) error_class),
bactext_error_code_name((int) error_code));
Error_Detected = true;
}
}
void MyAbortHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
{
(void) server;
if (address_match(&Target_Address, src) &&
(invoke_id == Request_Invoke_ID)) {
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name((int) abort_reason));
Error_Detected = true;
}
}
void MyRejectHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t reject_reason)
{
if (address_match(&Target_Address, src) &&
(invoke_id == Request_Invoke_ID)) {
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name((int) reject_reason));
Error_Detected = true;
}
}
static void Init_Service_Handlers(
void)
{
Device_Init(NULL);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the data coming back from requests */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_PRIVATE_TRANSFER,
handler_unconfirmed_private_transfer);
/* handle any errors coming back */
apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY, MyErrorHandler);
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = {
0
}; /* address where message came from */
uint16_t pdu_len = 0;
unsigned timeout = 100; /* milliseconds */
unsigned max_apdu = 0;
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
time_t delta_seconds = 0;
bool found = false;
char *filename = NULL;
char *value_string = NULL;
bool status = false;
int args_remaining = 0, tag_value_arg = 0, i = 0;
BACNET_APPLICATION_TAG property_tag;
uint8_t context_tag = 0;
BACNET_PRIVATE_TRANSFER_DATA private_data = {0};
int len = 0;
bool sent_message = false;
if (argc < 6) {
filename = filename_remove_path(argv[0]);
printf("Usage: %s device-instance vendor-id service-number "
"tag value [tag value...]\r\n", filename);
if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
printf("device-instance:\r\n"
"BACnet Device Object Instance number that you are\r\n"
"trying to communicate to. This number will be used\r\n"
"to try and bind with the device using Who-Is and\r\n"
"I-Am services. For example, if you were transferring to\r\n"
"Device Object 123, the device-instance would be 123.\r\n"
"\r\n"
"vendor_id:\r\n"
"the unique vendor identification code for the type of\r\n"
"vendor proprietary service to be performed.\r\n"
"\r\n"
"service-number (Unsigned32):\r\n"
"the desired proprietary service to be performed.\r\n"
"\r\n"
"tag:\r\n"
"Tag is the integer value of the enumeration \r\n"
"BACNET_APPLICATION_TAG in bacenum.h.\r\n"
"It is the data type of the value that you are sending.\r\n"
"For example, if you were transfering a REAL value, you would \r\n"
"use a tag of 4.\r\n"
"Context tags are created using two tags in a row.\r\n"
"The context tag is preceded by a C. Ctag tag.\r\n"
"C2 4 creates a context 2 tagged REAL.\r\n"
"\r\n"
"value:\r\n"
"The value is an ASCII representation of some type of data\r\n"
"that you are transfering.\r\n"
"It is encoded using the tag information provided.\r\n"
"For example, if you were transferring a REAL value of 100.0,\r\n"
"you would use 100.0 as the value.\r\n"
"If you were transferring an object identifier for Device 123,\r\n"
"you would use 8:123 as the value.\r\n"
"\r\n"
"Example:\r\n"
"If you want to transfer a REAL value of 1.1 to service 23 of \r\n"
"vendor 260 in Device 99, you could send the following command:\r\n"
"%s 99 260 23 4 1.1\r\n", filename);
}
return 0;
}
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
Target_Vendor_Identifier = strtol(argv[2], NULL, 0);
Target_Service_Number = strtol(argv[3], NULL, 0);
if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
return 1;
}
args_remaining = (argc - (6-2));
for (i = 0; i < MAX_PROPERTY_VALUES; i++) {
tag_value_arg = (6-2) + (i * 2);
/* special case for context tagged values */
if (toupper(argv[tag_value_arg][0]) == 'C') {
context_tag = strtol(&argv[tag_value_arg][1], NULL, 0);
tag_value_arg++;
args_remaining--;
Target_Object_Property_Value[i].context_tag = context_tag;
Target_Object_Property_Value[i].context_specific = true;
} else {
Target_Object_Property_Value[i].context_specific = false;
}
property_tag = strtol(argv[tag_value_arg], NULL, 0);
args_remaining--;
if (args_remaining <= 0) {
fprintf(stderr, "Error: not enough tag-value pairs\r\n");
return 1;
}
value_string = argv[tag_value_arg + 1];
args_remaining--;
/* printf("tag[%d]=%u value[%d]=%s\r\n",
i, property_tag, i, value_string); */
if (property_tag >= MAX_BACNET_APPLICATION_TAG) {
fprintf(stderr, "Error: tag=%u - it must be less than %u\r\n",
property_tag, MAX_BACNET_APPLICATION_TAG);
return 1;
}
status =
bacapp_parse_application_data(property_tag, value_string,
&Target_Object_Property_Value[i]);
if (!status) {
/* FIXME: show the expected entry format for the tag */
fprintf(stderr, "Error: unable to parse the tag value\r\n");
return 1;
}
Target_Object_Property_Value[i].next = NULL;
if (i > 0) {
Target_Object_Property_Value[i - 1].next =
&Target_Object_Property_Value[i];
}
if (args_remaining <= 0) {
break;
}
}
if (args_remaining > 0) {
fprintf(stderr, "Error: Exceeded %d tag-value pairs.\r\n",
MAX_PROPERTY_VALUES);
return 1;
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
dlenv_init();
atexit(datalink_cleanup);
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();
/* try to bind with the device */
found =
address_bind_request(Target_Device_Object_Instance, &max_apdu,
&Target_Address);
if (!found) {
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
}
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
current_seconds = time(NULL);
/* at least one second has passed */
if (current_seconds != last_seconds) {
/* increment timer - exit if timed out */
delta_seconds = current_seconds - last_seconds;
elapsed_seconds += delta_seconds;
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
}
if (Error_Detected)
break;
/* wait until the device is bound, or timeout and quit */
if (!found) {
found =
address_bind_request(Target_Device_Object_Instance, &max_apdu,
&Target_Address);
}
if (!sent_message) {
if (found) {
len = bacapp_encode_data(&Service_Parameters[0],
&Target_Object_Property_Value[0]);
private_data.serviceParameters = &Service_Parameters[0];
private_data.serviceParametersLen = len;
private_data.vendorID = Target_Vendor_Identifier;
private_data.serviceNumber = Target_Service_Number;
Send_UnconfirmedPrivateTransfer(
&Target_Address,
&private_data);
printf("Sent PrivateTransfer. Waiting %u seconds.\r\n",
(unsigned)(timeout_seconds - elapsed_seconds));
sent_message = true;
} else {
if (elapsed_seconds > timeout_seconds) {
printf("\rError: APDU Timeout!\r\n");
Error_Detected = true;
break;
}
}
}
/* returns 0 bytes on timeout */
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
if (Error_Detected) {
break;
}
/* unconfirmed - so just wait until our timeout value */
if (elapsed_seconds > timeout_seconds) {
break;
}
/* keep track of time for next check */
last_seconds = current_seconds;
}
if (Error_Detected)
return 1;
return 0;
}
+143 -143
View File
@@ -1,143 +1,143 @@
#
# Simple makefile to build an executable for Win32
#
# This makefile assumes Borland bcc32 development environment
# on Windows NT/9x/2000/XP
#
!ifndef BORLAND_DIR
BORLAND_DIR_Not_Defined:
@echo .
@echo You must define environment variable BORLAND_DIR to compile.
!endif
PRODUCT = bacupt
PRODUCT_EXE = $(PRODUCT).exe
# tools
CC = $(BORLAND_DIR)\bin\bcc32
MAKE=$(BORLAND_DIR)\bin\make.exe
#LINK = $(BORLAND_DIR)\bin\tlink32
LINK = $(BORLAND_DIR)\bin\ilink32
BACNET_LIB_DIR = ..\..\lib
BACNET_LIB = $(BACNET_LIB_DIR)\bacnet.lib
# directories
BACNET_PORT = ..\..\ports\win32
BACNET_INCLUDE = ..\..\include
BACNET_OBJECT = ..\object
BACNET_HANDLER = ..\handler
INCLUDES = \
-I$(BACNET_INCLUDE) \
-I$(BACNET_PORT) \
-I$(BACNET_OBJECT) \
-I$(BACNET_HANDLER) \
-I$(BORLAND_DIR)\include
#
BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
#BACDL_DEFINE=-DBACDL_MSTP=1
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
# by default bacupt can handle 64 tag/value pairs
BUILD_DEFINE = -DMAX_PROPERTY_VALUES=64
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) $(BUILD_DEFINE)
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
#
# Compiler definitions
#
BCC_CFG = bcc32.cfg
#
# Include directories
#
CFLAGS = $(INCLUDES) $(DEFINES)
#
# Libraries
#
C_LIB_DIR = $(BORLAND_DIR)\lib
LIBS = $(BACNET_LIB) \
$(C_LIB_DIR)\IMPORT32.lib \
$(C_LIB_DIR)\CW32MT.lib \
#
# Main target
#
# This should be the first one in the makefile
all : $(BACNET_LIB) $(BCC_CFG) $(OBJS) $(PRODUCT_EXE)
del $(BCC_CFG)
install: $(PRODUCT_EXE)
copy $(PRODUCT_EXE) ..\..\bin\$(PRODUCT_EXE)
# Linker specific: the link below is for BCC linker/compiler. If you link
# with a different linker - please change accordingly.
#
# need a temp response file (@&&| ... |) because command line is too long
# $** lists each dependency
# $< target name
# $* target name without extension
$(PRODUCT_EXE) : $(OBJS)
@echo Running Linker for $(PRODUCT_EXE)
$(LINK) -L$(C_LIB_DIR) -L$(BACNET_LIB_DIR) -m -c -s -v @&&|
$(BORLAND_DIR)\lib\c0x32.obj $**
$<
$*.map
$(LIBS)
|
#
# Utilities
clean :
del $(OBJS)
del $(PRODUCT_EXE)
del $(PRODUCT).map
del $(PRODUCT).ilc
del $(PRODUCT).ild
del $(PRODUCT).ilf
del $(PRODUCT).ils
del $(PRODUCT).tds
del $(BCC_CFG)
#
# Generic rules
#
.SUFFIXES: .cpp .c .sbr .obj
#
# cc generic rule
#
.c.obj:
$(CC) +$(BCC_CFG) -o$@ $<
# Compiler configuration file
$(BCC_CFG) :
Copy &&|
$(CFLAGS)
-c
-y #include line numbers in OBJ's
-v #include debug info
-w+ #turn on all warnings
-Od #disable all optimizations
#-a4 #32 bit data alignment
#-M # generate link map
#-ls # linker options
#-WM- #not multithread
-WM #multithread
-w-aus # ignore warning assigned a value that is never used
-w-sig # ignore warning conversion may lose sig digits
| $@
# EOF: makefile
#
# Simple makefile to build an executable for Win32
#
# This makefile assumes Borland bcc32 development environment
# on Windows NT/9x/2000/XP
#
!ifndef BORLAND_DIR
BORLAND_DIR_Not_Defined:
@echo .
@echo You must define environment variable BORLAND_DIR to compile.
!endif
PRODUCT = bacupt
PRODUCT_EXE = $(PRODUCT).exe
# tools
CC = $(BORLAND_DIR)\bin\bcc32
MAKE=$(BORLAND_DIR)\bin\make.exe
#LINK = $(BORLAND_DIR)\bin\tlink32
LINK = $(BORLAND_DIR)\bin\ilink32
BACNET_LIB_DIR = ..\..\lib
BACNET_LIB = $(BACNET_LIB_DIR)\bacnet.lib
# directories
BACNET_PORT = ..\..\ports\win32
BACNET_INCLUDE = ..\..\include
BACNET_OBJECT = ..\object
BACNET_HANDLER = ..\handler
INCLUDES = \
-I$(BACNET_INCLUDE) \
-I$(BACNET_PORT) \
-I$(BACNET_OBJECT) \
-I$(BACNET_HANDLER) \
-I$(BORLAND_DIR)\include
#
BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
#BACDL_DEFINE=-DBACDL_MSTP=1
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
# by default bacupt can handle 64 tag/value pairs
BUILD_DEFINE = -DMAX_PROPERTY_VALUES=64
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) $(BUILD_DEFINE)
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
#
# Compiler definitions
#
BCC_CFG = bcc32.cfg
#
# Include directories
#
CFLAGS = $(INCLUDES) $(DEFINES)
#
# Libraries
#
C_LIB_DIR = $(BORLAND_DIR)\lib
LIBS = $(BACNET_LIB) \
$(C_LIB_DIR)\IMPORT32.lib \
$(C_LIB_DIR)\CW32MT.lib \
#
# Main target
#
# This should be the first one in the makefile
all : $(BACNET_LIB) $(BCC_CFG) $(OBJS) $(PRODUCT_EXE)
del $(BCC_CFG)
install: $(PRODUCT_EXE)
copy $(PRODUCT_EXE) ..\..\bin\$(PRODUCT_EXE)
# Linker specific: the link below is for BCC linker/compiler. If you link
# with a different linker - please change accordingly.
#
# need a temp response file (@&&| ... |) because command line is too long
# $** lists each dependency
# $< target name
# $* target name without extension
$(PRODUCT_EXE) : $(OBJS)
@echo Running Linker for $(PRODUCT_EXE)
$(LINK) -L$(C_LIB_DIR) -L$(BACNET_LIB_DIR) -m -c -s -v @&&|
$(BORLAND_DIR)\lib\c0x32.obj $**
$<
$*.map
$(LIBS)
|
#
# Utilities
clean :
del $(OBJS)
del $(PRODUCT_EXE)
del $(PRODUCT).map
del $(PRODUCT).ilc
del $(PRODUCT).ild
del $(PRODUCT).ilf
del $(PRODUCT).ils
del $(PRODUCT).tds
del $(BCC_CFG)
#
# Generic rules
#
.SUFFIXES: .cpp .c .sbr .obj
#
# cc generic rule
#
.c.obj:
$(CC) +$(BCC_CFG) -o$@ $<
# Compiler configuration file
$(BCC_CFG) :
Copy &&|
$(CFLAGS)
-c
-y #include line numbers in OBJ's
-v #include debug info
-w+ #turn on all warnings
-Od #disable all optimizations
#-a4 #32 bit data alignment
#-M # generate link map
#-ls # linker options
#-WM- #not multithread
-WM #multithread
-w-aus # ignore warning assigned a value that is never used
-w-sig # ignore warning conversion may lose sig digits
| $@
# EOF: makefile
+35 -35
View File
@@ -1,38 +1,38 @@
#Makefile to build BACnet Application for the Linux Port
# tools - only if you need them.
# Most platforms have this already defined
# CC = gcc
TARGET = bacwir
#Makefile to build BACnet Application for the Linux Port
# tools - only if you need them.
# Most platforms have this already defined
# CC = gcc
TARGET = bacwir
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
size $@
cp $@ ../../bin
lib: ${BACNET_LIB_TARGET}
${BACNET_LIB_TARGET}:
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -f core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET} $(TARGET).map
include: .depend
lib: ${BACNET_LIB_TARGET}
${BACNET_LIB_TARGET}:
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -f core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET} $(TARGET).map
include: .depend
+84 -84
View File
@@ -1,84 +1,84 @@
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef BACNET_GET_ALARM_SUM_H_
#define BACNET_GET_ALARM_SUM_H_
#include "bacenum.h"
#include <stdint.h>
#include <stdbool.h>
#include "bacapp.h"
#include "timestamp.h"
typedef struct BACnet_Get_Alarm_Summary_Data {
BACNET_OBJECT_ID objectIdentifier;
BACNET_EVENT_STATE alarmState;
BACNET_BIT_STRING acknowledgedTransitions;
} BACNET_GET_ALARM_SUMMARY_DATA;
/* return 0 if no active alarm at this index
return -1 if end of list
return +1 if active alarm */
typedef int (
*get_alarm_summary_function) (
unsigned index,
BACNET_GET_ALARM_SUMMARY_DATA * getalarm_data);
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* set GetAlarmSummary function */
void handler_get_alarm_summary_set(
BACNET_OBJECT_TYPE object_type,
get_alarm_summary_function pFunction);
/* encode service */
int get_alarm_summary_ack_encode_apdu_init(
uint8_t * apdu,
uint8_t invoke_id);
int get_alarm_sumary_ack_encode_apdu_data(
uint8_t * apdu,
size_t max_apdu,
BACNET_GET_ALARM_SUMMARY_DATA * get_alarm_data);
#ifdef __cplusplus
}
#endif /* __cplusplus */
/** @defgroup ALMEVNT Alarm and Event Management BIBBs
* @ingroup ALMEVNT
* 13.1 ConfirmedCOVNotification Service <br>
* The GetAlarmSummary service is used by a client BACnet-user to obtain
* a summary of "active alarms." The term "active alarm" refers to
* BACnet standard objects that have an Event_State property whose value
* is not equal to NORMAL and a Notify_Type property whose value is ALARM.
* The GetEnrollmentSummary service provides a more sophisticated approach
* with various kinds of filters.
*/
#endif /* BACNET_GET_ALARM_SUM_H_ */
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef BACNET_GET_ALARM_SUM_H_
#define BACNET_GET_ALARM_SUM_H_
#include "bacenum.h"
#include <stdint.h>
#include <stdbool.h>
#include "bacapp.h"
#include "timestamp.h"
typedef struct BACnet_Get_Alarm_Summary_Data {
BACNET_OBJECT_ID objectIdentifier;
BACNET_EVENT_STATE alarmState;
BACNET_BIT_STRING acknowledgedTransitions;
} BACNET_GET_ALARM_SUMMARY_DATA;
/* return 0 if no active alarm at this index
return -1 if end of list
return +1 if active alarm */
typedef int (
*get_alarm_summary_function) (
unsigned index,
BACNET_GET_ALARM_SUMMARY_DATA * getalarm_data);
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* set GetAlarmSummary function */
void handler_get_alarm_summary_set(
BACNET_OBJECT_TYPE object_type,
get_alarm_summary_function pFunction);
/* encode service */
int get_alarm_summary_ack_encode_apdu_init(
uint8_t * apdu,
uint8_t invoke_id);
int get_alarm_sumary_ack_encode_apdu_data(
uint8_t * apdu,
size_t max_apdu,
BACNET_GET_ALARM_SUMMARY_DATA * get_alarm_data);
#ifdef __cplusplus
}
#endif /* __cplusplus */
/** @defgroup ALMEVNT Alarm and Event Management BIBBs
* @ingroup ALMEVNT
* 13.1 ConfirmedCOVNotification Service <br>
* The GetAlarmSummary service is used by a client BACnet-user to obtain
* a summary of "active alarms." The term "active alarm" refers to
* BACnet standard objects that have an Event_State property whose value
* is not equal to NORMAL and a Notify_Type property whose value is ALARM.
* The GetEnrollmentSummary service provides a more sophisticated approach
* with various kinds of filters.
*/
#endif /* BACNET_GET_ALARM_SUM_H_ */
+2 -2
View File
@@ -110,8 +110,8 @@
<Unit filename="..\include\sbuf.h" />
<Unit filename="..\include\timesync.h" />
<Unit filename="..\include\tsm.h" />
<Unit filename="..\include\txbuf.h" />
<Unit filename="..\include\dlenv.h" />
<Unit filename="..\include\txbuf.h" />
<Unit filename="..\include\dlenv.h" />
<Unit filename="..\include\version.h" />
<Unit filename="..\include\whohas.h" />
<Unit filename="..\include\whois.h" />
+152 -152
View File
@@ -1,152 +1,152 @@
# Makefile for AT91SAM7S evaluation kit with RS-485 Transceiver on UART0
# Written by Steve Karg <skarg@users.sourceforge.net> 06-Aug-2007
TARGET=bacnet
# Tools
CC=arm-elf-gcc
OBJCOPY=arm-elf-objcopy
OBJDUMP=arm-elf-objdump
AR=arm-elf-ar
SIZE = arm-elf-size
LDSCRIPT=at91sam7s256.ld
BACNET_FLAGS = -DBACDL_MSTP
BACNET_FLAGS += -DMAX_TSM_TRANSACTIONS=0
BACNET_FLAGS += -DPRINT_ENABLED=0
BACNET_FLAGS += -DMAX_APDU=480
BACNET_FLAGS += -DCRC_USE_TABLE
#BACNET_FLAGS += -DDLMSTP_TEST
BACNET_CORE = ../../src
BACNET_DEMO = ../../demo
BACNET_INCLUDE = ../../include
BACNET_OBJECT = ../../demo/object
BACNET_HANDLER = ../../demo/handler
INCLUDES = -I.
INCLUDES += -I$(BACNET_INCLUDE)
INCLUDES += -I$(BACNET_OBJECT)
INCLUDES += -I$(BACNET_HANDLER)
#OPTIMIZATION = -O0
OPTIMIZATION = -Os
CFLAGS = -fno-common $(INCLUDES) $(BACNET_FLAGS) -Wall -g
CFLAGS += -mno-thumb-interwork
# dead code removal
CFLAGS += -fdata-sections -ffunction-sections
LIBRARY = lib$(TARGET).a
# -Wa,<options> Pass comma-separated <options> on to the assembler
AFLAGS = -Wa,-ahls,-mapcs-32,-adhlns=$(<:.s=.lst)
# -Wl,<options> Pass comma-separated <options> on to the linker
LIBRARIES=-lc,-lgcc,-lm,-L.,-l$(TARGET)
LDFLAGS = -nostartfiles
LDFLAGS += -Wl,-nostdlib,-Map=$(TARGET).map,$(LIBRARIES),-T$(LDSCRIPT)
# dead code removal
LDFLAGS += -Wl,--gc-sections,-static
CPFLAGS = --output-target=binary
ODFLAGS = -x --syms
ASRC = crt.s
PORTSRC = main.c \
timer.c \
isr.c \
init.c \
blinker.c \
rs485.c \
dlmstp.c \
$(BACNET_CORE)/crc.c
DEMOSRC = ai.c \
av.c \
bi.c \
bv.c \
device.c \
$(BACNET_DEMO)/handler/txbuf.c \
$(BACNET_DEMO)/handler/noserv.c \
$(BACNET_DEMO)/handler/h_npdu.c \
$(BACNET_DEMO)/handler/h_whohas.c \
$(BACNET_DEMO)/handler/h_whois.c \
$(BACNET_DEMO)/handler/h_rd.c \
$(BACNET_DEMO)/handler/h_rp.c \
$(BACNET_DEMO)/handler/h_rpm.c \
$(BACNET_DEMO)/handler/h_wp.c \
$(BACNET_DEMO)/handler/h_dcc.c \
$(BACNET_DEMO)/handler/s_iam.c \
$(BACNET_DEMO)/handler/s_ihave.c
CORESRC = $(BACNET_CORE)/npdu.c \
$(BACNET_CORE)/apdu.c \
$(BACNET_CORE)/bacdcode.c \
$(BACNET_CORE)/bacint.c \
$(BACNET_CORE)/bacreal.c \
$(BACNET_CORE)/bacstr.c \
$(BACNET_CORE)/bacaddr.c \
$(BACNET_CORE)/abort.c \
$(BACNET_CORE)/bacerror.c \
$(BACNET_CORE)/reject.c \
$(BACNET_CORE)/bacapp.c \
$(BACNET_CORE)/datetime.c \
$(BACNET_CORE)/dcc.c \
$(BACNET_CORE)/iam.c \
$(BACNET_CORE)/ihave.c \
$(BACNET_CORE)/memcopy.c \
$(BACNET_CORE)/ringbuf.c \
$(BACNET_CORE)/rd.c \
$(BACNET_CORE)/rp.c \
$(BACNET_CORE)/rpm.c \
$(BACNET_CORE)/wp.c \
$(BACNET_CORE)/whohas.c \
$(BACNET_CORE)/whois.c \
$(BACNET_CORE)/version.c
CSRC = $(PORTSRC) $(DEMOSRC)
#CSRC = $(PORTSRC)
AOBJ = $(ASRC:.s=.o)
COBJ = $(CSRC:.c=.o)
COREOBJ = $(CORESRC:.c=.o)
all: $(TARGET).bin $(TARGET).elf
$(OBJDUMP) $(ODFLAGS) $(TARGET).elf > $(TARGET).dmp
$(SIZE) $(TARGET).elf
$(TARGET).bin: $(TARGET).elf
$(OBJCOPY) $(TARGET).elf $(CPFLAGS) $(TARGET).bin
$(TARGET).elf: $(COBJ) $(AOBJ) $(LIBRARY) Makefile
$(CC) $(CFLAGS) $(AOBJ) $(COBJ) $(LDFLAGS) -o $@
lib: $(LIBRARY)
$(LIBRARY): $(COREOBJ) Makefile
$(AR) rcs $@ $(COREOBJ)
# allow a single file to be unoptimized for debugging purposes
#dlmstp.o:
# $(CC) -c $(CFLAGS) $*.c -o $@
#
#main.o:
# $(CC) -c $(CFLAGS) $*.c -o $@
#
#$(BACNET_CORE)/npdu.o:
# $(CC) -c $(CFLAGS) $*.c -o $@
#
#$(BACNET_CORE)/apdu.o:
# $(CC) -c $(CFLAGS) $*.c -o $@
.c.o:
$(CC) -c $(OPTIMIZATION) $(CFLAGS) $*.c -o $@
.s.o:
$(CC) -c $(AFLAGS) $*.s -o $@
.PHONY: clean
clean:
-rm -rf $(COBJ) $(AOBJ) $(COREOBJ)
-rm -rf $(TARGET).elf $(TARGET).bin $(TARGET).dmp $(TARGET).map
-rm -rf $(LIBRARY)
-rm -rf *.lst
## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
# Makefile for AT91SAM7S evaluation kit with RS-485 Transceiver on UART0
# Written by Steve Karg <skarg@users.sourceforge.net> 06-Aug-2007
TARGET=bacnet
# Tools
CC=arm-elf-gcc
OBJCOPY=arm-elf-objcopy
OBJDUMP=arm-elf-objdump
AR=arm-elf-ar
SIZE = arm-elf-size
LDSCRIPT=at91sam7s256.ld
BACNET_FLAGS = -DBACDL_MSTP
BACNET_FLAGS += -DMAX_TSM_TRANSACTIONS=0
BACNET_FLAGS += -DPRINT_ENABLED=0
BACNET_FLAGS += -DMAX_APDU=480
BACNET_FLAGS += -DCRC_USE_TABLE
#BACNET_FLAGS += -DDLMSTP_TEST
BACNET_CORE = ../../src
BACNET_DEMO = ../../demo
BACNET_INCLUDE = ../../include
BACNET_OBJECT = ../../demo/object
BACNET_HANDLER = ../../demo/handler
INCLUDES = -I.
INCLUDES += -I$(BACNET_INCLUDE)
INCLUDES += -I$(BACNET_OBJECT)
INCLUDES += -I$(BACNET_HANDLER)
#OPTIMIZATION = -O0
OPTIMIZATION = -Os
CFLAGS = -fno-common $(INCLUDES) $(BACNET_FLAGS) -Wall -g
CFLAGS += -mno-thumb-interwork
# dead code removal
CFLAGS += -fdata-sections -ffunction-sections
LIBRARY = lib$(TARGET).a
# -Wa,<options> Pass comma-separated <options> on to the assembler
AFLAGS = -Wa,-ahls,-mapcs-32,-adhlns=$(<:.s=.lst)
# -Wl,<options> Pass comma-separated <options> on to the linker
LIBRARIES=-lc,-lgcc,-lm,-L.,-l$(TARGET)
LDFLAGS = -nostartfiles
LDFLAGS += -Wl,-nostdlib,-Map=$(TARGET).map,$(LIBRARIES),-T$(LDSCRIPT)
# dead code removal
LDFLAGS += -Wl,--gc-sections,-static
CPFLAGS = --output-target=binary
ODFLAGS = -x --syms
ASRC = crt.s
PORTSRC = main.c \
timer.c \
isr.c \
init.c \
blinker.c \
rs485.c \
dlmstp.c \
$(BACNET_CORE)/crc.c
DEMOSRC = ai.c \
av.c \
bi.c \
bv.c \
device.c \
$(BACNET_DEMO)/handler/txbuf.c \
$(BACNET_DEMO)/handler/noserv.c \
$(BACNET_DEMO)/handler/h_npdu.c \
$(BACNET_DEMO)/handler/h_whohas.c \
$(BACNET_DEMO)/handler/h_whois.c \
$(BACNET_DEMO)/handler/h_rd.c \
$(BACNET_DEMO)/handler/h_rp.c \
$(BACNET_DEMO)/handler/h_rpm.c \
$(BACNET_DEMO)/handler/h_wp.c \
$(BACNET_DEMO)/handler/h_dcc.c \
$(BACNET_DEMO)/handler/s_iam.c \
$(BACNET_DEMO)/handler/s_ihave.c
CORESRC = $(BACNET_CORE)/npdu.c \
$(BACNET_CORE)/apdu.c \
$(BACNET_CORE)/bacdcode.c \
$(BACNET_CORE)/bacint.c \
$(BACNET_CORE)/bacreal.c \
$(BACNET_CORE)/bacstr.c \
$(BACNET_CORE)/bacaddr.c \
$(BACNET_CORE)/abort.c \
$(BACNET_CORE)/bacerror.c \
$(BACNET_CORE)/reject.c \
$(BACNET_CORE)/bacapp.c \
$(BACNET_CORE)/datetime.c \
$(BACNET_CORE)/dcc.c \
$(BACNET_CORE)/iam.c \
$(BACNET_CORE)/ihave.c \
$(BACNET_CORE)/memcopy.c \
$(BACNET_CORE)/ringbuf.c \
$(BACNET_CORE)/rd.c \
$(BACNET_CORE)/rp.c \
$(BACNET_CORE)/rpm.c \
$(BACNET_CORE)/wp.c \
$(BACNET_CORE)/whohas.c \
$(BACNET_CORE)/whois.c \
$(BACNET_CORE)/version.c
CSRC = $(PORTSRC) $(DEMOSRC)
#CSRC = $(PORTSRC)
AOBJ = $(ASRC:.s=.o)
COBJ = $(CSRC:.c=.o)
COREOBJ = $(CORESRC:.c=.o)
all: $(TARGET).bin $(TARGET).elf
$(OBJDUMP) $(ODFLAGS) $(TARGET).elf > $(TARGET).dmp
$(SIZE) $(TARGET).elf
$(TARGET).bin: $(TARGET).elf
$(OBJCOPY) $(TARGET).elf $(CPFLAGS) $(TARGET).bin
$(TARGET).elf: $(COBJ) $(AOBJ) $(LIBRARY) Makefile
$(CC) $(CFLAGS) $(AOBJ) $(COBJ) $(LDFLAGS) -o $@
lib: $(LIBRARY)
$(LIBRARY): $(COREOBJ) Makefile
$(AR) rcs $@ $(COREOBJ)
# allow a single file to be unoptimized for debugging purposes
#dlmstp.o:
# $(CC) -c $(CFLAGS) $*.c -o $@
#
#main.o:
# $(CC) -c $(CFLAGS) $*.c -o $@
#
#$(BACNET_CORE)/npdu.o:
# $(CC) -c $(CFLAGS) $*.c -o $@
#
#$(BACNET_CORE)/apdu.o:
# $(CC) -c $(CFLAGS) $*.c -o $@
.c.o:
$(CC) -c $(OPTIMIZATION) $(CFLAGS) $*.c -o $@
.s.o:
$(CC) -c $(AFLAGS) $*.s -o $@
.PHONY: clean
clean:
-rm -rf $(COBJ) $(AOBJ) $(COREOBJ)
-rm -rf $(TARGET).elf $(TARGET).bin $(TARGET).dmp $(TARGET).map
-rm -rf $(LIBRARY)
-rm -rf *.lst
## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
File diff suppressed because it is too large Load Diff
+10 -10
View File
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<workspace>
<project>
<path>$WS_DIR$\bacnet.ewp</path>
</project>
<batchBuild/>
</workspace>
<?xml version="1.0" encoding="iso-8859-1"?>
<workspace>
<project>
<path>$WS_DIR$\bacnet.ewp</path>
</project>
<batchBuild/>
</workspace>
+178 -178
View File
@@ -1,178 +1,178 @@
###############################################################################
# Makefile for BACnet
###############################################################################
## General Flags
PROJECT = bacnet
MCU = atmega168
TARGET = bacnet
## Tools
CC = avr-gcc
AR = avr-ar
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
# Source locations
BACNET_CORE = ../../src
BACNET_INCLUDE = ../../include
BACNET_DEMO = ../../demo
# local files for this project
CSRC = main.c \
timer.c \
rs485.c \
dlmstp.c \
apdu.c \
$(BACNET_CORE)/crc.c
# common demo files needed
DEMOSRC = h_rp.c \
device.c \
$(BACNET_DEMO)/handler/txbuf.c \
$(BACNET_DEMO)/handler/h_npdu.c \
$(BACNET_DEMO)/handler/noserv.c
# core BACnet stack files
CORESRC = \
$(BACNET_CORE)/apdu.c \
$(BACNET_CORE)/npdu.c \
$(BACNET_CORE)/bacdcode.c \
$(BACNET_CORE)/bacint.c \
$(BACNET_CORE)/bacreal.c \
$(BACNET_CORE)/bacstr.c \
$(BACNET_CORE)/rp.c \
$(BACNET_CORE)/bacaddr.c \
$(BACNET_CORE)/abort.c \
$(BACNET_CORE)/reject.c \
$(BACNET_CORE)/bacerror.c \
$(BACNET_CORE)/bacapp.c
# $(BACNET_CORE)/iam.c \
# $(BACNET_CORE)/whois.c \
# $(BACNET_CORE)/wp.c \
# $(BACNET_CORE)/version.c
# $(BACNET_CORE)/bacprop.c \
# $(BACNET_CORE)/bactext.c \
# $(BACNET_CORE)/datetime.c \
# $(BACNET_CORE)/indtext.c \
# $(BACNET_CORE)/bigend.c \
# $(BACNET_CORE)/arf.c \
# $(BACNET_CORE)/awf.c \
# $(BACNET_CORE)/cov.c \
# $(BACNET_CORE)/dcc.c \
# $(BACNET_CORE)/iam/iam_client.c \
# $(BACNET_CORE)/ihave.c \
# $(BACNET_CORE)/rd.c \
# $(BACNET_CORE)/rpm.c \
# $(BACNET_CORE)/timesync.c \
# $(BACNET_CORE)/whohas.c \
# $(BACNET_CORE)/filename.c \
# $(BACNET_CORE)/tsm.c \
# $(BACNET_CORE)/address.c \
## Include Directories
INCLUDES = -I. -I$(BACNET_INCLUDE)
# Source to Object conversion
COBJ = $(CSRC:.c=.o)
DEMOOBJ = $(DEMOSRC:.c=.o)
COREOBJ = $(CORESRC:.c=.o)
LIBRARY = lib$(TARGET).a
## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU)
OPTIMIZE_FLAGS = -mcall-prologues
#OPTIMIZE_FLAGS += -finline-functions
OPTIMIZE_FLAGS += -finline-functions-called-once
#OPTIMIZATION = -O0
#OPTIMIZATION = -Os
OPTIMIZATION = -Os $(OPTIMIZE_FLAGS)
#OPTIMIZATION = -O3 $(OPTIMIZE_FLAGS)
## Compile options common for all C compilation units.
BFLAGS = -DBACDL_MSTP
BFLAGS += -DMAX_APDU=50
BFLAGS += -DBIG_ENDIAN=0
BFLAGS += -DMAX_TSM_TRANSACTIONS=0
#BFLAGS += -DCRC_USE_TABLE
#BFLAGS += -DBACAPP_REAL
#BFLAGS += -DBACAPP_OBJECT_ID
#BFLAGS += -DBACAPP_UNSIGNED
#BFLAGS += -DBACAPP_ENUMERATED
#BFLAGS += -DBACAPP_CHARACTER_STRING
#BFLAGS += -DWRITE_PROPERTY
BFLAGS += -DMAX_ANALOG_VALUES=0
BFLAGS += -DMAX_BINARY_VALUES=0
CFLAGS = $(COMMON)
# dead code removal
CFLAGS += -ffunction-sections -fdata-sections
CFLAGS += -Wall -gdwarf-2 $(BFLAGS) $(OPTIMIZATION) -fsigned-char
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d
## Assembly specific flags
ASMFLAGS = $(COMMON)
ASMFLAGS += $(CFLAGS)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
## Linker flags
LDFLAGS = $(COMMON)
#dead code removal
#LDFLAGS += -Wl,-nostartfiles,-nostdlib
LDFLAGS += -Wl,--gc-sections,-static
LDFLAGS += -Wl,-Map=$(TARGET).map,-L.,-l$(TARGET)
#LDFLAGS += -Wl,-Map=$(TARGET).map
## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom
HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings
## Objects that must be built in order to link
OBJECTS = $(COBJ) $(DEMOOBJ)
#OBJECTS = $(COBJ)
## Build
TARGET_ELF=$(TARGET).elf
all: $(LIBRARY) $(TARGET_ELF) $(TARGET).hex $(TARGET).eep $(TARGET).lst \
size Makefile
##Link
$(TARGET_ELF): $(OBJECTS) $(LIBRARY)
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
%.hex: $(TARGET_ELF)
$(OBJCOPY) -O ihex $(HEX_FLASH_FLAGS) $< $@
%.eep: $(TARGET_ELF)
-$(OBJCOPY) $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
%.lst: $(TARGET_ELF)
$(OBJDUMP) -h -S $< > $@
lib: $(LIBRARY)
$(LIBRARY): $(COREOBJ) Makefile
$(AR) rcs $@ $(COREOBJ)
$(OBJDUMP) --syms $@ > $(LIBRARY:.a=.lst)
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $*.c -o $@
size: ${TARGET_ELF}
@echo
@${SIZE} -C --mcu=${MCU} ${TARGET_ELF}
## Clean target
.PHONY: clean
clean:
-rm -rf $(OBJECTS) $(TARGET_ELF) dep/*
-rm -rf $(LIBRARY) $(COREOBJ) $(LIBRARY:.a=.lst)
-rm -rf $(TARGET).hex $(TARGET).eep $(TARGET).lst $(TARGET).map
## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
###############################################################################
# Makefile for BACnet
###############################################################################
## General Flags
PROJECT = bacnet
MCU = atmega168
TARGET = bacnet
## Tools
CC = avr-gcc
AR = avr-ar
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
# Source locations
BACNET_CORE = ../../src
BACNET_INCLUDE = ../../include
BACNET_DEMO = ../../demo
# local files for this project
CSRC = main.c \
timer.c \
rs485.c \
dlmstp.c \
apdu.c \
$(BACNET_CORE)/crc.c
# common demo files needed
DEMOSRC = h_rp.c \
device.c \
$(BACNET_DEMO)/handler/txbuf.c \
$(BACNET_DEMO)/handler/h_npdu.c \
$(BACNET_DEMO)/handler/noserv.c
# core BACnet stack files
CORESRC = \
$(BACNET_CORE)/apdu.c \
$(BACNET_CORE)/npdu.c \
$(BACNET_CORE)/bacdcode.c \
$(BACNET_CORE)/bacint.c \
$(BACNET_CORE)/bacreal.c \
$(BACNET_CORE)/bacstr.c \
$(BACNET_CORE)/rp.c \
$(BACNET_CORE)/bacaddr.c \
$(BACNET_CORE)/abort.c \
$(BACNET_CORE)/reject.c \
$(BACNET_CORE)/bacerror.c \
$(BACNET_CORE)/bacapp.c
# $(BACNET_CORE)/iam.c \
# $(BACNET_CORE)/whois.c \
# $(BACNET_CORE)/wp.c \
# $(BACNET_CORE)/version.c
# $(BACNET_CORE)/bacprop.c \
# $(BACNET_CORE)/bactext.c \
# $(BACNET_CORE)/datetime.c \
# $(BACNET_CORE)/indtext.c \
# $(BACNET_CORE)/bigend.c \
# $(BACNET_CORE)/arf.c \
# $(BACNET_CORE)/awf.c \
# $(BACNET_CORE)/cov.c \
# $(BACNET_CORE)/dcc.c \
# $(BACNET_CORE)/iam/iam_client.c \
# $(BACNET_CORE)/ihave.c \
# $(BACNET_CORE)/rd.c \
# $(BACNET_CORE)/rpm.c \
# $(BACNET_CORE)/timesync.c \
# $(BACNET_CORE)/whohas.c \
# $(BACNET_CORE)/filename.c \
# $(BACNET_CORE)/tsm.c \
# $(BACNET_CORE)/address.c \
## Include Directories
INCLUDES = -I. -I$(BACNET_INCLUDE)
# Source to Object conversion
COBJ = $(CSRC:.c=.o)
DEMOOBJ = $(DEMOSRC:.c=.o)
COREOBJ = $(CORESRC:.c=.o)
LIBRARY = lib$(TARGET).a
## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU)
OPTIMIZE_FLAGS = -mcall-prologues
#OPTIMIZE_FLAGS += -finline-functions
OPTIMIZE_FLAGS += -finline-functions-called-once
#OPTIMIZATION = -O0
#OPTIMIZATION = -Os
OPTIMIZATION = -Os $(OPTIMIZE_FLAGS)
#OPTIMIZATION = -O3 $(OPTIMIZE_FLAGS)
## Compile options common for all C compilation units.
BFLAGS = -DBACDL_MSTP
BFLAGS += -DMAX_APDU=50
BFLAGS += -DBIG_ENDIAN=0
BFLAGS += -DMAX_TSM_TRANSACTIONS=0
#BFLAGS += -DCRC_USE_TABLE
#BFLAGS += -DBACAPP_REAL
#BFLAGS += -DBACAPP_OBJECT_ID
#BFLAGS += -DBACAPP_UNSIGNED
#BFLAGS += -DBACAPP_ENUMERATED
#BFLAGS += -DBACAPP_CHARACTER_STRING
#BFLAGS += -DWRITE_PROPERTY
BFLAGS += -DMAX_ANALOG_VALUES=0
BFLAGS += -DMAX_BINARY_VALUES=0
CFLAGS = $(COMMON)
# dead code removal
CFLAGS += -ffunction-sections -fdata-sections
CFLAGS += -Wall -gdwarf-2 $(BFLAGS) $(OPTIMIZATION) -fsigned-char
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d
## Assembly specific flags
ASMFLAGS = $(COMMON)
ASMFLAGS += $(CFLAGS)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
## Linker flags
LDFLAGS = $(COMMON)
#dead code removal
#LDFLAGS += -Wl,-nostartfiles,-nostdlib
LDFLAGS += -Wl,--gc-sections,-static
LDFLAGS += -Wl,-Map=$(TARGET).map,-L.,-l$(TARGET)
#LDFLAGS += -Wl,-Map=$(TARGET).map
## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom
HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings
## Objects that must be built in order to link
OBJECTS = $(COBJ) $(DEMOOBJ)
#OBJECTS = $(COBJ)
## Build
TARGET_ELF=$(TARGET).elf
all: $(LIBRARY) $(TARGET_ELF) $(TARGET).hex $(TARGET).eep $(TARGET).lst \
size Makefile
##Link
$(TARGET_ELF): $(OBJECTS) $(LIBRARY)
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
%.hex: $(TARGET_ELF)
$(OBJCOPY) -O ihex $(HEX_FLASH_FLAGS) $< $@
%.eep: $(TARGET_ELF)
-$(OBJCOPY) $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0
%.lst: $(TARGET_ELF)
$(OBJDUMP) -h -S $< > $@
lib: $(LIBRARY)
$(LIBRARY): $(COREOBJ) Makefile
$(AR) rcs $@ $(COREOBJ)
$(OBJDUMP) --syms $@ > $(LIBRARY:.a=.lst)
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $*.c -o $@
size: ${TARGET_ELF}
@echo
@${SIZE} -C --mcu=${MCU} ${TARGET_ELF}
## Clean target
.PHONY: clean
clean:
-rm -rf $(OBJECTS) $(TARGET_ELF) dep/*
-rm -rf $(LIBRARY) $(COREOBJ) $(LIBRARY:.a=.lst)
-rm -rf $(TARGET).hex $(TARGET).eep $(TARGET).lst $(TARGET).map
## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
+45 -45
View File
@@ -1,45 +1,45 @@
This port was originally done with the Atmel ATmega168
I used the following tools:
1. The WinAVR compiler avr-gcc (GCC) 4.1.2 (WinAVR 20070525)
and tools from <http://winavr.sourceforge.net/>, hints and
sample code from <http://www.avrfreaks.net/> and
<http://savannah.gnu.org/projects/avr-libc/>.
"avr-binutils, avr-gcc, and avr-libc form the heart of the
Free Software toolchain for the Atmel AVR microcontrollers."
2. AVR Studio 4 from Atmel <http://atmel.com/>
The hardware is expected to utilize the signals as defined
in the spreadsheet hardware.ods (OpenOffice.org calc).
Attach a DS75176 RS-485 transceiver (or similar) to the USART.
DS75176 ATmega168
------ ---------
RO RXD
/RE --choice of I/O
DE --choice of I/O
DI TXD
GND GND
DO --to RS-485 wire
DO --to RS-485 wire
+5V From 5V Regulator
The makefile allows you to build a simple server.
dlmstp is the datalink layer for MS/TP over RS-485.
This project uses an MS/TP Slave Node.
I used the makefile from the command line on Windows:
C:\code\bacnet-stack\ports\atmega168> make clean all
The BACnet Capabilities include ReadProperty support.
The BACnet objects include only a Device object.
All required object properties can be retrieved using ReadProperty.
With full optimization, the statistics on the demo are:
avr-gcc (GCC) 4.2.2 (WinAVR 20071221rc1)
Device: atmega168
Program: 8734 bytes (53.3% Full)
Data: 254 bytes (24.8% Full) (does not include CStack)
Hopefully you find this code useful!
Steve Karg <skarg@users.sourceforge.net>
This port was originally done with the Atmel ATmega168
I used the following tools:
1. The WinAVR compiler avr-gcc (GCC) 4.1.2 (WinAVR 20070525)
and tools from <http://winavr.sourceforge.net/>, hints and
sample code from <http://www.avrfreaks.net/> and
<http://savannah.gnu.org/projects/avr-libc/>.
"avr-binutils, avr-gcc, and avr-libc form the heart of the
Free Software toolchain for the Atmel AVR microcontrollers."
2. AVR Studio 4 from Atmel <http://atmel.com/>
The hardware is expected to utilize the signals as defined
in the spreadsheet hardware.ods (OpenOffice.org calc).
Attach a DS75176 RS-485 transceiver (or similar) to the USART.
DS75176 ATmega168
------ ---------
RO RXD
/RE --choice of I/O
DE --choice of I/O
DI TXD
GND GND
DO --to RS-485 wire
DO --to RS-485 wire
+5V From 5V Regulator
The makefile allows you to build a simple server.
dlmstp is the datalink layer for MS/TP over RS-485.
This project uses an MS/TP Slave Node.
I used the makefile from the command line on Windows:
C:\code\bacnet-stack\ports\atmega168> make clean all
The BACnet Capabilities include ReadProperty support.
The BACnet objects include only a Device object.
All required object properties can be retrieved using ReadProperty.
With full optimization, the statistics on the demo are:
avr-gcc (GCC) 4.2.2 (WinAVR 20071221rc1)
Device: atmega168
Program: 8734 bytes (53.3% Full)
Data: 254 bytes (24.8% Full) (does not include CStack)
Hopefully you find this code useful!
Steve Karg <skarg@users.sourceforge.net>
@@ -1,3 +1,3 @@
Made with the free Dev-C++ IDE
http://bloodshed.net/dev/
Made with the free Dev-C++ IDE
http://bloodshed.net/dev/
File diff suppressed because it is too large Load Diff
+10 -10
View File
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<workspace>
<project>
<path>$WS_DIR$\bacnet.ewp</path>
</project>
<batchBuild/>
</workspace>
<?xml version="1.0" encoding="iso-8859-1"?>
<workspace>
<project>
<path>$WS_DIR$\bacnet.ewp</path>
</project>
<batchBuild/>
</workspace>
@@ -15,8 +15,8 @@ ATmega323 iom323.h 64 16 256 0x73 0x1E 0x95 0x01 UBRRL UCSRB UCSRA TXEN RXEN TXC
ATmega329 iom329.h 64 32 256 0x1E 0x95 0x03 UBRR UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCSR
ATmega3290 iom3290.h 64 32 256 0x1E 0x95 0x04 UBRR UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCSR
ATmega64 iom64.h 128 32 256 0x46 0x1E 0x96 0x02 UBRR0L UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCR
ATmega644 iom644.h 128 32 256 0x1E 0x96 0x09 UBRR0 UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCSR
ATmega644P iom644.h 128 32 256 0x1E 0x96 0x0A UBRR1 UCSR1B UCSR1A TXEN1 RXEN1 TXC1 RXC1 UDR1 SPMCSR
ATmega644 iom644.h 128 32 256 0x1E 0x96 0x09 UBRR0 UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCSR
ATmega644P iom644.h 128 32 256 0x1E 0x96 0x0A UBRR1 UCSR1B UCSR1A TXEN1 RXEN1 TXC1 RXC1 UDR1 SPMCSR
ATmega649 iom649.h 128 32 256 0x1E 0x96 0x03 UBRR UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCSR
ATmega6490 iom6490.h 128 32 256 0x1E 0x96 0x04 UBRR UCSRB UCSRA TXEN RXEN TXC RXC UDR SPMCSR
ATmega128 iom128.h 128 32 512 0x44 0x1E 0x97 0x02 UBRR0L UCSR0B UCSR0A TXEN0 RXEN0 TXC0 RXC0 UDR0 SPMCSR
+10
View File
@@ -32,6 +32,8 @@
#include "bo.h"
#include "rs485.h"
#include "dlmstp.h"
#include "seeprom.h"
#include "nvdata.h"
/* me */
#include "test.h"
@@ -117,6 +119,7 @@ void test_task(
void)
{
uint8_t data_register = 0;
uint16_t id = 0;
if (timer_interval_expired(&Test_Timer)) {
timer_interval_reset(&Test_Timer);
@@ -159,13 +162,20 @@ void test_task(
case '9':
rs485_baud_rate_set(9600);
break;
case 'e':
seeprom_bytes_read(NV_SEEPROM_TYPE_0, (uint8_t *) &id, 2);
sprintf(Send_Buffer, "\r\n%04X", id);
serial_bytes_send((uint8_t *) Send_Buffer, strlen(Send_Buffer));
break;
case 'b':
sprintf(Send_Buffer, "\r\n%lubps",
(unsigned long) rs485_baud_rate());
serial_bytes_send((uint8_t *) Send_Buffer, strlen(Send_Buffer));
break;
case 'm':
sprintf(Send_Buffer, "\r\nMax:%u",
(unsigned) dlmstp_max_master());
serial_bytes_send((uint8_t *) Send_Buffer, strlen(Send_Buffer));
break;
default:
break;
+431 -431
View File
@@ -1,431 +1,431 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "timer.h"
/* generic elapsed timer handling */
/* interval not to exceed 49.7 days */
/* interval of 1ms may be 0 to 1ms */
/*************************************************************************
* Description: Sets the start time for an elapsed timer
* Returns: the value of the start timer
* Notes: none
*************************************************************************/
void timer_elapsed_start(
struct etimer *t)
{
uint32_t now = timer_milliseconds();
if (t) {
t->start = now;
}
}
/*************************************************************************
* Description: Gets the amount of elapsed time in milliseconds
* Returns: elapsed time in milliseconds
* Notes: none
*************************************************************************/
uint32_t timer_elapsed_time(
struct etimer *t)
{
uint32_t now = timer_milliseconds();
uint32_t delta = 0;
if (t) {
delta = now - t->start;
}
return delta;
}
/*************************************************************************
* Description: Sets the start time with an offset
* Returns: elapsed time in milliseconds
* Notes: none
*************************************************************************/
void timer_elapsed_start_offset(
struct etimer *t,
uint32_t offset)
{
uint32_t now = timer_milliseconds();
if (t) {
t->start = now + offset;
}
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_milliseconds(
struct etimer *t,
uint32_t milliseconds)
{
return (timer_elapsed_time(t) >= milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_seconds(
struct etimer * t,
uint32_t seconds)
{
uint32_t milliseconds = seconds;
milliseconds *= 1000L;
return timer_elapsed_milliseconds(t, milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_minutes(
struct etimer * t,
uint32_t minutes)
{
uint32_t milliseconds = minutes;
milliseconds *= 1000L;
milliseconds *= 60L;
return timer_elapsed_milliseconds(t, milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_milliseconds_short(
struct etimer * t,
uint16_t value)
{
uint32_t milliseconds;
milliseconds = value;
return (timer_elapsed_time(t) >= milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_seconds_short(
struct etimer * t,
uint16_t value)
{
return timer_elapsed_seconds(t, value);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_minutes_short(
struct etimer * t,
uint16_t value)
{
return timer_elapsed_minutes(t, value);
}
/*************************************************************************
* Description: Starts an interval timer
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_start(
struct itimer *t,
uint32_t interval)
{
if (t) {
t->start = timer_milliseconds();
t->interval = interval;
}
}
/*************************************************************************
* Description: Starts an interval timer
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_start_seconds(
struct itimer *t,
uint32_t seconds)
{
uint32_t interval = seconds;
interval *= 1000L;
timer_interval_start(t, interval);
}
/*************************************************************************
* Description: Starts an interval timer
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_start_minutes(
struct itimer *t,
uint32_t minutes)
{
uint32_t interval = minutes;
interval *= 1000L;
interval *= 60L;
timer_interval_start(t, interval);
}
/*************************************************************************
* Description: Determines the amount of time that has elapsed
* Returns: elapsed milliseconds
* Notes: none
*************************************************************************/
uint32_t timer_interval_elapsed(
struct itimer *t)
{
uint32_t now = timer_milliseconds();
uint32_t delta = 0;
if (t) {
delta = now - t->start;
}
return delta;
}
/*************************************************************************
* Description: Determines the amount of time that has elapsed
* Returns: elapsed milliseconds
* Notes: none
*************************************************************************/
uint32_t timer_interval(
struct itimer * t)
{
uint32_t interval = 0;
if (t) {
interval = t->interval;
}
return interval;
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_interval_expired(
struct itimer * t)
{
bool expired = false;
if (t) {
if (t->interval) {
expired = timer_interval_elapsed(t) >= t->interval;
}
}
return expired;
}
/*************************************************************************
* Description: Sets the interval value to zero so it never expires
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_no_expire(
struct itimer *t)
{
if (t) {
t->interval = 0;
}
}
/*************************************************************************
* Description: Adds another interval to the start time. Used for cyclic
* timers that won't lose ticks.
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_reset(
struct itimer *t)
{
if (t) {
t->start += t->interval;
}
}
/*************************************************************************
* Description: Restarts the timer with the same interval
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_restart(
struct itimer *t)
{
if (t) {
t->start = timer_milliseconds();
}
}
/*************************************************************************
* Description: Return the elapsed time
* Returns: number of milliseconds elapsed
* Notes: only up to 255ms elapsed
**************************************************************************/
uint8_t timer_milliseconds_delta(
uint8_t start)
{
return (timer_milliseconds_byte() - start);
}
/*************************************************************************
* Description: Mark the start of a delta timer
* Returns: mark timer starting tick
* Notes: only up to 255ms elapsed
**************************************************************************/
uint8_t timer_milliseconds_mark(
void)
{
return timer_milliseconds_byte();
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
static uint32_t Milliseconds;
uint32_t timer_milliseconds(
void)
{
return Milliseconds;
}
uint32_t timer_milliseconds_set(
uint32_t value)
{
uint32_t old_value = Milliseconds;
Milliseconds = value;
return old_value;
}
void testElapsedTimer(
Test * pTest)
{
struct etimer t;
uint32_t test_time = 0;
timer_milliseconds_set(test_time);
timer_elapsed_start(&t);
ct_test(pTest, timer_elapsed_time(&t) == test_time);
test_time = 0xffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_elapsed_time(&t) == test_time);
test_time = 0xffffffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_elapsed_time(&t) == test_time);
}
void testIntervalTimer(
Test * pTest)
{
struct itimer t;
uint32_t interval = 0;
uint32_t test_time = 0;
timer_milliseconds_set(test_time);
timer_interval_start(&t, interval);
test_time = 0xffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_interval(&t) == interval);
ct_test(pTest, timer_interval_elapsed(&t) == test_time);
test_time = 0xffffffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_interval(&t) == interval);
ct_test(pTest, timer_interval_elapsed(&t) == test_time);
test_time = 0;
timer_milliseconds_set(test_time);
interval = 0xffff;
timer_interval_start(&t, interval);
ct_test(pTest, timer_interval(&t) == interval);
interval = 0xffffffff;
timer_interval_start(&t, interval);
ct_test(pTest, timer_interval(&t) == interval);
interval = 0;
timer_interval_start_seconds(&t, interval);
ct_test(pTest, timer_interval(&t) == interval);
interval = 60L;
timer_interval_start_seconds(&t, interval);
interval *= 1000L;
ct_test(pTest, timer_interval(&t) == interval);
}
#ifdef TEST_TIMER
int main(
void)
{
Test *pTest;
bool rc;
pTest = ct_create("Timer", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, testElapsedTimer);
assert(rc);
rc = ct_addTestFunction(pTest, testIntervalTimer);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif
#endif
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "timer.h"
/* generic elapsed timer handling */
/* interval not to exceed 49.7 days */
/* interval of 1ms may be 0 to 1ms */
/*************************************************************************
* Description: Sets the start time for an elapsed timer
* Returns: the value of the start timer
* Notes: none
*************************************************************************/
void timer_elapsed_start(
struct etimer *t)
{
uint32_t now = timer_milliseconds();
if (t) {
t->start = now;
}
}
/*************************************************************************
* Description: Gets the amount of elapsed time in milliseconds
* Returns: elapsed time in milliseconds
* Notes: none
*************************************************************************/
uint32_t timer_elapsed_time(
struct etimer *t)
{
uint32_t now = timer_milliseconds();
uint32_t delta = 0;
if (t) {
delta = now - t->start;
}
return delta;
}
/*************************************************************************
* Description: Sets the start time with an offset
* Returns: elapsed time in milliseconds
* Notes: none
*************************************************************************/
void timer_elapsed_start_offset(
struct etimer *t,
uint32_t offset)
{
uint32_t now = timer_milliseconds();
if (t) {
t->start = now + offset;
}
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_milliseconds(
struct etimer *t,
uint32_t milliseconds)
{
return (timer_elapsed_time(t) >= milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_seconds(
struct etimer * t,
uint32_t seconds)
{
uint32_t milliseconds = seconds;
milliseconds *= 1000L;
return timer_elapsed_milliseconds(t, milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_minutes(
struct etimer * t,
uint32_t minutes)
{
uint32_t milliseconds = minutes;
milliseconds *= 1000L;
milliseconds *= 60L;
return timer_elapsed_milliseconds(t, milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_milliseconds_short(
struct etimer * t,
uint16_t value)
{
uint32_t milliseconds;
milliseconds = value;
return (timer_elapsed_time(t) >= milliseconds);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_seconds_short(
struct etimer * t,
uint16_t value)
{
return timer_elapsed_seconds(t, value);
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_elapsed_minutes_short(
struct etimer * t,
uint16_t value)
{
return timer_elapsed_minutes(t, value);
}
/*************************************************************************
* Description: Starts an interval timer
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_start(
struct itimer *t,
uint32_t interval)
{
if (t) {
t->start = timer_milliseconds();
t->interval = interval;
}
}
/*************************************************************************
* Description: Starts an interval timer
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_start_seconds(
struct itimer *t,
uint32_t seconds)
{
uint32_t interval = seconds;
interval *= 1000L;
timer_interval_start(t, interval);
}
/*************************************************************************
* Description: Starts an interval timer
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_start_minutes(
struct itimer *t,
uint32_t minutes)
{
uint32_t interval = minutes;
interval *= 1000L;
interval *= 60L;
timer_interval_start(t, interval);
}
/*************************************************************************
* Description: Determines the amount of time that has elapsed
* Returns: elapsed milliseconds
* Notes: none
*************************************************************************/
uint32_t timer_interval_elapsed(
struct itimer *t)
{
uint32_t now = timer_milliseconds();
uint32_t delta = 0;
if (t) {
delta = now - t->start;
}
return delta;
}
/*************************************************************************
* Description: Determines the amount of time that has elapsed
* Returns: elapsed milliseconds
* Notes: none
*************************************************************************/
uint32_t timer_interval(
struct itimer * t)
{
uint32_t interval = 0;
if (t) {
interval = t->interval;
}
return interval;
}
/*************************************************************************
* Description: Tests to see if time has elapsed
* Returns: true if time has elapsed
* Notes: none
*************************************************************************/
bool timer_interval_expired(
struct itimer * t)
{
bool expired = false;
if (t) {
if (t->interval) {
expired = timer_interval_elapsed(t) >= t->interval;
}
}
return expired;
}
/*************************************************************************
* Description: Sets the interval value to zero so it never expires
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_no_expire(
struct itimer *t)
{
if (t) {
t->interval = 0;
}
}
/*************************************************************************
* Description: Adds another interval to the start time. Used for cyclic
* timers that won't lose ticks.
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_reset(
struct itimer *t)
{
if (t) {
t->start += t->interval;
}
}
/*************************************************************************
* Description: Restarts the timer with the same interval
* Returns: nothing
* Notes: none
*************************************************************************/
void timer_interval_restart(
struct itimer *t)
{
if (t) {
t->start = timer_milliseconds();
}
}
/*************************************************************************
* Description: Return the elapsed time
* Returns: number of milliseconds elapsed
* Notes: only up to 255ms elapsed
**************************************************************************/
uint8_t timer_milliseconds_delta(
uint8_t start)
{
return (timer_milliseconds_byte() - start);
}
/*************************************************************************
* Description: Mark the start of a delta timer
* Returns: mark timer starting tick
* Notes: only up to 255ms elapsed
**************************************************************************/
uint8_t timer_milliseconds_mark(
void)
{
return timer_milliseconds_byte();
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
static uint32_t Milliseconds;
uint32_t timer_milliseconds(
void)
{
return Milliseconds;
}
uint32_t timer_milliseconds_set(
uint32_t value)
{
uint32_t old_value = Milliseconds;
Milliseconds = value;
return old_value;
}
void testElapsedTimer(
Test * pTest)
{
struct etimer t;
uint32_t test_time = 0;
timer_milliseconds_set(test_time);
timer_elapsed_start(&t);
ct_test(pTest, timer_elapsed_time(&t) == test_time);
test_time = 0xffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_elapsed_time(&t) == test_time);
test_time = 0xffffffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_elapsed_time(&t) == test_time);
}
void testIntervalTimer(
Test * pTest)
{
struct itimer t;
uint32_t interval = 0;
uint32_t test_time = 0;
timer_milliseconds_set(test_time);
timer_interval_start(&t, interval);
test_time = 0xffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_interval(&t) == interval);
ct_test(pTest, timer_interval_elapsed(&t) == test_time);
test_time = 0xffffffff;
timer_milliseconds_set(test_time);
ct_test(pTest, timer_interval(&t) == interval);
ct_test(pTest, timer_interval_elapsed(&t) == test_time);
test_time = 0;
timer_milliseconds_set(test_time);
interval = 0xffff;
timer_interval_start(&t, interval);
ct_test(pTest, timer_interval(&t) == interval);
interval = 0xffffffff;
timer_interval_start(&t, interval);
ct_test(pTest, timer_interval(&t) == interval);
interval = 0;
timer_interval_start_seconds(&t, interval);
ct_test(pTest, timer_interval(&t) == interval);
interval = 60L;
timer_interval_start_seconds(&t, interval);
interval *= 1000L;
ct_test(pTest, timer_interval(&t) == interval);
}
#ifdef TEST_TIMER
int main(
void)
{
Test *pTest;
bool rc;
pTest = ct_create("Timer", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, testElapsedTimer);
assert(rc);
rc = ct_addTestFunction(pTest, testIntervalTimer);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif
#endif
+8 -8
View File
@@ -1,8 +1,8 @@
BACnet Etherent
Demonstrates the Ethernet peripheral by implmenting BACnet over Ethernet
on the RX62N Development Kit. The project is compiled with the RX Standard
Toolchain, and the default drivers included with the RX62N kit.
 
The project does not use any additional hardware.
 
The project was tested using a BACnet/IP to BACnet Ethernet router, using the bacnet-tools from the BACnet Protocol Stack site.
BACnet Etherent
Demonstrates the Ethernet peripheral by implmenting BACnet over Ethernet
on the RX62N Development Kit. The project is compiled with the RX Standard
Toolchain, and the default drivers included with the RX62N kit.
 
The project does not use any additional hardware.
 
The project was tested using a BACnet/IP to BACnet Ethernet router, using the bacnet-tools from the BACnet Protocol Stack site.
File diff suppressed because it is too large Load Diff
+10 -10
View File
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<workspace>
<project>
<path>$WS_DIR$\bacnet.ewp</path>
</project>
<batchBuild/>
</workspace>
<?xml version="1.0" encoding="iso-8859-1"?>
<workspace>
<project>
<path>$WS_DIR$\bacnet.ewp</path>
</project>
<batchBuild/>
</workspace>
+31 -31
View File
@@ -1,31 +1,31 @@
This port was done with the STM32 ARM Cortex-M3 STM32F103RGT6 on
a STM32 Discovery Kit using the STM32 CMSIS library and drivers
and IAR EWARM 6.10 compiler.
The CMSIS library was 21MiB compressed, so I didn't include it
as part of this project. The CMSIS and drivers
can be found by following the 'Click here for STM32
embedded firmware' link from the resources page:
http://www.st.com/stonline/stappl/resourceSelector/app?page=resourceSelector&doctype=FIRMWARE&SubClassID=1169
There will be a list of firmware resources.
The library you are looking for is in the
ARM-based 32-bit MCU STM32F10xxx standard peripheral library.
Download the
ARM-based 32-bit MCU STM32F10xxx standard peripheral library
and the CMSIS library can be found in
'…\STM32F10x_StdPeriph_Lib_V3.4.0\Libraries\CMSIS\CM3'.
Copy the contents of 'CMSIS' to the 'CMSIS' folder in this project.
and the drivers library can be found in
'…\STM32F10x_StdPeriph_Lib_V3.4.0\Libraries\STM32F10x_StdPeriph_Driver'.
Copy the contents of 'STM32F10x_StdPeriph_Driver' to the
'drivers' folder in this project.
The hardware interface only uses the USART and a peripheral pin
(RTS) for the MS/TP RS-485 interface, and the System Clock for
the millisecond timer.
It was created for the STM32 Design Challenge on March 20, 2011,
by Steve Karg. Although the design didn't win any awards,
it was one of the six finalists and was on display at the
STM booth at the 2010 Embedded Systems Conference West.
http://www.stm32challenge.com/
This port was done with the STM32 ARM Cortex-M3 STM32F103RGT6 on
a STM32 Discovery Kit using the STM32 CMSIS library and drivers
and IAR EWARM 6.10 compiler.
The CMSIS library was 21MiB compressed, so I didn't include it
as part of this project. The CMSIS and drivers
can be found by following the 'Click here for STM32
embedded firmware' link from the resources page:
http://www.st.com/stonline/stappl/resourceSelector/app?page=resourceSelector&doctype=FIRMWARE&SubClassID=1169
There will be a list of firmware resources.
The library you are looking for is in the
ARM-based 32-bit MCU STM32F10xxx standard peripheral library.
Download the
ARM-based 32-bit MCU STM32F10xxx standard peripheral library
and the CMSIS library can be found in
'…\STM32F10x_StdPeriph_Lib_V3.4.0\Libraries\CMSIS\CM3'.
Copy the contents of 'CMSIS' to the 'CMSIS' folder in this project.
and the drivers library can be found in
'…\STM32F10x_StdPeriph_Lib_V3.4.0\Libraries\STM32F10x_StdPeriph_Driver'.
Copy the contents of 'STM32F10x_StdPeriph_Driver' to the
'drivers' folder in this project.
The hardware interface only uses the USART and a peripheral pin
(RTS) for the MS/TP RS-485 interface, and the System Clock for
the millisecond timer.
It was created for the STM32 Design Challenge on March 20, 2011,
by Steve Karg. Although the design didn't win any awards,
it was one of the six finalists and was on display at the
STM booth at the 2010 Embedded Systems Conference West.
http://www.stm32challenge.com/
@@ -1,31 +1,31 @@
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000 ;
define symbol __ICFEDIT_region_ROM_end__ = 0x080FFFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x20017FFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x800;
define symbol __ICFEDIT_size_heap__ = 0x200;
/**** End of ICF editor section. ###ICF###*/
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
initialize by copy { readwrite };
do not initialize { section .noinit };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place in ROM_region { readonly };
place in RAM_region { readwrite,
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000 ;
define symbol __ICFEDIT_region_ROM_end__ = 0x080FFFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x20017FFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x800;
define symbol __ICFEDIT_size_heap__ = 0x200;
/**** End of ICF editor section. ###ICF###*/
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
initialize by copy { readwrite };
do not initialize { section .noinit };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place in ROM_region { readonly };
place in RAM_region { readwrite,
block CSTACK, block HEAP };
+7 -7
View File
@@ -1,7 +1,7 @@
@echo off
echo Build for Borland 5.5 tools
set BORLAND_DIR=c:\borland\bcc55
%BORLAND_DIR%\bin\make -f makefile.mak clean
%BORLAND_DIR%\bin\make -f makefile.mak all
@echo off
echo Build for Borland 5.5 tools
set BORLAND_DIR=c:\borland\bcc55
%BORLAND_DIR%\bin\make -f makefile.mak clean
%BORLAND_DIR%\bin\make -f makefile.mak all
+15 -15
View File
@@ -1,15 +1,15 @@
BACnet Stack - Win32
This directory contains a demo program that compiles with a Win32 compiler.
It was tested with the freely downloadable Borland C++ 5.5, as well as
Borland C++ 5 and Visual C++ 6.0.
The makefile.mak file is used with the Borland command line tools.
Run setvars.bat to configure the environment for the Borland tools.
Edit it if necessary to set the correct location of your tools.
The bacnet.ide file is used with the Borland IDE.
The bacnet directory is used with Visual C++ 6 tools, and there is a
workspace file bacnet.dsw that is used to compile the demo program.
BACnet Stack - Win32
This directory contains a demo program that compiles with a Win32 compiler.
It was tested with the freely downloadable Borland C++ 5.5, as well as
Borland C++ 5 and Visual C++ 6.0.
The makefile.mak file is used with the Borland command line tools.
Run setvars.bat to configure the environment for the Borland tools.
Edit it if necessary to set the correct location of your tools.
The bacnet.ide file is used with the Borland IDE.
The bacnet directory is used with Visual C++ 6 tools, and there is a
workspace file bacnet.dsw that is used to compile the demo program.
+109 -109
View File
@@ -1,110 +1,110 @@
#
# Simple makefile to build an executable for Win32 console
#
# This makefile assumes Borland development environment
# on Windows NT/9x/2000/XP
# Tools: bcc32, make, ilink
!ifndef BORLAND_DIR
BORLAND_DIR_Not_Defined:
@echo .
@echo You must define environment variable BORLAND_DIR to compile.
!endif
PRODUCT = rs485
PRODUCT_EXE = $(PRODUCT).exe
# Choose the Data Link Layer to Enable
DEFINES = -DBACDL_MSTP=1;TEST_RS485;TEST_RS485_TRANSMIT
SRCS = rs485.c
OBJS = $(SRCS:.c=.obj)
# Compiler definitions
#
BCC_CFG = bcc32.cfg
CC = $(BORLAND_DIR)\bin\bcc32 +$(BCC_CFG)
#LINK = $(BORLAND_DIR)\bin\tlink32
LINK = $(BORLAND_DIR)\bin\ilink32
TLIB = $(BORLAND_DIR)\bin\tlib
#
# Include directories
#
CC_DIR = $(BORLAND_DIR)\BIN
BACNET_INCL = ..\..\include;.
INCL_DIRS = -I$(BORLAND_DIR)\include;$(BACNET_INCL)
CFLAGS = $(INCL_DIRS) $(CS_FLAGS) $(DEFINES)
# Libraries
#
C_LIB_DIR = $(BORLAND_DIR)\lib
LIBS = $(C_LIB_DIR)\IMPORT32.lib \
$(C_LIB_DIR)\CW32MT.lib
#
# Main target
#
# This should be the first one in the makefile
all : $(BCC_CFG) $(PRODUCT_EXE)
# Linker specific: the link below is for BCC linker/compiler. If you link
# with a different linker - please change accordingly.
#
# need a temp response file (@&&) because command line is too long
$(PRODUCT_EXE) : $(OBJS)
@echo Running Linker for $(PRODUCT_EXE)
$(LINK) -L$(C_LIB_DIR) -m -c -s -v @&&| # temp response file, starts with |
$(BORLAND_DIR)\lib\c0x32.obj $** # $** lists each dependency
$<
$*.map
$(LIBS)
| # end of temp response file
#
# Utilities
clean :
@echo Deleting obj files, $(PRODUCT_EXE) and map files.
del *.obj
del ..\..\*.obj
del ..\..\demo\handler\*.obj
del ..\..\demo\object\*.obj
del $(PRODUCT_EXE)
del *.map
del $(BCC_CFG)
#
# Generic rules
#
.SUFFIXES: .cpp .c .sbr .obj
#
# cc generic rule
#
.c.obj:
$(CC) -o$@ $<
# Compiler configuration file
$(BCC_CFG) :
Copy &&|
$(CFLAGS)
-c
-y #include line numbers in OBJ's
-v #include debug info
-w+ #turn on all warnings
-Od #disable all optimizations
#-a4 #32 bit data alignment
#-M # generate link map
#-ls # linker options
#-WM- #not multithread
-WM #multithread
-w-aus # ignore warning assigned a value that is never used
-w-sig # ignore warning conversion may lose sig digits
| $@
#
# Simple makefile to build an executable for Win32 console
#
# This makefile assumes Borland development environment
# on Windows NT/9x/2000/XP
# Tools: bcc32, make, ilink
!ifndef BORLAND_DIR
BORLAND_DIR_Not_Defined:
@echo .
@echo You must define environment variable BORLAND_DIR to compile.
!endif
PRODUCT = rs485
PRODUCT_EXE = $(PRODUCT).exe
# Choose the Data Link Layer to Enable
DEFINES = -DBACDL_MSTP=1;TEST_RS485;TEST_RS485_TRANSMIT
SRCS = rs485.c
OBJS = $(SRCS:.c=.obj)
# Compiler definitions
#
BCC_CFG = bcc32.cfg
CC = $(BORLAND_DIR)\bin\bcc32 +$(BCC_CFG)
#LINK = $(BORLAND_DIR)\bin\tlink32
LINK = $(BORLAND_DIR)\bin\ilink32
TLIB = $(BORLAND_DIR)\bin\tlib
#
# Include directories
#
CC_DIR = $(BORLAND_DIR)\BIN
BACNET_INCL = ..\..\include;.
INCL_DIRS = -I$(BORLAND_DIR)\include;$(BACNET_INCL)
CFLAGS = $(INCL_DIRS) $(CS_FLAGS) $(DEFINES)
# Libraries
#
C_LIB_DIR = $(BORLAND_DIR)\lib
LIBS = $(C_LIB_DIR)\IMPORT32.lib \
$(C_LIB_DIR)\CW32MT.lib
#
# Main target
#
# This should be the first one in the makefile
all : $(BCC_CFG) $(PRODUCT_EXE)
# Linker specific: the link below is for BCC linker/compiler. If you link
# with a different linker - please change accordingly.
#
# need a temp response file (@&&) because command line is too long
$(PRODUCT_EXE) : $(OBJS)
@echo Running Linker for $(PRODUCT_EXE)
$(LINK) -L$(C_LIB_DIR) -m -c -s -v @&&| # temp response file, starts with |
$(BORLAND_DIR)\lib\c0x32.obj $** # $** lists each dependency
$<
$*.map
$(LIBS)
| # end of temp response file
#
# Utilities
clean :
@echo Deleting obj files, $(PRODUCT_EXE) and map files.
del *.obj
del ..\..\*.obj
del ..\..\demo\handler\*.obj
del ..\..\demo\object\*.obj
del $(PRODUCT_EXE)
del *.map
del $(BCC_CFG)
#
# Generic rules
#
.SUFFIXES: .cpp .c .sbr .obj
#
# cc generic rule
#
.c.obj:
$(CC) -o$@ $<
# Compiler configuration file
$(BCC_CFG) :
Copy &&|
$(CFLAGS)
-c
-y #include line numbers in OBJ's
-v #include debug info
-w+ #turn on all warnings
-Od #disable all optimizations
#-a4 #32 bit data alignment
#-M # generate link map
#-ls # linker options
#-WM- #not multithread
-WM #multithread
-w-aus # ignore warning assigned a value that is never used
-w-sig # ignore warning conversion may lose sig digits
| $@
# EOF: makefile
+114 -114
View File
@@ -1,114 +1,114 @@
#
# Simple makefile to build an executable for Win32 console
#
# This makefile assumes Borland development environment
# on Windows NT/9x/2000/XP
# Tools: bcc32, make, ilink
!ifndef BORLAND_DIR
BORLAND_DIR_Not_Defined:
@echo .
@echo You must define environment variable BORLAND_DIR to compile.
!endif
PRODUCT = rx_fsm
PRODUCT_EXE = $(PRODUCT).exe
# Choose the Data Link Layer to Enable
DEFINES = -DBACDL_MSTP -DBACAPP_ALL -DPRINT_ENABLED=1
#DEFINED += -DPRINT_ENABLED_RECEIVE_DATA=1
SRCS = rs485.c \
rx_fsm.c \
..\..\src\mstp.c \
..\..\src\mstptext.c \
..\..\src\indtext.c \
..\..\src\crc.c
OBJS = $(SRCS:.c=.obj)
# Compiler definitions
#
BCC_CFG = bcc32.cfg
CC = $(BORLAND_DIR)\bin\bcc32 +$(BCC_CFG)
#LINK = $(BORLAND_DIR)\bin\tlink32
LINK = $(BORLAND_DIR)\bin\ilink32
TLIB = $(BORLAND_DIR)\bin\tlib
#
# Include directories
#
CC_DIR = $(BORLAND_DIR)\BIN
BACNET_INCL = ..\..\include;.
INCL_DIRS = -I$(BORLAND_DIR)\include;$(BACNET_INCL)
CFLAGS = $(INCL_DIRS) $(CS_FLAGS) $(DEFINES)
# Libraries
#
C_LIB_DIR = $(BORLAND_DIR)\lib
LIBS = $(C_LIB_DIR)\IMPORT32.lib \
$(C_LIB_DIR)\CW32MT.lib
#
# Main target
#
# This should be the first one in the makefile
all : $(BCC_CFG) $(PRODUCT_EXE)
# Linker specific: the link below is for BCC linker/compiler. If you link
# with a different linker - please change accordingly.
#
# need a temp response file (@&&) because command line is too long
$(PRODUCT_EXE) : $(OBJS)
@echo Running Linker for $(PRODUCT_EXE)
$(LINK) -L$(C_LIB_DIR) -m -c -s -v @&&| # temp response file, starts with |
$(BORLAND_DIR)\lib\c0x32.obj $** # $** lists each dependency
$<
$*.map
$(LIBS)
| # end of temp response file
#
# Utilities
clean :
@echo Deleting obj files, $(PRODUCT_EXE) and map files.
del $(OBJS)
del $(PRODUCT_EXE)
del *.map
del $(BCC_CFG)
#
# Generic rules
#
.SUFFIXES: .cpp .c .sbr .obj
#
# cc generic rule
#
.c.obj:
$(CC) -o$@ $<
# Compiler configuration file
$(BCC_CFG) :
Copy &&|
$(CFLAGS)
-c
-y #include line numbers in OBJ's
-v #include debug info
-w+ #turn on all warnings
-Od #disable all optimizations
#-a4 #32 bit data alignment
#-M # generate link map
#-ls # linker options
#-WM- #not multithread
-WM #multithread
-w-aus # ignore warning assigned a value that is never used
-w-sig # ignore warning conversion may lose sig digits
| $@
# EOF: makefile
#
# Simple makefile to build an executable for Win32 console
#
# This makefile assumes Borland development environment
# on Windows NT/9x/2000/XP
# Tools: bcc32, make, ilink
!ifndef BORLAND_DIR
BORLAND_DIR_Not_Defined:
@echo .
@echo You must define environment variable BORLAND_DIR to compile.
!endif
PRODUCT = rx_fsm
PRODUCT_EXE = $(PRODUCT).exe
# Choose the Data Link Layer to Enable
DEFINES = -DBACDL_MSTP -DBACAPP_ALL -DPRINT_ENABLED=1
#DEFINED += -DPRINT_ENABLED_RECEIVE_DATA=1
SRCS = rs485.c \
rx_fsm.c \
..\..\src\mstp.c \
..\..\src\mstptext.c \
..\..\src\indtext.c \
..\..\src\crc.c
OBJS = $(SRCS:.c=.obj)
# Compiler definitions
#
BCC_CFG = bcc32.cfg
CC = $(BORLAND_DIR)\bin\bcc32 +$(BCC_CFG)
#LINK = $(BORLAND_DIR)\bin\tlink32
LINK = $(BORLAND_DIR)\bin\ilink32
TLIB = $(BORLAND_DIR)\bin\tlib
#
# Include directories
#
CC_DIR = $(BORLAND_DIR)\BIN
BACNET_INCL = ..\..\include;.
INCL_DIRS = -I$(BORLAND_DIR)\include;$(BACNET_INCL)
CFLAGS = $(INCL_DIRS) $(CS_FLAGS) $(DEFINES)
# Libraries
#
C_LIB_DIR = $(BORLAND_DIR)\lib
LIBS = $(C_LIB_DIR)\IMPORT32.lib \
$(C_LIB_DIR)\CW32MT.lib
#
# Main target
#
# This should be the first one in the makefile
all : $(BCC_CFG) $(PRODUCT_EXE)
# Linker specific: the link below is for BCC linker/compiler. If you link
# with a different linker - please change accordingly.
#
# need a temp response file (@&&) because command line is too long
$(PRODUCT_EXE) : $(OBJS)
@echo Running Linker for $(PRODUCT_EXE)
$(LINK) -L$(C_LIB_DIR) -m -c -s -v @&&| # temp response file, starts with |
$(BORLAND_DIR)\lib\c0x32.obj $** # $** lists each dependency
$<
$*.map
$(LIBS)
| # end of temp response file
#
# Utilities
clean :
@echo Deleting obj files, $(PRODUCT_EXE) and map files.
del $(OBJS)
del $(PRODUCT_EXE)
del *.map
del $(BCC_CFG)
#
# Generic rules
#
.SUFFIXES: .cpp .c .sbr .obj
#
# cc generic rule
#
.c.obj:
$(CC) -o$@ $<
# Compiler configuration file
$(BCC_CFG) :
Copy &&|
$(CFLAGS)
-c
-y #include line numbers in OBJ's
-v #include debug info
-w+ #turn on all warnings
-Od #disable all optimizations
#-a4 #32 bit data alignment
#-M # generate link map
#-ls # linker options
#-WM- #not multithread
-WM #multithread
-w-aus # ignore warning assigned a value that is never used
-w-sig # ignore warning conversion may lose sig digits
| $@
# EOF: makefile
+2 -2
View File
@@ -1,2 +1,2 @@
set BORLAND_DIR=\bcc55
set BORLAND_DIR=\bcc55
+75 -75
View File
@@ -1,75 +1,75 @@
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <assert.h>
#include "bacdcode.h"
#include "get_alarm_sum.h"
#include "npdu.h"
int get_alarm_summary_ack_encode_apdu_init(
uint8_t * apdu,
uint8_t invoke_id)
{
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
apdu[0] = PDU_TYPE_COMPLEX_ACK; /* complex ACK service */
apdu[1] = invoke_id; /* original invoke id from request */
apdu[2] = SERVICE_CONFIRMED_GET_ALARM_SUMMARY;
apdu_len = 3;
}
return apdu_len;
}
int get_alarm_sumary_ack_encode_apdu_data(
uint8_t * apdu,
size_t max_apdu,
BACNET_GET_ALARM_SUMMARY_DATA * get_alarm_data)
{
int apdu_len = 0; /* total length of the apdu, return value */
if (!apdu) {
apdu_len = BACNET_STATUS_ERROR;
}
else if(max_apdu >= 10) {
/* tag 0 - Object Identifier */
apdu_len += encode_application_object_id(&apdu[apdu_len],
(int)get_alarm_data->objectIdentifier.type,
get_alarm_data->objectIdentifier.instance);
/* tag 1 - Alarm State */
apdu_len += encode_application_enumerated(&apdu[apdu_len],
get_alarm_data->alarmState);
/* tag 2 - Acknowledged Transitions */
apdu_len += encode_application_bitstring(&apdu[apdu_len],
&get_alarm_data->acknowledgedTransitions);
}
else {
apdu_len = BACNET_STATUS_ABORT;
}
return apdu_len;
}
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <assert.h>
#include "bacdcode.h"
#include "get_alarm_sum.h"
#include "npdu.h"
int get_alarm_summary_ack_encode_apdu_init(
uint8_t * apdu,
uint8_t invoke_id)
{
int apdu_len = 0; /* total length of the apdu, return value */
if (apdu) {
apdu[0] = PDU_TYPE_COMPLEX_ACK; /* complex ACK service */
apdu[1] = invoke_id; /* original invoke id from request */
apdu[2] = SERVICE_CONFIRMED_GET_ALARM_SUMMARY;
apdu_len = 3;
}
return apdu_len;
}
int get_alarm_sumary_ack_encode_apdu_data(
uint8_t * apdu,
size_t max_apdu,
BACNET_GET_ALARM_SUMMARY_DATA * get_alarm_data)
{
int apdu_len = 0; /* total length of the apdu, return value */
if (!apdu) {
apdu_len = BACNET_STATUS_ERROR;
}
else if(max_apdu >= 10) {
/* tag 0 - Object Identifier */
apdu_len += encode_application_object_id(&apdu[apdu_len],
(int)get_alarm_data->objectIdentifier.type,
get_alarm_data->objectIdentifier.instance);
/* tag 1 - Alarm State */
apdu_len += encode_application_enumerated(&apdu[apdu_len],
get_alarm_data->alarmState);
/* tag 2 - Acknowledged Transitions */
apdu_len += encode_application_bitstring(&apdu[apdu_len],
&get_alarm_data->acknowledgedTransitions);
}
else {
apdu_len = BACNET_STATUS_ABORT;
}
return apdu_len;
}
+34 -34
View File
@@ -1,34 +1,34 @@
#Makefile to build test case
CC = gcc
SRC_DIR = ../src
INCLUDES = -I../include -I.
DEFINES = -DBIG_ENDIAN=0 -DTEST -DTEST_OBJECT_LIST
CFLAGS = -Wall $(INCLUDES) $(DEFINES) -g
SRCS = $(SRC_DIR)/objects.c \
$(SRC_DIR)/keylist.c \
$(SRC_DIR)/key.c \
ctest.c
TARGET = rp
all: ${TARGET}
OBJS = ${SRCS:.c=.o}
${TARGET}: ${OBJS}
${CC} -o $@ ${OBJS}
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -rf core ${TARGET} $(OBJS) *.bak *.1 *.ini
include: .depend
#Makefile to build test case
CC = gcc
SRC_DIR = ../src
INCLUDES = -I../include -I.
DEFINES = -DBIG_ENDIAN=0 -DTEST -DTEST_OBJECT_LIST
CFLAGS = -Wall $(INCLUDES) $(DEFINES) -g
SRCS = $(SRC_DIR)/objects.c \
$(SRC_DIR)/keylist.c \
$(SRC_DIR)/key.c \
ctest.c
TARGET = rp
all: ${TARGET}
OBJS = ${SRCS:.c=.o}
${TARGET}: ${OBJS}
${CC} -o $@ ${OBJS}
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -rf core ${TARGET} $(OBJS) *.bak *.1 *.ini
include: .depend
+6 -6
View File
@@ -7,13 +7,13 @@ DEFINES = -DBIG_ENDIAN=0 -DTEST -DTEST_PRIVATE_TRANSFER
CFLAGS = -Wall $(INCLUDES) $(DEFINES) -g
SRCS = $(SRC_DIR)/bacdcode.c \
$(SRC_DIR)/bacapp.c \
$(SRC_DIR)/bactext.c \
$(SRC_DIR)/indtext.c \
$(SRC_DIR)/bacint.c \
$(SRC_DIR)/bacapp.c \
$(SRC_DIR)/bactext.c \
$(SRC_DIR)/indtext.c \
$(SRC_DIR)/bacint.c \
$(SRC_DIR)/bacstr.c \
$(SRC_DIR)/bacreal.c \
$(SRC_DIR)/datetime.c \
$(SRC_DIR)/bacreal.c \
$(SRC_DIR)/datetime.c \
$(SRC_DIR)/ptransfer.c \
ctest.c