Removed the object-table function macros from each demo object header file since it was very difficult to maintain when new functions are added. Added device-client.c file which is a small device object just for simple clients. Updated most Makefiles of client demo applications to utilize device-client.c file.

Added two device object table functions for COV support.
Corrected demo COV handler interaction with TSM, COV flags, and multiple subscriptions for the same object.
This commit is contained in:
skarg
2011-10-03 18:54:14 +00:00
parent 3bd72dc18d
commit dd93e8cf1b
77 changed files with 1543 additions and 589 deletions
+2 -1
View File
@@ -8,7 +8,8 @@ TARGET = bacdcc
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+1 -8
View File
@@ -51,13 +51,6 @@
#include "txbuf.h"
#include "dlenv.h"
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -123,7 +116,7 @@ void MyDeviceCommunicationControlSimpleAckHandler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
+3 -2
View File
@@ -12,7 +12,7 @@ BORLAND_DIR_Not_Defined:
!endif
# target
PRODUCT = bacdcc
PRODUCT = bacdcc ..\handler\device-client.c
PRODUCT_EXE = $(PRODUCT).exe
# tools
@@ -42,7 +42,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+3
View File
@@ -48,6 +48,9 @@
<Unit filename="main.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\object\device-client.c">
<Option compilerVar="CC" />
</Unit>
<Extensions>
<code_completion />
<envvars />
+34 -41
View File
@@ -23,7 +23,7 @@
*
*********************************************************************/
/** @file epics/bacepics.c Command line tool to build a full VTS3 EPICS file,
/** @file epics/bacepics.c Command line tool to build a full VTS3 EPICS file,
* including the heading information. */
#include <stddef.h>
@@ -69,13 +69,6 @@
* 3) Postpends the tail information to complete the EPICS file.
*/
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -299,7 +292,7 @@ void MyReadPropertyMultipleAckHandler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
Device_Init(NULL);
#if BAC_ROUTING
uint32_t Object_Instance;
@@ -335,12 +328,12 @@ static void Init_Service_Handlers(
}
/** Determine if this is a writable property, and, if so,
/** Determine if this is a writable property, and, if so,
* note that in the EPICS output.
* This function may need a lot of customization for different implementations;
* This function may need a lot of customization for different implementations;
* but as a starting point, take the Device object-instance and -name as writable.
* For the EPICS output to VTS3, printing 'w' after the property is sufficient,
* but to aid readability for human eyes, printing as "Writable".
* For the EPICS output to VTS3, printing 'w' after the property is sufficient,
* but to aid readability for human eyes, printing as "Writable".
*
* @param object_type [in] The BACnet Object type of this object.
* @note object_instance [in] The ID number for this object.
@@ -348,7 +341,7 @@ static void Init_Service_Handlers(
* Value, and Error information.
*/
void CheckIsWritableProperty(
BACNET_OBJECT_TYPE object_type,
BACNET_OBJECT_TYPE object_type,
/* uint32_t object_instance, */
BACNET_PROPERTY_REFERENCE * rpm_property)
{
@@ -639,11 +632,11 @@ void PrintReadPropertyData(
break;
default:
/* First, if this is a date type, it needs a different format
/* First, if this is a date type, it needs a different format
* for VTS, so pretty print it. */
if (ShowValues && (object_value.value->tag == BACNET_APPLICATION_TAG_DATE))
{
/* This would be PROP_LOCAL_DATE, or OBJECT_DATETIME_VALUE,
/* This would be PROP_LOCAL_DATE, or OBJECT_DATETIME_VALUE,
* or OBJECT_DATE_VALUE */
PrettyPrintPropertyValue(stdout, &object_value);
} else {
@@ -684,7 +677,7 @@ void PrintReadPropertyData(
/* Closing brace for this multi-valued array */
fprintf(stdout, " }");
}
CheckIsWritableProperty(object_type, /* object_instance, */
CheckIsWritableProperty(object_type, /* object_instance, */
rpm_property);
fprintf(stdout, "\r\n");
}
@@ -714,7 +707,7 @@ void Print_Property_Identifier(
/** Build a list of properties to request with RPM.
* @param rpm_object [out] The structure holding our linked list of properties to request.
* @param propList [in] Simple list of properties (ptr to array), terminated with -1
* @param propList [in] Simple list of properties (ptr to array), terminated with -1
*/
void BuildPropRequest( BACNET_READ_ACCESS_DATA *rpm_object, int32_t *propList )
{
@@ -870,8 +863,8 @@ EPICS_STATES ProcessRPMData(
free(old_value);
}
} else if ( myState == GET_HEADING_RESPONSE ) {
InitIdValues[i++] = rpm_property->value;
/* copy this pointer.
InitIdValues[i++] = rpm_property->value;
/* copy this pointer.
* On error, the pointer will be null
* We won't free these values*/
} else {
@@ -892,7 +885,7 @@ EPICS_STATES ProcessRPMData(
/* Now determine the next state */
if ( myState == GET_HEADING_RESPONSE )
nextState = PRINT_HEADING;
nextState = PRINT_HEADING;
/* press ahead with or without the data */
else if (bSuccess && (myState == GET_ALL_RESPONSE))
nextState = NEXT_OBJECT;
@@ -1038,7 +1031,7 @@ void PrintHeading( )
char *relation = "for"; /* Text for Gateways */
if ( Target_Address.net != 0 )
relation = "provided by"; /* Text for child routed devices */
printf("PICS 0\r\n");
printf("BACnet Protocol Implementation Conformance Statement\r\n\r\n");
@@ -1046,14 +1039,14 @@ void PrintHeading( )
printf("-- BACnet/IP Interface for BACnet-stack Devices\r\n");
printf("-- http://sourceforge.net/projects/bacnet/ \r\n");
printf("-- \r\n-- \r\n\r\n");
/* InitIdValues , , , */
/* InitIdValues , , , */
value = InitIdValues[INIT_VENDOR_NAME];
if ( value != NULL )
printf("Vendor Name: \"%s\"\r\n", characterstring_value( &value->type.Character_String) );
else
printf("Vendor Name: \"bacnet-stack\"\r\n");
value = InitIdValues[INIT_MODEL_NAME];
/* Best we can do with Product Name and Model Number is use the same text */
if ( value != NULL ) {
@@ -1079,11 +1072,11 @@ void PrintHeading( )
printf(" DM-DOB-B\r\n");
printf(" DM-DCC-B\r\n");
printf(" DM-RD-B\r\n");
#ifdef BAC_ROUTING
#ifdef BAC_ROUTING
/* Next line only for the gateway (ie, if not addressing a subNet) */
if ( Target_Address.net == 0 )
printf(" NM-RC-B\r\n");
#endif
#endif
printf("}\r\n\r\n");
/* You might add some of:
* -- DS-COV-A DS-COV-B
@@ -1104,7 +1097,7 @@ void PrintHeading( )
printf(" Who-Is Initiate Execute\r\n");
printf(" I-Am Initiate\r\n");
printf(" ReinitializeDevice Execute\r\n");
#ifdef BAC_ROUTING
#ifdef BAC_ROUTING
if ( Target_Address.net == 0 )
{
printf(" -- Note: The following Routing Services are Supported:\r\n");
@@ -1113,7 +1106,7 @@ void PrintHeading( )
printf(" -- Initialize-Routing-Table Execute\r\n");
printf(" -- Initialize-Routing-Table-Ack Initiate\r\n");
}
#endif
#endif
printf("}\r\n\r\n");
/* You might want to add some of:
* -- AcknowledgeAlarm Initiate Execute
@@ -1132,10 +1125,10 @@ void PrintHeading( )
printf("Standard Object-Types Supported:\r\n");
printf("{\r\n");
value = InitIdValues[INIT_OBJ_TYPES];
/* We have to process this bit string and determine which Object Types we have,
/* We have to process this bit string and determine which Object Types we have,
* and show them
*/
if ( ( value != NULL ) && (value->tag == BACNET_APPLICATION_TAG_BIT_STRING) )
if ( ( value != NULL ) && (value->tag == BACNET_APPLICATION_TAG_BIT_STRING) )
{
int i, len = bitstring_bits_used(&value->type.Bit_String);
for ( i = 0; i < len; i++) {
@@ -1148,8 +1141,8 @@ void PrintHeading( )
printf(" Binary Input\r\n");
printf(" Binary Value\r\n");
printf(" Device\r\n");
printf(" Multi-state Input\r\n");
printf(" Multi-state Value\r\n");
printf(" Multi-state Input\r\n");
printf(" Multi-state Value\r\n");
printf(" Structured View\r\n");
printf(" Characterstring Value\r\n");
printf(" Datetime Value\r\n");
@@ -1163,7 +1156,7 @@ void PrintHeading( )
* -- Multi-state Output
* -- Trend Log Createable Deleteable
* -- Load Control
* -- Bitstring Value
* -- Bitstring Value
* -- Date Pattern Value
* -- Date Value
* -- Datetime Pattern Value
@@ -1172,7 +1165,7 @@ void PrintHeading( )
* -- Time Pattern Value
* -- Time Value
*/
printf("Data Link Layer Option:\r\n");
printf("{\r\n");
printf(" BACnet/IP, 'DIX' Ethernet\r\n");
@@ -1187,8 +1180,8 @@ void PrintHeading( )
printf("{\r\n");
printf(" Maximum APDU size in octets: 1476\r\n");
printf("}\r\n\r\n");
printf("List of Objects in Test Device:\r\n");
printf("List of Objects in Test Device:\r\n");
/* Print Opening brace, then kick off the Device Object */
printf("{\r\n");
printf(" {\r\n"); /* And opening brace for the first object */
@@ -1342,7 +1335,7 @@ int main(
myState = GET_HEADING_INFO;
}
break;
case GET_HEADING_INFO:
last_seconds = current_seconds;
StartNextObject(rpm_object, &myObject);
@@ -1414,7 +1407,7 @@ int main(
elapsed_seconds = 0;
invoke_id = 0;
if ( myState == GET_HEADING_RESPONSE )
myState = PRINT_HEADING;
myState = PRINT_HEADING;
/* just press ahead without the data */
else if (Error_Detected) {
/* The normal case for Device Object */
@@ -1442,7 +1435,7 @@ int main(
invoke_id = 0;
elapsed_seconds = 0;
if ( myState == GET_HEADING_RESPONSE )
myState = PRINT_HEADING;
myState = PRINT_HEADING;
/* just press ahead without the data */
else
myState = GET_ALL_REQUEST; /* Let's try again */
@@ -1451,7 +1444,7 @@ int main(
elapsed_seconds = 0;
invoke_id = 0;
if ( myState == GET_HEADING_RESPONSE )
myState = PRINT_HEADING;
myState = PRINT_HEADING;
/* just press ahead without the data */
else
myState = NEXT_OBJECT; /* Give up and move on to the next. */
+3 -17
View File
@@ -59,20 +59,6 @@
#ifdef BACNET_TEST_VMAC
#include "vmac.h"
#endif
#include "ai.h"
#include "ao.h"
#include "av.h"
#include "bi.h"
#include "bo.h"
#include "bv.h"
#include "lc.h"
#include "lsp.h"
#include "mso.h"
#include "ms-input.h"
#include "trendlog.h"
#if defined(BACFILE)
#include "bacfile.h"
#endif
/** @file gateway/main.c Example virtual gateway application using the BACnet Stack. */
@@ -139,10 +125,10 @@ static void Init_Service_Handlers(
Routing_Device_Init(first_object_instance);
/* we need to handle who-is to support dynamic device binding
* For the gateway, we will use the unicast variety so we can
* get back through switches to different subnets.
* For the gateway, we will use the unicast variety so we can
* get back through switches to different subnets.
* Don't need the routed versions, since the npdu handler calls
* each device in turn.
* each device in turn.
*/
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is_unicast);
+97 -37
View File
@@ -53,6 +53,7 @@ typedef struct BACnet_COV_Subscription {
uint32_t subscriberProcessIdentifier;
BACNET_OBJECT_ID monitoredObjectIdentifier;
bool issueConfirmedNotifications; /* optional */
uint8_t invokeID; /* for confirmed COV */
uint32_t lifetime; /* optional */
bool send_requested;
} BACNET_COV_SUBSCRIPTION;
@@ -223,6 +224,7 @@ void handler_cov_init(
OBJECT_ANALOG_INPUT;
COV_Subscriptions[index].monitoredObjectIdentifier.instance = 0;
COV_Subscriptions[index].issueConfirmedNotifications = false;
COV_Subscriptions[index].invokeID = 0;
COV_Subscriptions[index].lifetime = 0;
COV_Subscriptions[index].send_requested = false;
}
@@ -261,6 +263,10 @@ static bool cov_list_subscribe(
COV_Subscriptions[index].lifetime = cov_data->lifetime;
COV_Subscriptions[index].send_requested = true;
}
if (COV_Subscriptions[index].invokeID) {
tsm_free_invoke_id(COV_Subscriptions[index].invokeID);
COV_Subscriptions[index].invokeID = 0;
}
break;
}
} else {
@@ -283,6 +289,7 @@ static bool cov_list_subscribe(
cov_data->subscriberProcessIdentifier;
COV_Subscriptions[index].issueConfirmedNotifications =
cov_data->issueConfirmedNotifications;
COV_Subscriptions[index].invokeID = 0;
COV_Subscriptions[index].lifetime = cov_data->lifetime;
COV_Subscriptions[index].send_requested = true;
} else if (!existing_entry) {
@@ -335,6 +342,7 @@ static bool cov_send_request(
if (cov_subscription->issueConfirmedNotifications) {
invoke_id = tsm_next_free_invokeID();
if (invoke_id) {
cov_subscription->invokeID = invoke_id;
len =
ccov_notify_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
invoke_id, &cov_data);
@@ -385,19 +393,13 @@ static bool cov_send_request(
*
* @param elapsed_seconds [in] How many seconds have elapsed since last called.
*/
void handler_cov_task(
void handler_cov_timer_seconds(
uint32_t elapsed_seconds)
{
int index = 0, index2 = 0;
int index = 0;
uint32_t lifetime_seconds = 0;
uint16_t object_type = 0, object_type2 = 0;
uint32_t object_instance = 0, object_instance2 = 0;
bool status = false;
BACNET_PROPERTY_VALUE value_list[2];
value_list[0].next = &value_list[1];
value_list[1].next = NULL;
/* existing? - match Object ID and Process ID */
/* handle the subscription timeouts */
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) {
if (COV_Subscriptions[index].valid) {
/* handle timeouts */
@@ -413,44 +415,102 @@ void handler_cov_task(
}
if (COV_Subscriptions[index].lifetime == 0) {
COV_Subscriptions[index].valid = false;
if (COV_Subscriptions[index].issueConfirmedNotifications) {
if (COV_Subscriptions[index].invokeID) {
tsm_free_invoke_id(COV_Subscriptions[index].invokeID);
COV_Subscriptions[index].invokeID = 0;
}
}
}
/* handle COV notifications */
object_type =
}
}
}
void handler_cov_task(void)
{
int index = 0;
BACNET_OBJECT_TYPE object_type = MAX_BACNET_OBJECT_TYPE;
uint32_t object_instance = 0;
bool status = false;
BACNET_PROPERTY_VALUE value_list[2];
/* configure the linked list for the two properties */
value_list[0].next = &value_list[1];
value_list[1].next = NULL;
/* mark any subscriptions where the value has changed */
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) {
if (COV_Subscriptions[index].valid) {
object_type = (BACNET_OBJECT_TYPE)
COV_Subscriptions[index].monitoredObjectIdentifier.type;
object_instance =
COV_Subscriptions[index].monitoredObjectIdentifier.instance;
status =
Device_Encode_Value_List(object_type, object_instance,
&value_list[0]);
status = Device_COV(object_type, object_instance);
if (status) {
COV_Subscriptions[index].send_requested = true;
}
if (COV_Subscriptions[index].send_requested) {
cov_send_request(&COV_Subscriptions[index], &value_list[0]);
COV_Subscriptions[index].send_requested = false;
}
}
/* clear the COV flag after checking all subscriptions (dup objects) */
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) {
if (COV_Subscriptions[index].valid) {
object_type = (BACNET_OBJECT_TYPE)
COV_Subscriptions[index].monitoredObjectIdentifier.type;
object_instance =
COV_Subscriptions[index].monitoredObjectIdentifier.instance;
status = Device_COV(object_type, object_instance);
if (status) {
Device_COV_Clear(object_type, object_instance);
}
if (status && ((index + 1) < MAX_COV_SUBCRIPTIONS)) {
/* if more than one subscription for this object instance */
for (index2 = index + 1; index2 < MAX_COV_SUBCRIPTIONS;
index2++) {
object_type2 =
COV_Subscriptions[index2].monitoredObjectIdentifier.
type;
object_instance2 =
COV_Subscriptions[index2].monitoredObjectIdentifier.
instance;
if ((COV_Subscriptions[index].lifetime) &&
(COV_Subscriptions[index].valid) &&
(object_type == object_type2) &&
(object_instance == object_instance2)) {
cov_send_request(&COV_Subscriptions[index2],
&value_list[0]);
COV_Subscriptions[index2].send_requested = false;
}
}
/* confirmed notification house keeping */
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) {
if (COV_Subscriptions[index].valid) {
if (COV_Subscriptions[index].issueConfirmedNotifications) {
if (COV_Subscriptions[index].invokeID) {
if (tsm_invoke_id_free(COV_Subscriptions[index].invokeID)) {
COV_Subscriptions[index].invokeID = 0;
} else if (tsm_invoke_id_failed(
COV_Subscriptions[index].invokeID)) {
tsm_free_invoke_id(COV_Subscriptions[index].invokeID);
COV_Subscriptions[index].invokeID = 0;
}
}
}
}
}
/* send any COVs that are requested */
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) {
if (COV_Subscriptions[index].valid) {
if (COV_Subscriptions[index].send_requested) {
if (COV_Subscriptions[index].issueConfirmedNotifications) {
if (COV_Subscriptions[index].invokeID != 0) {
/* already sending - be patient! */
continue;
}
if (!tsm_transaction_available()) {
/* no free transactions - be patient! */
continue;
}
}
object_type = (BACNET_OBJECT_TYPE)
COV_Subscriptions[index].monitoredObjectIdentifier.type;
object_instance =
COV_Subscriptions[index].monitoredObjectIdentifier.instance;
(void)Device_Encode_Value_List(object_type, object_instance,
&value_list[0]);
status = cov_send_request(
&COV_Subscriptions[index],
&value_list[0]);
if (status) {
COV_Subscriptions[index].send_requested = false;
} else {
/* must be out of PDU space - stop for now */
break;
}
}
}
}
}
static bool cov_subscribe(
@@ -460,10 +520,10 @@ static bool cov_subscribe(
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
uint16_t object_type = 0;
BACNET_OBJECT_TYPE object_type = MAX_BACNET_OBJECT_TYPE;
uint32_t object_instance = 0;
object_type = cov_data->monitoredObjectIdentifier.type;
object_type = (BACNET_OBJECT_TYPE)cov_data->monitoredObjectIdentifier.type;
object_instance = cov_data->monitoredObjectIdentifier.instance;
status = Device_Valid_Object_Id(object_type, object_instance);
if (status) {
@@ -518,7 +578,7 @@ void handler_cov_subscribe(
bool error = false;
/* initialize a common abort code */
cov_data.error_code = ABORT_REASON_SEGMENTATION_NOT_SUPPORTED;
cov_data.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
+53 -7
View File
@@ -45,20 +45,66 @@ void handler_unconfirmed_private_transfer(
BACNET_ADDRESS * src)
{
BACNET_PRIVATE_TRANSFER_DATA private_data;
BACNET_OBJECT_PROPERTY_VALUE object_value; /* for bacapp printing */
BACNET_APPLICATION_DATA_VALUE value; /* for decode value data */
int len = 0;
uint8_t *application_data;
int application_data_len;
bool first_value = true;
bool print_brace = false;
#if PRINT_ENABLED
fprintf(stderr, "Received Unconfirmed Private Transfer Request!\n");
#endif
(void) src;
len =
ptransfer_decode_service_request(service_request, service_len,
&private_data);
len = ptransfer_decode_service_request(
service_request, service_len, &private_data);
if (len >= 0) {
#if PRINT_ENABLED
fprintf(stderr,
"UnconfirmedPrivateTransfer: " "vendorID=%u serviceNumber=%u\n",
private_data.vendorID, private_data.serviceNumber);
printf("PrivateTransfer:vendorID=%u\r\n",
(unsigned)private_data.vendorID);
printf("PrivateTransfer:serviceNumber=%lu\r\n",
(unsigned long)private_data.serviceNumber);
#endif
application_data = private_data.serviceParameters;
application_data_len = private_data.serviceParametersLen;
for (;;) {
len =
bacapp_decode_application_data(application_data,
(uint8_t) application_data_len, &value);
if (first_value && (len < application_data_len)) {
first_value = false;
#if PRINT_ENABLED
fprintf(stdout, "{");
#endif
print_brace = true;
}
/* private transfer doesn't provide any clues */
object_value.object_type = MAX_BACNET_OBJECT_TYPE;
object_value.object_instance = BACNET_MAX_INSTANCE;
object_value.object_property = MAX_BACNET_PROPERTY_ID;
object_value.array_index = BACNET_ARRAY_ALL;
object_value.value = &value;
bacapp_print_value(stdout, &object_value);
if (len > 0) {
if (len < application_data_len) {
application_data += len;
application_data_len -= len;
/* there's more! */
#if PRINT_ENABLED
fprintf(stdout, ",");
#endif
} else {
break;
}
} else {
break;
}
}
#if PRINT_ENABLED
if (print_brace)
fprintf(stdout, "}");
fprintf(stdout, "\r\n");
#endif
}
}
+2 -1
View File
@@ -8,7 +8,8 @@ TARGET = baciamr
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+1 -10
View File
@@ -46,15 +46,6 @@
#include "txbuf.h"
#include "dlenv.h"
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
};
/* buffer used for receive */
/* static uint8_t Rx_Buf[MAX_MPDU] = { 0 }; */
/* global variables used in this file */
#define MAX_ROUTER_DNETS 64
static int Target_Router_Networks[MAX_ROUTER_DNETS] = { -1 };
@@ -90,7 +81,7 @@ void MyRejectHandler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
+2 -1
View File
@@ -42,7 +42,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+2 -1
View File
@@ -8,7 +8,8 @@ TARGET = bacinitr
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+1 -7
View File
@@ -48,12 +48,6 @@
#include "txbuf.h"
#include "dlenv.h"
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -220,7 +214,7 @@ static void My_NPDU_Handler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
+2 -1
View File
@@ -42,7 +42,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+1 -5
View File
@@ -143,9 +143,5 @@ extern "C" {
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define ANALOG_INPUT_OBJ_FUNCTIONS \
OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count, \
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance, \
Analog_Input_Object_Name, Analog_Input_Read_Property, NULL, \
Analog_Input_Property_Lists, NULL, NULL, NULL
#endif
+1 -6
View File
@@ -100,10 +100,5 @@ extern "C" {
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define ANALOG_OUTPUT_OBJ_FUNCTIONS \
OBJECT_ANALOG_OUTPUT, Analog_Output_Init, Analog_Output_Count, \
Analog_Output_Index_To_Instance, Analog_Output_Valid_Instance, \
Analog_Output_Object_Name, Analog_Output_Read_Property, \
Analog_Output_Write_Property, Analog_Output_Property_Lists, \
NULL, NULL, NULL
#endif
+1 -6
View File
@@ -132,10 +132,5 @@ extern "C" {
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define ANALOG_VALUE_OBJ_FUNCTIONS \
OBJECT_ANALOG_VALUE, Analog_Value_Init, Analog_Value_Count, \
Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance, \
Analog_Value_Object_Name, Analog_Value_Read_Property, \
Analog_Value_Write_Property, Analog_Value_Property_Lists, NULL, \
NULL, NULL
#endif
+1 -4
View File
@@ -98,8 +98,5 @@ extern "C" {
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define FILE_OBJ_FUNCTIONS \
OBJECT_FILE, bacfile_init, bacfile_count, bacfile_index_to_instance, \
bacfile_valid_instance, bacfile_object_name, bacfile_read_property, \
bacfile_write_property, BACfile_Property_Lists, NULL, NULL
#endif
+2 -3
View File
@@ -183,7 +183,7 @@ bool Binary_Input_Out_Of_Service(
return value;
}
static bool Binary_Input_Change_Of_Value(
bool Binary_Input_Change_Of_Value(
uint32_t object_instance)
{
bool status = false;
@@ -197,7 +197,7 @@ static bool Binary_Input_Change_Of_Value(
return status;
}
static void Binary_Input_Change_Of_Value_Clear(
void Binary_Input_Change_Of_Value_Clear(
uint32_t object_instance)
{
unsigned index;
@@ -249,7 +249,6 @@ bool Binary_Input_Encode_Value_List(
value_list->priority = BACNET_NO_PRIORITY;
}
status = Binary_Input_Change_Of_Value(object_instance);
Binary_Input_Change_Of_Value_Clear(object_instance);
return status;
}
+5 -5
View File
@@ -86,6 +86,10 @@ extern "C" {
bool Binary_Input_Encode_Value_List(
uint32_t object_instance,
BACNET_PROPERTY_VALUE * value_list);
bool Binary_Input_Change_Of_Value(
uint32_t instance);
void Binary_Input_Change_Of_Value_Clear(
uint32_t instance);
int Binary_Input_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata);
@@ -110,9 +114,5 @@ extern "C" {
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define BINARY_INPUT_OBJ_FUNCTIONS \
OBJECT_BINARY_INPUT, Binary_Input_Init, Binary_Input_Count, \
Binary_Input_Index_To_Instance, Binary_Input_Valid_Instance, \
Binary_Input_Object_Name, Binary_Input_Read_Property, NULL, \
Binary_Input_Property_Lists, NULL, NULL, Binary_Input_Encode_Value_List
#endif
+1 -6
View File
@@ -109,10 +109,5 @@ extern "C" {
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define BINARY_OUTPUT_OBJ_FUNCTIONS \
OBJECT_BINARY_OUTPUT, Binary_Output_Init, Binary_Output_Count, \
Binary_Output_Index_To_Instance, Binary_Output_Valid_Instance, \
Binary_Output_Object_Name, Binary_Output_Read_Property, \
Binary_Output_Write_Property, Binary_Output_Property_Lists, \
NULL, NULL, NULL
#endif
+1 -6
View File
@@ -71,10 +71,5 @@ extern "C" {
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define BINARY_VALUE_OBJ_FUNCTIONS \
OBJECT_BINARY_VALUE, Binary_Value_Init, Binary_Value_Count, \
Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance, \
Binary_Value_Object_Name, Binary_Value_Read_Property, \
Binary_Value_Write_Property, Binary_Value_Property_Lists, NULL, \
NULL, NULL
#endif
+908
View File
@@ -0,0 +1,908 @@
/**************************************************************************
*
* 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.
*
*********************************************************************/
/** @file device-client.c Lightweight base "class" for handling all
* BACnet objects belonging to a BACnet device, as well as
* Device-specific properties. This Device instance is designed to
* meet minimal functionality for simple clients. */
#include <stdbool.h>
#include <stdint.h>
#include <string.h> /* for memmove */
#include <time.h> /* for timezone, localtime */
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "apdu.h"
#include "rp.h" /* ReadProperty handling */
#include "version.h"
#include "handlers.h"
#include "datalink.h"
#include "address.h"
/* include the device object */
#include "device.h" /* me */
/* note: you really only need to define variables for
properties that are writable or that may change.
The properties that are constant can be hard coded
into the read-property encoding. */
static uint32_t Object_Instance_Number = 260001;
static BACNET_CHARACTER_STRING My_Object_Name;
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
static char *Vendor_Name = BACNET_VENDOR_NAME;
static uint16_t Vendor_Identifier = BACNET_VENDOR_ID;
static char *Model_Name = "GNU";
static char *Application_Software_Version = "1.0";
static char *Location = "USA";
static char *Description = "command line client";
/* static uint8_t Protocol_Version = 1; - constant, not settable */
/* static uint8_t Protocol_Revision = 4; - constant, not settable */
/* Protocol_Services_Supported - dynamically generated */
/* Protocol_Object_Types_Supported - in RP encoding */
/* Object_List - dynamically generated */
/* static BACNET_SEGMENTATION Segmentation_Supported = SEGMENTATION_NONE; */
/* static uint8_t Max_Segments_Accepted = 0; */
/* VT_Classes_Supported */
/* Active_VT_Sessions */
/* static BACNET_TIME Local_Time; rely on OS, if there is one */
/* static BACNET_DATE Local_Date; rely on OS, if there is one */
/* NOTE: BACnet UTC Offset is inverse of common practice.
If your UTC offset is -5hours of GMT,
then BACnet UTC offset is +5hours.
BACnet UTC offset is expressed in minutes. */
/* static int32_t UTC_Offset = 5 * 60; */
/* static bool Daylight_Savings_Status = false; rely on OS */
/* List_Of_Session_Keys */
/* Time_Synchronization_Recipients */
/* Max_Master - rely on MS/TP subsystem, if there is one */
/* Max_Info_Frames - rely on MS/TP subsystem, if there is one */
/* Device_Address_Binding - required, but relies on binding cache */
static uint32_t Database_Revision = 0;
/* Configuration_Files */
/* Last_Restore_Time */
/* Backup_Failure_Timeout */
/* Active_COV_Subscriptions */
/* Slave_Proxy_Enable */
/* Manual_Slave_Address_Binding */
/* Auto_Slave_Discovery */
/* Slave_Address_Binding */
/* Profile_Name */
/* local forward (semi-private) and external prototypes */
int Device_Read_Property_Local(
BACNET_READ_PROPERTY_DATA * rpdata);
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{OBJECT_DEVICE,
NULL /* Init - don't init Device or it will recourse! */,
Device_Count,
Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name,
Device_Read_Property_Local,
NULL /* Write_Property */,
NULL /* Property_Lists */,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
NULL /* Intrinsic Reporting */},
{MAX_BACNET_OBJECT_TYPE,
NULL /* Init */,
NULL /* Count */,
NULL /* Index_To_Instance */,
NULL /* Valid_Instance */,
NULL /* Object_Name */,
NULL /* Read_Property */,
NULL /* Write_Property */,
NULL /* Property_Lists */,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
NULL /* Intrinsic Reporting */}
};
/** Glue function to let the Device object, when called by a handler,
* lookup which Object type needs to be invoked.
* @ingroup ObjHelpers
* @param Object_Type [in] The type of BACnet Object the handler wants to access.
* @return Pointer to the group of object helper functions that implement this
* type of Object.
*/
static struct object_functions *Device_Objects_Find_Functions(
BACNET_OBJECT_TYPE Object_Type)
{
struct object_functions *pObject = NULL;
pObject = &Object_Table[0];
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
/* handle each object type */
if (pObject->Object_Type == Object_Type) {
return (pObject);
}
pObject++;
}
return (NULL);
}
unsigned Device_Count(
void)
{
return 1;
}
uint32_t Device_Index_To_Instance(
unsigned index)
{
index = index;
return Object_Instance_Number;
}
/* methods to manipulate the data */
/** Return the Object Instance number for our (single) Device Object.
* This is a key function, widely invoked by the handler code, since
* it provides "our" (ie, local) address.
* @ingroup ObjIntf
* @return The Instance number used in the BACNET_OBJECT_ID for the Device.
*/
uint32_t Device_Object_Instance_Number(
void)
{
#ifdef BAC_ROUTING
return Routed_Device_Object_Instance_Number();
#else
return Object_Instance_Number;
#endif
}
bool Device_Set_Object_Instance_Number(
uint32_t object_id)
{
bool status = true; /* return value */
if (object_id <= BACNET_MAX_INSTANCE) {
/* Make the change and update the database revision */
Object_Instance_Number = object_id;
Device_Inc_Database_Revision();
} else
status = false;
return status;
}
bool Device_Valid_Object_Instance_Number(
uint32_t object_id)
{
/* BACnet allows for a wildcard instance number */
return ((Object_Instance_Number == object_id) ||
(object_id == BACNET_MAX_INSTANCE));
}
bool Device_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
{
bool status = false;
if (object_instance == Object_Instance_Number) {
status = characterstring_copy(object_name, &My_Object_Name);
}
return status;
}
bool Device_Set_Object_Name(
BACNET_CHARACTER_STRING * object_name)
{
bool status = false; /*return value */
if (!characterstring_same(&My_Object_Name, object_name)) {
/* Make the change and update the database revision */
status = characterstring_copy(&My_Object_Name, object_name);
Device_Inc_Database_Revision();
}
return status;
}
BACNET_DEVICE_STATUS Device_System_Status(
void)
{
return System_Status;
}
int Device_Set_System_Status(
BACNET_DEVICE_STATUS status,
bool local)
{
int result = 0; /*return value - 0 = ok, -1 = bad value, -2 = not allowed */
/* We limit the options available depending on whether the source is
* internal or external. */
if (local) {
switch (status) {
case STATUS_OPERATIONAL:
case STATUS_OPERATIONAL_READ_ONLY:
case STATUS_DOWNLOAD_REQUIRED:
case STATUS_DOWNLOAD_IN_PROGRESS:
case STATUS_NON_OPERATIONAL:
System_Status = status;
break;
/* Don't support backup at present so don't allow setting */
case STATUS_BACKUP_IN_PROGRESS:
result = -2;
break;
default:
result = -1;
break;
}
} else {
switch (status) {
/* Allow these for the moment as a way to easily alter
* overall device operation. The lack of password protection
* or other authentication makes allowing writes to this
* property a risky facility to provide.
*/
case STATUS_OPERATIONAL:
case STATUS_OPERATIONAL_READ_ONLY:
case STATUS_NON_OPERATIONAL:
System_Status = status;
break;
/* Don't allow outsider set this - it should probably
* be set if the device config is incomplete or
* corrupted or perhaps after some sort of operator
* wipe operation.
*/
case STATUS_DOWNLOAD_REQUIRED:
/* Don't allow outsider set this - it should be set
* internally at the start of a multi packet download
* perhaps indirectly via PT or WF to a config file.
*/
case STATUS_DOWNLOAD_IN_PROGRESS:
/* Don't support backup at present so don't allow setting */
case STATUS_BACKUP_IN_PROGRESS:
result = -2;
break;
default:
result = -1;
break;
}
}
return (result);
}
const char *Device_Vendor_Name(
void)
{
return Vendor_Name;
}
/** Returns the Vendor ID for this Device.
* See the assignments at http://www.bacnet.org/VendorID/BACnet%20Vendor%20IDs.htm
* @return The Vendor ID of this Device.
*/
uint16_t Device_Vendor_Identifier(
void)
{
return Vendor_Identifier;
}
void Device_Set_Vendor_Identifier(
uint16_t vendor_id)
{
Vendor_Identifier = vendor_id;
}
const char *Device_Model_Name(
void)
{
return Model_Name;
}
bool Device_Set_Model_Name(
const char *name,
size_t length)
{
bool status = false; /*return value */
if (length < sizeof(Model_Name)) {
memmove(Model_Name, name, length);
Model_Name[length] = 0;
status = true;
}
return status;
}
const char *Device_Firmware_Revision(
void)
{
return BACnet_Version;
}
const char *Device_Application_Software_Version(
void)
{
return Application_Software_Version;
}
bool Device_Set_Application_Software_Version(
const char *name,
size_t length)
{
bool status = false; /*return value */
if (length < sizeof(Application_Software_Version)) {
memmove(Application_Software_Version, name, length);
Application_Software_Version[length] = 0;
status = true;
}
return status;
}
const char *Device_Description(
void)
{
return Description;
}
bool Device_Set_Description(
const char *name,
size_t length)
{
bool status = false; /*return value */
if (length < sizeof(Description)) {
memmove(Description, name, length);
Description[length] = 0;
status = true;
}
return status;
}
const char *Device_Location(
void)
{
return Location;
}
bool Device_Set_Location(
const char *name,
size_t length)
{
bool status = false; /*return value */
if (length < sizeof(Location)) {
memmove(Location, name, length);
Location[length] = 0;
status = true;
}
return status;
}
uint8_t Device_Protocol_Version(
void)
{
return BACNET_PROTOCOL_VERSION;
}
uint8_t Device_Protocol_Revision(
void)
{
return BACNET_PROTOCOL_REVISION;
}
BACNET_SEGMENTATION Device_Segmentation_Supported(
void)
{
return SEGMENTATION_NONE;
}
uint32_t Device_Database_Revision(
void)
{
return Database_Revision;
}
void Device_Set_Database_Revision(
uint32_t revision)
{
Database_Revision = revision;
}
/*
* Shortcut for incrementing database revision as this is potentially
* the most common operation if changing object names and ids is
* implemented.
*/
void Device_Inc_Database_Revision(
void)
{
Database_Revision++;
}
/** Get the total count of objects supported by this Device Object.
* @note Since many network clients depend on the object list
* for discovery, it must be consistent!
* @return The count of objects, for all supported Object types.
*/
unsigned Device_Object_List_Count(
void)
{
unsigned count = 0; /* number of objects */
struct object_functions *pObject = NULL;
/* initialize the default return values */
pObject = &Object_Table[0];
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
if (pObject->Object_Count) {
count += pObject->Object_Count();
}
pObject++;
}
return count;
}
/** Lookup the Object at the given array index in the Device's Object List.
* Even though we don't keep a single linear array of objects in the Device,
* this method acts as though we do and works through a virtual, concatenated
* array of all of our object type arrays.
*
* @param array_index [in] The desired array index (1 to N)
* @param object_type [out] The object's type, if found.
* @param instance [out] The object's instance number, if found.
* @return True if found, else false.
*/
bool Device_Object_List_Identifier(
unsigned array_index,
int *object_type,
uint32_t * instance)
{
bool status = false;
unsigned count = 0;
unsigned object_index = 0;
unsigned temp_index = 0;
struct object_functions *pObject = NULL;
/* array index zero is length - so invalid */
if (array_index == 0) {
return status;
}
object_index = array_index - 1;
/* initialize the default return values */
pObject = &Object_Table[0];
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
if (pObject->Object_Count) {
object_index -= count;
count = pObject->Object_Count();
if (object_index < count) {
/* Use the iterator function if available otherwise
* look for the index to instance to get the ID */
if (pObject->Object_Iterator) {
/* First find the first object */
temp_index = pObject->Object_Iterator(~(unsigned) 0);
/* Then step through the objects to find the nth */
while (object_index != 0) {
temp_index = pObject->Object_Iterator(temp_index);
object_index--;
}
/* set the object_index up before falling through to next bit */
object_index = temp_index;
}
if (pObject->Object_Index_To_Instance) {
*object_type = pObject->Object_Type;
*instance =
pObject->Object_Index_To_Instance(object_index);
status = true;
break;
}
}
}
pObject++;
}
return status;
}
/** Determine if we have an object with the given object_name.
* If the object_type and object_instance pointers are not null,
* and the lookup succeeds, they will be given the resulting values.
* @param object_name [in] The desired Object Name to look for.
* @param object_type [out] The BACNET_OBJECT_TYPE of the matching Object.
* @param object_instance [out] The object instance number of the matching Object.
* @return True on success or else False if not found.
*/
bool Device_Valid_Object_Name(
BACNET_CHARACTER_STRING * object_name1,
int *object_type,
uint32_t * object_instance)
{
bool found = false;
int type = 0;
uint32_t instance;
unsigned max_objects = 0, i = 0;
bool check_id = false;
BACNET_CHARACTER_STRING object_name2;
struct object_functions *pObject = NULL;
max_objects = Device_Object_List_Count();
for (i = 0; i < max_objects; i++) {
check_id = Device_Object_List_Identifier(i, &type, &instance);
if (check_id) {
pObject = Device_Objects_Find_Functions(type);
if ((pObject != NULL) && (pObject->Object_Name != NULL) &&
(pObject->Object_Name(instance, &object_name2) &&
characterstring_same(object_name1, &object_name2))) {
found = true;
if (object_type) {
*object_type = type;
}
if (object_instance) {
*object_instance = instance;
}
break;
}
}
}
return found;
}
/** Determine if we have an object of this type and instance number.
* @param object_type [in] The desired BACNET_OBJECT_TYPE
* @param object_instance [in] The object instance number to be looked up.
* @return True if found, else False if no such Object in this device.
*/
bool Device_Valid_Object_Id(
int object_type,
uint32_t object_instance)
{
bool status = false; /* return value */
struct object_functions *pObject = NULL;
pObject = Device_Objects_Find_Functions(object_type);
if ((pObject != NULL) && (pObject->Object_Valid_Instance != NULL)) {
status = pObject->Object_Valid_Instance(object_instance);
}
return status;
}
/** Copy a child object's object_name value, given its ID.
* @param object_type [in] The BACNET_OBJECT_TYPE of the child Object.
* @param object_instance [in] The object instance number of the child Object.
* @param object_name [out] The Object Name found for this child Object.
* @return True on success or else False if not found.
*/
bool Device_Object_Name_Copy(
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
{
struct object_functions *pObject = NULL;
bool found = false;
pObject = Device_Objects_Find_Functions(object_type);
if ((pObject != NULL) && (pObject->Object_Name != NULL)) {
found = pObject->Object_Name(object_instance, object_name);
}
return found;
}
/* return the length of the apdu encoded or BACNET_STATUS_ERROR for error or
BACNET_STATUS_ABORT for abort message */
int Device_Read_Property_Local(
BACNET_READ_PROPERTY_DATA * rpdata)
{
int apdu_len = 0; /* return value */
int len = 0; /* apdu len intermediate value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
unsigned i = 0;
int object_type = 0;
uint32_t instance = 0;
unsigned count = 0;
uint8_t *apdu = NULL;
struct object_functions *pObject = NULL;
bool found = false;
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_DEVICE,
Object_Instance_Number);
break;
case PROP_OBJECT_NAME:
apdu_len =
encode_application_character_string(&apdu[0], &My_Object_Name);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
break;
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string, Description);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_SYSTEM_STATUS:
apdu_len = encode_application_enumerated(&apdu[0], System_Status);
break;
case PROP_VENDOR_NAME:
characterstring_init_ansi(&char_string, Vendor_Name);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_VENDOR_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0], Vendor_Identifier);
break;
case PROP_MODEL_NAME:
characterstring_init_ansi(&char_string, Model_Name);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_FIRMWARE_REVISION:
characterstring_init_ansi(&char_string, BACnet_Version);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_APPLICATION_SOFTWARE_VERSION:
characterstring_init_ansi(&char_string,
Application_Software_Version);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_LOCATION:
characterstring_init_ansi(&char_string, Location);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_PROTOCOL_VERSION:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Protocol_Version());
break;
case PROP_PROTOCOL_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Protocol_Revision());
break;
case PROP_PROTOCOL_SERVICES_SUPPORTED:
/* Note: list of services that are executed, not initiated. */
bitstring_init(&bit_string);
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
/* automatic lookup based on handlers set */
bitstring_set_bit(&bit_string, (uint8_t) i,
apdu_service_supported((BACNET_SERVICES_SUPPORTED) i));
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
/* Note: this is the list of objects that can be in this device,
not a list of objects that this device can access */
bitstring_init(&bit_string);
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
/* initialize all the object types to not-supported */
bitstring_set_bit(&bit_string, (uint8_t) i, false);
}
/* set the object types with objects to supported */
pObject = &Object_Table[0];
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
if ((pObject->Object_Count) && (pObject->Object_Count() > 0)) {
bitstring_set_bit(&bit_string, pObject->Object_Type, true);
}
pObject++;
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
/* Array element zero is the number of objects in the list */
if (rpdata->array_index == 0)
apdu_len = encode_application_unsigned(&apdu[0], count);
/* if no index was specified, then try to encode the entire list */
/* into one packet. Note that more than likely you will have */
/* to return an error if the number of encoded objects exceeds */
/* your maximum APDU size. */
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
for (i = 1; i <= count; i++) {
found =
Device_Object_List_Identifier(i, &object_type,
&instance);
if (found) {
len =
encode_application_object_id(&apdu[apdu_len],
object_type, instance);
apdu_len += len;
/* assume next one is the same size as this one */
/* can we all fit into the APDU? Don't check for last entry */
if ((i != count) && (apdu_len + len) >= MAX_APDU) {
/* Abort response */
rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
apdu_len = BACNET_STATUS_ABORT;
break;
}
} else {
/* error: internal error? */
rpdata->error_class = ERROR_CLASS_SERVICES;
rpdata->error_code = ERROR_CODE_OTHER;
apdu_len = BACNET_STATUS_ERROR;
break;
}
}
} else {
found =
Device_Object_List_Identifier(rpdata->array_index,
&object_type, &instance);
if (found) {
apdu_len =
encode_application_object_id(&apdu[0], object_type,
instance);
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = BACNET_STATUS_ERROR;
}
}
break;
case PROP_MAX_APDU_LENGTH_ACCEPTED:
apdu_len = encode_application_unsigned(&apdu[0], MAX_APDU);
break;
case PROP_SEGMENTATION_SUPPORTED:
apdu_len =
encode_application_enumerated(&apdu[0],
Device_Segmentation_Supported());
break;
case PROP_APDU_TIMEOUT:
apdu_len = encode_application_unsigned(&apdu[0], apdu_timeout());
break;
case PROP_NUMBER_OF_APDU_RETRIES:
apdu_len = encode_application_unsigned(&apdu[0], apdu_retries());
break;
case PROP_DEVICE_ADDRESS_BINDING:
/* FIXME: the real max apdu remaining should be passed into function */
apdu_len = address_list_encode(&apdu[0], MAX_APDU);
break;
case PROP_DATABASE_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0], Database_Revision);
break;
#if defined(BACDL_MSTP)
case PROP_MAX_INFO_FRAMES:
apdu_len =
encode_application_unsigned(&apdu[0],
dlmstp_max_info_frames());
break;
case PROP_MAX_MASTER:
apdu_len =
encode_application_unsigned(&apdu[0], dlmstp_max_master());
break;
#endif
case PROP_ACTIVE_COV_SUBSCRIPTIONS:
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = BACNET_STATUS_ERROR;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) && (rpdata->object_property != PROP_OBJECT_LIST) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = BACNET_STATUS_ERROR;
}
return apdu_len;
}
/** Looks up the requested Object and Property, and encodes its Value in an APDU.
* @ingroup ObjIntf
* If the Object or Property can't be found, sets the error class and code.
*
* @param rpdata [in,out] Structure with the desired Object and Property info
* on entry, and APDU message on return.
* @return The length of the APDU on success, else BACNET_STATUS_ERROR
*/
int Device_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
{
int apdu_len = BACNET_STATUS_ERROR;
struct object_functions *pObject = NULL;
/* initialize the default return values */
rpdata->error_class = ERROR_CLASS_OBJECT;
rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT;
pObject = Device_Objects_Find_Functions(rpdata->object_type);
if (pObject != NULL) {
if (pObject->Object_Valid_Instance &&
pObject->Object_Valid_Instance(rpdata->object_instance)) {
if (pObject->Object_Read_Property) {
apdu_len = pObject->Object_Read_Property(rpdata);
}
} else {
rpdata->error_class = ERROR_CLASS_OBJECT;
rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
} else {
rpdata->error_class = ERROR_CLASS_OBJECT;
rpdata->error_code = ERROR_CODE_UNSUPPORTED_OBJECT_TYPE;
}
return apdu_len;
}
/** Initialize the Device Object.
Initialize the group of object helper functions for any supported Object.
Initialize each of the Device Object child Object instances.
* @ingroup ObjIntf
* @param object_table [in,out] array of structure with object functions.
* Each Child Object must provide some implementation of each of these
* functions in order to properly support the default handlers.
*/
void Device_Init(
object_functions_t * object_table)
{
struct object_functions *pObject = NULL;
characterstring_init_ansi(&My_Object_Name, "SimpleClient");
/* we don't use the object table passed in */
(void) object_table;
pObject = &Object_Table[0];
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
if (pObject->Object_Init) {
pObject->Object_Init();
}
pObject++;
}
}
+250 -90
View File
@@ -83,87 +83,209 @@ extern int Routed_Device_Read_Property_Local(
extern bool Routed_Device_Write_Property_Local(
BACNET_WRITE_PROPERTY_DATA * wp_data);
/* may be overridden by outside table */
static object_functions_t *Object_Table;
static object_functions_t Object_Table[] = {
{
OBJECT_DEVICE, NULL, Device_Count, /* don't init - recursive! */
Device_Index_To_Instance, Device_Valid_Object_Instance_Number,
Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists,
NULL, NULL, NULL, NULL}, {
OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
Analog_Input_Object_Name, Analog_Input_Read_Property,
Analog_Input_Write_Property, Analog_Input_Property_Lists,
NULL, NULL, NULL, Analog_Input_Intrinsic_Reporting}, {
OBJECT_ANALOG_VALUE, Analog_Value_Init, Analog_Value_Count,
Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance,
Analog_Value_Object_Name, Analog_Value_Read_Property,
Analog_Value_Write_Property, Analog_Value_Property_Lists,
NULL, NULL, NULL, Analog_Value_Intrinsic_Reporting}, {
OBJECT_BINARY_INPUT, Binary_Input_Init, Binary_Input_Count,
Binary_Input_Index_To_Instance, Binary_Input_Valid_Instance,
Binary_Input_Object_Name, Binary_Input_Read_Property,
NULL, Binary_Input_Property_Lists,
NULL, NULL, NULL, NULL}, {
OBJECT_BINARY_VALUE, Binary_Value_Init, Binary_Value_Count,
Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance,
Binary_Value_Object_Name, Binary_Value_Read_Property,
Binary_Value_Write_Property, Binary_Value_Property_Lists,
NULL, NULL, NULL, NULL}, {
static object_functions_t My_Object_Table[] = {
{OBJECT_DEVICE,
NULL /* Init - don't init Device or it will recourse! */,
Device_Count,
Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name,
Device_Read_Property_Local,
Device_Write_Property_Local,
Device_Property_Lists,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
NULL /* Intrinsic Reporting */},
{OBJECT_ANALOG_INPUT,
Analog_Input_Init,
Analog_Input_Count,
Analog_Input_Index_To_Instance,
Analog_Input_Valid_Instance,
Analog_Input_Object_Name,
Analog_Input_Read_Property,
Analog_Input_Write_Property,
Analog_Input_Property_Lists,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
Analog_Input_Intrinsic_Reporting},
{OBJECT_ANALOG_VALUE,
Analog_Value_Init,
Analog_Value_Count,
Analog_Value_Index_To_Instance,
Analog_Value_Valid_Instance,
Analog_Value_Object_Name,
Analog_Value_Read_Property,
Analog_Value_Write_Property,
Analog_Value_Property_Lists,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
Analog_Value_Intrinsic_Reporting},
{OBJECT_BINARY_INPUT,
Binary_Input_Init,
Binary_Input_Count,
Binary_Input_Index_To_Instance,
Binary_Input_Valid_Instance,
Binary_Input_Object_Name,
Binary_Input_Read_Property,
NULL /* Write Property */,
Binary_Input_Property_Lists,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
Binary_Input_Encode_Value_List,
Binary_Input_Change_Of_Value,
Binary_Input_Change_Of_Value_Clear,
NULL /* Intrinsic Reporting */},
{OBJECT_BINARY_VALUE,
Binary_Value_Init,
Binary_Value_Count,
Binary_Value_Index_To_Instance,
Binary_Value_Valid_Instance,
Binary_Value_Object_Name,
Binary_Value_Read_Property,
Binary_Value_Write_Property,
Binary_Value_Property_Lists,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
NULL /* Intrinsic Reporting */},
#if defined(INTRINSIC_REPORTING)
OBJECT_NOTIFICATION_CLASS, Notification_Class_Init,
Notification_Class_Count,
Notification_Class_Index_To_Instance,
Notification_Class_Valid_Instance,
Notification_Class_Object_Name, Notification_Class_Read_Property,
Notification_Class_Write_Property,
Notification_Class_Property_Lists,
NULL, NULL, NULL, NULL}, {
{OBJECT_NOTIFICATION_CLASS,
Notification_Class_Init,
Notification_Class_Count,
Notification_Class_Index_To_Instance,
Notification_Class_Valid_Instance,
Notification_Class_Object_Name,
Notification_Class_Read_Property,
Notification_Class_Write_Property,
Notification_Class_Property_Lists,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
NULL /* Intrinsic Reporting */},
#endif
OBJECT_LIFE_SAFETY_POINT, Life_Safety_Point_Init,
Life_Safety_Point_Count,
Life_Safety_Point_Index_To_Instance,
Life_Safety_Point_Valid_Instance,
Life_Safety_Point_Object_Name, Life_Safety_Point_Read_Property,
Life_Safety_Point_Write_Property, Life_Safety_Point_Property_Lists,
NULL, NULL, NULL, NULL}, {
OBJECT_LOAD_CONTROL, Load_Control_Init, Load_Control_Count,
Load_Control_Index_To_Instance, Load_Control_Valid_Instance,
Load_Control_Object_Name, Load_Control_Read_Property,
Load_Control_Write_Property, Load_Control_Property_Lists,
NULL, NULL, NULL, NULL}, {
OBJECT_MULTI_STATE_OUTPUT, Multistate_Output_Init,
Multistate_Output_Count,
Multistate_Output_Index_To_Instance,
Multistate_Output_Valid_Instance,
Multistate_Output_Object_Name, Multistate_Output_Read_Property,
Multistate_Output_Write_Property, Multistate_Output_Property_Lists,
NULL, NULL, NULL, NULL}, {
OBJECT_MULTI_STATE_INPUT, Multistate_Input_Init,
Multistate_Input_Count,
Multistate_Input_Index_To_Instance,
Multistate_Input_Valid_Instance,
Multistate_Input_Object_Name, Multistate_Input_Read_Property,
Multistate_Input_Write_Property, Multistate_Input_Property_Lists,
NULL, NULL, NULL, NULL}, {
OBJECT_TRENDLOG, Trend_Log_Init, Trend_Log_Count,
Trend_Log_Index_To_Instance, Trend_Log_Valid_Instance,
Trend_Log_Object_Name, Trend_Log_Read_Property,
Trend_Log_Write_Property, Trend_Log_Property_Lists,
TrendLogGetRRInfo, NULL, NULL, NULL}, {
{OBJECT_LIFE_SAFETY_POINT,
Life_Safety_Point_Init,
Life_Safety_Point_Count,
Life_Safety_Point_Index_To_Instance,
Life_Safety_Point_Valid_Instance,
Life_Safety_Point_Object_Name,
Life_Safety_Point_Read_Property,
Life_Safety_Point_Write_Property,
Life_Safety_Point_Property_Lists,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
NULL /* Intrinsic Reporting */},
{OBJECT_LOAD_CONTROL,
Load_Control_Init,
Load_Control_Count,
Load_Control_Index_To_Instance,
Load_Control_Valid_Instance,
Load_Control_Object_Name,
Load_Control_Read_Property,
Load_Control_Write_Property,
Load_Control_Property_Lists,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
NULL /* Intrinsic Reporting */},
{OBJECT_MULTI_STATE_OUTPUT,
Multistate_Output_Init,
Multistate_Output_Count,
Multistate_Output_Index_To_Instance,
Multistate_Output_Valid_Instance,
Multistate_Output_Object_Name,
Multistate_Output_Read_Property,
Multistate_Output_Write_Property,
Multistate_Output_Property_Lists,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
NULL /* Intrinsic Reporting */},
{OBJECT_MULTI_STATE_INPUT,
Multistate_Input_Init,
Multistate_Input_Count,
Multistate_Input_Index_To_Instance,
Multistate_Input_Valid_Instance,
Multistate_Input_Object_Name,
Multistate_Input_Read_Property,
Multistate_Input_Write_Property,
Multistate_Input_Property_Lists,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
NULL /* Intrinsic Reporting */},
{OBJECT_TRENDLOG,
Trend_Log_Init,
Trend_Log_Count,
Trend_Log_Index_To_Instance,
Trend_Log_Valid_Instance,
Trend_Log_Object_Name,
Trend_Log_Read_Property,
Trend_Log_Write_Property,
Trend_Log_Property_Lists,
TrendLogGetRRInfo,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
NULL /* Intrinsic Reporting */},
#if defined(BACFILE)
OBJECT_FILE, bacfile_init, bacfile_count,
bacfile_index_to_instance, bacfile_valid_instance,
bacfile_object_name, bacfile_read_property,
bacfile_write_property, BACfile_Property_Lists,
NULL, NULL, NULL, NULL}, {
{OBJECT_FILE,
bacfile_init,
bacfile_count,
bacfile_index_to_instance,
bacfile_valid_instance,
bacfile_object_name,
bacfile_read_property,
bacfile_write_property,
BACfile_Property_Lists,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
NULL /* Intrinsic Reporting */},
#endif
MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL}
{MAX_BACNET_OBJECT_TYPE,
NULL /* Init */,
NULL /* Count */,
NULL /* Index_To_Instance */,
NULL /* Valid_Instance */,
NULL /* Object_Name */,
NULL /* Read_Property */,
NULL /* Write_Property */,
NULL /* Property_Lists */,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
NULL /* Intrinsic Reporting */}
};
/** Glue function to let the Device object, when called by a handler,
* lookup which Object type needs to be invoked.
* @ingroup ObjHelpers
@@ -176,13 +298,12 @@ static struct object_functions *Device_Objects_Find_Functions(
{
struct object_functions *pObject = NULL;
pObject = &Object_Table[0];
pObject = Object_Table;
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
/* handle each object type */
if (pObject->Object_Type == Object_Type) {
return (pObject);
}
pObject++;
}
@@ -341,16 +462,16 @@ static const int Device_Properties_Required[] = {
PROP_SEGMENTATION_SUPPORTED,
PROP_APDU_TIMEOUT,
PROP_NUMBER_OF_APDU_RETRIES,
#if defined(BACDL_MSTP)
PROP_MAX_MASTER,
PROP_MAX_INFO_FRAMES,
#endif
PROP_DEVICE_ADDRESS_BINDING,
PROP_DATABASE_REVISION,
-1
};
static const int Device_Properties_Optional[] = {
#if defined(BACDL_MSTP)
PROP_MAX_MASTER,
PROP_MAX_INFO_FRAMES,
#endif
PROP_DESCRIPTION,
PROP_LOCAL_TIME,
PROP_UTC_OFFSET,
@@ -744,7 +865,7 @@ unsigned Device_Object_List_Count(
struct object_functions *pObject = NULL;
/* initialize the default return values */
pObject = &Object_Table[0];
pObject = Object_Table;
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
if (pObject->Object_Count) {
count += pObject->Object_Count();
@@ -782,7 +903,7 @@ bool Device_Object_List_Identifier(
}
object_index = array_index - 1;
/* initialize the default return values */
pObject = &Object_Table[0];
pObject = Object_Table;
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
if (pObject->Object_Count) {
object_index -= count;
@@ -887,7 +1008,7 @@ bool Device_Valid_Object_Id(
* @return True on success or else False if not found.
*/
bool Device_Object_Name_Copy(
BACNET_OBJECT_TYPE object_type,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
{
@@ -1087,7 +1208,7 @@ int Device_Read_Property_Local(
}
/* set the object types with objects to supported */
pObject = &Object_Table[0];
pObject = Object_Table;
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
if ((pObject->Object_Count) && (pObject->Object_Count() > 0)) {
bitstring_set_bit(&bit_string, pObject->Object_Type, true);
@@ -1206,7 +1327,7 @@ int Device_Read_Property_Local(
* If the Object or Property can't be found, sets the error class and code.
*
* @param rpdata [in,out] Structure with the desired Object and Property info
* on entry, and APDU message on return.
* on entry, and APDU message on return.
* @return The length of the APDU on success, else BACNET_STATUS_ERROR
*/
int Device_Read_Property(
@@ -1483,6 +1604,43 @@ bool Device_Encode_Value_List(
return (status);
}
bool Device_COV(
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance)
{
bool status = false; /* Ever the pessamist! */
struct object_functions *pObject = NULL;
pObject = Device_Objects_Find_Functions(object_type);
if (pObject != NULL) {
if (pObject->Object_Valid_Instance &&
pObject->Object_Valid_Instance(object_instance)) {
if (pObject->Object_COV) {
status = pObject->Object_COV(
object_instance);
}
}
}
return (status);
}
void Device_COV_Clear(
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance)
{
struct object_functions *pObject = NULL;
pObject = Device_Objects_Find_Functions(object_type);
if (pObject != NULL) {
if (pObject->Object_Valid_Instance &&
pObject->Object_Valid_Instance(object_instance)) {
if (pObject->Object_COV_Clear) {
pObject->Object_COV_Clear(object_instance);
}
}
}
}
#if defined(INTRINSIC_REPORTING)
void Device_local_reporting(
@@ -1548,10 +1706,12 @@ void Device_Init(
struct object_functions *pObject = NULL;
characterstring_init_ansi(&My_Object_Name, "SimpleServer");
/* we don't use the object table passed in
since there is extra stuff we don't need in there. */
(void) object_table;
pObject = &Object_Table[0];
if (object_table) {
Object_Table = object_table;
} else {
Object_Table = &My_Object_Table[0];
}
pObject = Object_Table;
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
if (pObject->Object_Init) {
pObject->Object_Init();
@@ -1625,7 +1785,7 @@ void Routing_Device_Init(
Add_Routed_Device(first_object_instance, &My_Object_Name, Description);
/* Now substitute our routed versions of the main object functions. */
pDevObject = &Object_Table[0];
pDevObject = Object_Table;
pDevObject->Object_Index_To_Instance = Routed_Device_Index_To_Instance;
pDevObject->Object_Valid_Instance =
Routed_Device_Valid_Object_Instance_Number;
+35 -10
View File
@@ -70,7 +70,7 @@ typedef uint32_t(
* @param object_name [in,out] Pointer to a character_string structure that
* will hold a copy of the object name if this is a valid object_instance.
* @return True if the object_instance is valid and object_name has been
* filled with a copy of the Object's name.
* filled with a copy of the Object's name.
*/
typedef bool(
*object_name_function)
@@ -113,6 +113,23 @@ typedef bool(
uint32_t object_instance,
BACNET_PROPERTY_VALUE * value_list);
/** Look in the table of objects for this instance to see if value changed.
* @ingroup ObjHelpers
* @param [in] The object instance number to be looked up.
* @return True if the object instance has changed.
*/
typedef bool(
*object_cov_function) (
uint32_t object_instance);
/** Look in the table of objects for this instance to clear the changed flag.
* @ingroup ObjHelpers
* @param [in] The object instance number to be looked up.
*/
typedef void(
*object_cov_clear_function) (
uint32_t object_instance);
/** Intrinsic Reporting funcionality.
* @ingroup ObjHelpers
* @param [in] Object instance.
@@ -127,7 +144,7 @@ typedef void (
* Each Object must provide some implementation of each of these helpers
* in order to properly support the handlers. Eg, the ReadProperty handler
* handler_read_property() relies on the instance of Object_Read_Property
* for each Object type.
* for each Object type, or configure the function as NULL.
* In both appearance and operation, this group of functions acts like
* they are member functions of a C++ Object base class.
*/
@@ -144,6 +161,8 @@ typedef struct object_functions {
rr_info_function Object_RR_Info;
object_iterate_function Object_Iterator;
object_value_list_function Object_Value_List;
object_cov_function Object_COV;
object_cov_clear_function Object_COV_Clear;
object_intrinsic_reporting_function Object_Intrinsic_Reporting;
} object_functions_t;
@@ -224,13 +243,19 @@ extern "C" {
void Device_Objects_Property_List(
BACNET_OBJECT_TYPE object_type,
struct special_property_list_t *pPropertyList);
/* functions to support COV */
bool Device_Encode_Value_List(
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_PROPERTY_VALUE * value_list);
bool Device_Value_List_Supported(
BACNET_OBJECT_TYPE object_type);
bool Device_COV(
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance);
void Device_COV_Clear(
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance);
uint32_t Device_Object_Instance_Number(
void);
@@ -401,11 +426,7 @@ extern "C" {
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define DEVICE_OBJ_FUNCTIONS \
OBJECT_DEVICE, NULL, Device_Count, Device_Index_To_Instance, \
Device_Valid_Object_Instance_Number, Device_Object_Name, \
Device_Read_Property_Local, Device_Write_Property_Local, \
Device_Property_Lists, DeviceGetRRInfo, NULL, NULL
/** @defgroup ObjFrmwk Object Framework
* The modules in this section describe the BACnet-stack's framework for
* BACnet-defined Objects (Device, Analog Input, etc). There are two submodules
@@ -415,11 +436,15 @@ extern "C" {
* - The interface between the implemented Objects and the BAC-stack services,
* specifically the handlers, which are mediated through function calls to
* the Device object.
*//** @defgroup ObjHelpers Object Helper Functions
*/
/** @defgroup ObjHelpers Object Helper Functions
* @ingroup ObjFrmwk
* This section describes the function templates for the helper functions that
* provide common object support.
*//** @defgroup ObjIntf Handler-to-Object Interface Functions
*/
/** @defgroup ObjIntf Handler-to-Object Interface Functions
* @ingroup ObjFrmwk
* This section describes the fairly limited set of functions that link the
* BAC-stack handlers to the BACnet Object instances. All of these calls are
+1 -6
View File
@@ -76,10 +76,5 @@ extern "C" {
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define LOAD_CONTROL_OBJ_FUNCTIONS \
OBJECT_LOAD_CONTROL, Load_Control_Init, Load_Control_Count, \
Load_Control_Index_To_Instance, Load_Control_Valid_Instance, \
Load_Control_Object_Name, Load_Control_Read_Property, \
Load_Control_Write_Property, Load_Control_Property_Lists, NULL, \
NULL, NULL
#endif
+1 -7
View File
@@ -69,11 +69,5 @@ extern "C" {
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define LIFE_SAFETY_POINT_OBJ_FUNCTIONS \
OBJECT_LIFE_SAFETY_POINT, Life_Safety_Point_Init, \
Life_Safety_Point_Count, Life_Safety_Point_Index_To_Instance, \
Life_Safety_Point_Valid_Instance, Life_Safety_Point_Object_Name, \
Life_Safety_Point_Read_Property, \
Life_Safety_Point_Write_Property, \
Life_Safety_Point_Property_Lists, NULL, NULL, NULL
#endif
+1 -7
View File
@@ -96,11 +96,5 @@ extern "C" {
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define MULTI_STATE_INPUT_OBJ_FUNCTIONS \
OBJECT_MULTI_STATE_INPUT, Multistate_Input_Init, \
Multistate_Input_Count, Multistate_Input_Index_To_Instance, \
Multistate_Input_Valid_Instance, Multistate_Input_Object_Name, \
Multistate_Input_Read_Property, \
Multistate_Input_Write_Property, \
Multistate_Input_Property_Lists, NULL, NULL, NULL
#endif
+1 -7
View File
@@ -71,11 +71,5 @@ extern "C" {
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define MULTI_STATE_OUTPUT_OBJ_FUNCTIONS \
OBJECT_MULTI_STATE_OUTPUT, Multistate_Output_Init, \
Multistate_Output_Count, Multistate_Output_Index_To_Instance, \
Multistate_Output_Valid_Instance, Multistate_Output_Object_Name, \
Multistate_Output_Read_Property, \
Multistate_Output_Write_Property, \
Multistate_Output_Property_Lists, NULL, NULL, NULL
#endif
+1 -6
View File
@@ -138,10 +138,5 @@ BACnetRecipient ::= CHOICE {
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define NOTIFICATION_CLASS_OBJ_FUNCTIONS \
OBJECT_NOTIFICATION_CLASS, Notification_Class_Init, Notification_Class_Count, \
Notification_Class_Index_To_Instance, Notification_Class_Valid_Instance, \
Notification_Class_Object_Name, Notification_Class_Read_Property, \
Notification_Class_Write_Property, Notification_Class_Property_Lists, \
NULL, NULL, NULL
#endif /* NC_H */
+1 -6
View File
@@ -197,10 +197,5 @@ extern "C" {
#ifdef __cplusplus
}
#endif /* __cplusplus */
#define TRENDLOG_OBJ_FUNCTIONS \
OBJECT_TRENDLOG, Trend_Log_Init, Trend_Log_Count, \
Trend_Log_Index_To_Instance, Trend_Log_Valid_Instance, \
Trend_Log_Object_Name, Trend_Log_Read_Property, \
Trend_Log_Write_Property, Trend_Log_Property_Lists, \
TrendLogGetRRInfo, NULL, NULL
#endif
+44 -37
View File
@@ -1,37 +1,44 @@
#Makefile to build BACnet Application for the Linux Port
# tools - only if you need them.
# Most platforms have this already defined
# CC = gcc
TARGET = ptransfer
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.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
#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
+1 -8
View File
@@ -68,13 +68,6 @@ uint8_t Send_Private_Transfer_Request(
char block_number,
DATABLOCK * block);
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -132,7 +125,7 @@ void MyRejectHandler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
+2 -1
View File
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+2 -1
View File
@@ -8,7 +8,8 @@ TARGET = bacarf
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+1 -8
View File
@@ -50,13 +50,6 @@
#include "txbuf.h"
#include "dlenv.h"
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -186,7 +179,7 @@ static void LocalIAmHandler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
+2 -1
View File
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+2 -1
View File
@@ -14,7 +14,8 @@ TARGET = bacrp
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+1 -8
View File
@@ -53,13 +53,6 @@
#include "txbuf.h"
#include "dlenv.h"
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -150,7 +143,7 @@ void My_Read_Property_Ack_Handler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
+2 -1
View File
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+2 -1
View File
@@ -9,7 +9,8 @@ TARGET = bacrpm
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+1 -8
View File
@@ -54,13 +54,6 @@
#include "txbuf.h"
#include "dlenv.h"
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -195,7 +188,7 @@ void My_Read_Property_Multiple_Ack_Handler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
+2 -1
View File
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+1 -8
View File
@@ -80,13 +80,6 @@
#define _stricmp stricmp
#endif
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -144,7 +137,7 @@ void MyRejectHandler(
static void Init_Objects(
void)
{
Device_Init(&Object_Table[0]);
Device_Init(NULL);
}
static void Init_Service_Handlers(
+2 -1
View File
@@ -9,7 +9,8 @@ TARGET = bacrd
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+1 -8
View File
@@ -51,13 +51,6 @@
#include "txbuf.h"
#include "dlenv.h"
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -121,7 +114,7 @@ void MyReinitializeDeviceSimpleAckHandler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
+2 -1
View File
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+2 -1
View File
@@ -14,7 +14,8 @@ TARGET = bacscov
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+1 -8
View File
@@ -54,13 +54,6 @@
#include "txbuf.h"
#include "dlenv.h"
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -121,7 +114,7 @@ void MyRejectHandler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
+2 -1
View File
@@ -45,7 +45,8 @@ BUILD_DEFINE = -DMAX_PROPERTY_VALUES=64
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) $(BUILD_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+7 -3
View File
@@ -118,6 +118,9 @@ static void Init_Service_Handlers(
/* handle communication so we can shutup when asked */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
handler_device_communication_control);
/* handle the data coming back from private requests */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_PRIVATE_TRANSFER,
handler_unconfirmed_private_transfer);
#if defined(INTRINSIC_REPORTING)
apdu_set_confirmed_handler(SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM,
handler_alarm_ack);
@@ -202,15 +205,16 @@ int main(
dlenv_maintenance_timer(elapsed_seconds);
Load_Control_State_Machine_Handler();
elapsed_milliseconds = elapsed_seconds * 1000;
if (dcc_communication_enabled()) {
handler_cov_task(elapsed_seconds);
}
handler_cov_timer_seconds(elapsed_seconds);
tsm_timer_milliseconds(elapsed_milliseconds);
trend_log_timer(elapsed_seconds);
#if defined(INTRINSIC_REPORTING)
Device_local_reporting();
#endif
}
if (dcc_communication_enabled()) {
handler_cov_task();
}
/* scan cache address */
address_binding_tmr += elapsed_seconds;
if (address_binding_tmr >= 60) {
+2 -1
View File
@@ -9,7 +9,8 @@ TARGET = bacts
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+1 -8
View File
@@ -46,13 +46,6 @@
#include "txbuf.h"
#include "dlenv.h"
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -93,7 +86,7 @@ void MyRejectHandler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
+2 -1
View File
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+2 -1
View File
@@ -9,7 +9,8 @@ TARGET = bacucov
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+1 -8
View File
@@ -50,17 +50,10 @@
#include "txbuf.h"
#include "dlenv.h"
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
+2 -1
View File
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+2 -1
View File
@@ -14,7 +14,8 @@ TARGET = bacupt
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+3 -74
View File
@@ -54,13 +54,6 @@
#include "txbuf.h"
#include "dlenv.h"
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -124,74 +117,10 @@ void MyRejectHandler(
}
}
void MyUnconfirmedPrivateTransferHandler(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src)
{
BACNET_PRIVATE_TRANSFER_DATA private_data;
BACNET_OBJECT_PROPERTY_VALUE object_value; /* for bacapp printing */
BACNET_APPLICATION_DATA_VALUE value; /* for decode value data */
int len = 0;
uint8_t *application_data;
int application_data_len;
bool first_value = true;
bool print_brace = false;
len = ptransfer_decode_service_request(
service_request, service_len, &private_data);
if (len >= 0) {
printf("PrivateTransfer:vendorID=%u\r\n",
(unsigned)private_data.vendorID);
printf("PrivateTransfer:serviceNumber=%lu\r\n",
(unsigned long)private_data.serviceNumber);
application_data = private_data.serviceParameters;
application_data_len = private_data.serviceParametersLen;
for (;;) {
len =
bacapp_decode_application_data(application_data,
(uint8_t) application_data_len, &value);
if (first_value && (len < application_data_len)) {
first_value = false;
#if PRINT_ENABLED
fprintf(stdout, "{");
#endif
print_brace = true;
}
/* private transfer doesn't provide any clues */
object_value.object_type = MAX_BACNET_OBJECT_TYPE;
object_value.object_instance = BACNET_MAX_INSTANCE;
object_value.object_property = MAX_BACNET_PROPERTY_ID;
object_value.array_index = BACNET_ARRAY_ALL;
object_value.value = &value;
bacapp_print_value(stdout, &object_value);
if (len > 0) {
if (len < application_data_len) {
application_data += len;
application_data_len -= len;
/* there's more! */
#if PRINT_ENABLED
fprintf(stdout, ",");
#endif
} else {
break;
}
} else {
break;
}
}
#if PRINT_ENABLED
if (print_brace)
fprintf(stdout, "}");
fprintf(stdout, "\r\n");
#endif
}
}
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
@@ -204,9 +133,9 @@ static void Init_Service_Handlers(
/* 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 confirmed requests */
/* handle the data coming back from requests */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_PRIVATE_TRANSFER,
MyUnconfirmedPrivateTransferHandler);
handler_unconfirmed_private_transfer);
/* handle any errors coming back */
apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY, MyErrorHandler);
apdu_set_abort_handler(MyAbortHandler);
+2 -1
View File
@@ -45,7 +45,8 @@ BUILD_DEFINE = -DMAX_PROPERTY_VALUES=64
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) $(BUILD_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+2 -1
View File
@@ -9,7 +9,8 @@ TARGET = bacwh
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+1 -8
View File
@@ -50,13 +50,6 @@
#include "txbuf.h"
#include "dlenv.h"
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -96,7 +89,7 @@ void MyRejectHandler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
+2 -1
View File
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+2 -1
View File
@@ -8,7 +8,8 @@ TARGET = bacwi
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+1 -8
View File
@@ -50,13 +50,6 @@
#endif
#include "dlenv.h"
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -97,7 +90,7 @@ void MyRejectHandler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
Device_Init(NULL);
/* Note: this applications doesn't need to handle who-is
it is confusing for the user! */
/* set the handler for all the services we don't implement
+2 -1
View File
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+2 -1
View File
@@ -8,7 +8,8 @@ TARGET = bacwir
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+1 -7
View File
@@ -51,12 +51,6 @@
#endif
#include "dlenv.h"
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -175,7 +169,7 @@ void My_NPDU_Handler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
+2 -1
View File
@@ -42,7 +42,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+2 -1
View File
@@ -9,7 +9,8 @@ TARGET = bacawf
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+1 -8
View File
@@ -50,13 +50,6 @@
#include "txbuf.h"
#include "dlenv.h"
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -140,7 +133,7 @@ static void LocalIAmHandler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
+2 -1
View File
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+2 -1
View File
@@ -9,7 +9,8 @@ TARGET = bacwp
TARGET_BIN = ${TARGET}$(TARGET_EXT)
SRCS = main.c
SRCS = main.c \
../object/device-client.c
OBJS = ${SRCS:.c=.o}
+1 -8
View File
@@ -56,13 +56,6 @@
#define MAX_PROPERTY_VALUES 64
#endif
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL}
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -141,7 +134,7 @@ void MyWritePropertySimpleAckHandler(
static void Init_Service_Handlers(
void)
{
Device_Init(&Object_Table[0]);
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);
+2 -1
View File
@@ -45,7 +45,8 @@ WRITEPROPS_DEFINE = -DMAX_PROPERTY_VALUES=64
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) $(WRITEPROPS_DEFINE)
SRCS = main.c
SRCS = main.c \
$(BACNET_OBJECT)\device-client.c
OBJS = $(SRCS:.c=.obj)
+2 -1
View File
@@ -215,7 +215,8 @@ extern "C" {
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data);
void handler_cov_task(
void handler_cov_task(void);
void handler_cov_timer_seconds(
uint32_t elapsed_seconds);
void handler_cov_init(
void);
+1 -22
View File
@@ -59,26 +59,6 @@
#include "bacfile.h"
#endif
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{DEVICE_OBJ_FUNCTIONS},
{ANALOG_INPUT_OBJ_FUNCTIONS},
{ANALOG_OUTPUT_OBJ_FUNCTIONS},
{ANALOG_VALUE_OBJ_FUNCTIONS},
{BINARY_INPUT_OBJ_FUNCTIONS},
{BINARY_OUTPUT_OBJ_FUNCTIONS},
{BINARY_VALUE_OBJ_FUNCTIONS},
{LIFE_SAFETY_POINT_OBJ_FUNCTIONS},
{LOAD_CONTROL_OBJ_FUNCTIONS},
{MULTI_STATE_OUTPUT_OBJ_FUNCTIONS},
{MULTI_STATE_INPUT_OBJ_FUNCTIONS},
{TRENDLOG_OBJ_FUNCTIONS},
#if defined(BACFILE)
{FILE_OBJ_FUNCTIONS},
#endif
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
};
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
@@ -189,8 +169,7 @@ static void LocalIAmHandler(
static void Init_Service_Handlers(
void)
{
Device_Initialize_Object_Functions(&Object_Table[0]);
Device_Init();
Device_Init(NULL);
/* we need to handle who-is to support dynamic device binding */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);