diff --git a/bacnet-stack/demo/dcc/Makefile b/bacnet-stack/demo/dcc/Makefile index 3060b9d3..1ddc8981 100644 --- a/bacnet-stack/demo/dcc/Makefile +++ b/bacnet-stack/demo/dcc/Makefile @@ -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} diff --git a/bacnet-stack/demo/dcc/main.c b/bacnet-stack/demo/dcc/main.c index d2266801..cf1f57bd 100644 --- a/bacnet-stack/demo/dcc/main.c +++ b/bacnet-stack/demo/dcc/main.c @@ -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); diff --git a/bacnet-stack/demo/dcc/makefile.b32 b/bacnet-stack/demo/dcc/makefile.b32 index b5a28e87..9baddb54 100644 --- a/bacnet-stack/demo/dcc/makefile.b32 +++ b/bacnet-stack/demo/dcc/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/epics/bacepics.cbp b/bacnet-stack/demo/epics/bacepics.cbp index db1331bb..3733fdeb 100644 --- a/bacnet-stack/demo/epics/bacepics.cbp +++ b/bacnet-stack/demo/epics/bacepics.cbp @@ -48,6 +48,9 @@ + + diff --git a/bacnet-stack/demo/epics/main.c b/bacnet-stack/demo/epics/main.c index 4e5c3d0a..f1070883 100644 --- a/bacnet-stack/demo/epics/main.c +++ b/bacnet-stack/demo/epics/main.c @@ -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 @@ -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. */ diff --git a/bacnet-stack/demo/gateway/main.c b/bacnet-stack/demo/gateway/main.c index 68376abc..8e97c566 100644 --- a/bacnet-stack/demo/gateway/main.c +++ b/bacnet-stack/demo/gateway/main.c @@ -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); diff --git a/bacnet-stack/demo/handler/h_cov.c b/bacnet-stack/demo/handler/h_cov.c index 56f054ab..7a498b90 100644 --- a/bacnet-stack/demo/handler/h_cov.c +++ b/bacnet-stack/demo/handler/h_cov.c @@ -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); diff --git a/bacnet-stack/demo/handler/h_upt.c b/bacnet-stack/demo/handler/h_upt.c index 8ce97311..adb8bb71 100644 --- a/bacnet-stack/demo/handler/h_upt.c +++ b/bacnet-stack/demo/handler/h_upt.c @@ -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 } } + diff --git a/bacnet-stack/demo/iamrouter/Makefile b/bacnet-stack/demo/iamrouter/Makefile index a20b6fb2..5b342c1d 100644 --- a/bacnet-stack/demo/iamrouter/Makefile +++ b/bacnet-stack/demo/iamrouter/Makefile @@ -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} diff --git a/bacnet-stack/demo/iamrouter/main.c b/bacnet-stack/demo/iamrouter/main.c index 7d8d3853..716c402a 100644 --- a/bacnet-stack/demo/iamrouter/main.c +++ b/bacnet-stack/demo/iamrouter/main.c @@ -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); diff --git a/bacnet-stack/demo/iamrouter/makefile.b32 b/bacnet-stack/demo/iamrouter/makefile.b32 index 2f09819f..72cc4b15 100644 --- a/bacnet-stack/demo/iamrouter/makefile.b32 +++ b/bacnet-stack/demo/iamrouter/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/initrouter/Makefile b/bacnet-stack/demo/initrouter/Makefile index 8bf952ce..e48e8b16 100644 --- a/bacnet-stack/demo/initrouter/Makefile +++ b/bacnet-stack/demo/initrouter/Makefile @@ -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} diff --git a/bacnet-stack/demo/initrouter/main.c b/bacnet-stack/demo/initrouter/main.c index 6205788d..03e1b10d 100644 --- a/bacnet-stack/demo/initrouter/main.c +++ b/bacnet-stack/demo/initrouter/main.c @@ -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); diff --git a/bacnet-stack/demo/initrouter/makefile.b32 b/bacnet-stack/demo/initrouter/makefile.b32 index 52839306..8c7b7871 100644 --- a/bacnet-stack/demo/initrouter/makefile.b32 +++ b/bacnet-stack/demo/initrouter/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/object/ai.h b/bacnet-stack/demo/object/ai.h index 23daf740..0bd3c4fb 100644 --- a/bacnet-stack/demo/object/ai.h +++ b/bacnet-stack/demo/object/ai.h @@ -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 diff --git a/bacnet-stack/demo/object/ao.h b/bacnet-stack/demo/object/ao.h index b2c2bf9b..688120a8 100644 --- a/bacnet-stack/demo/object/ao.h +++ b/bacnet-stack/demo/object/ao.h @@ -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 diff --git a/bacnet-stack/demo/object/av.h b/bacnet-stack/demo/object/av.h index e05f8886..08a62575 100644 --- a/bacnet-stack/demo/object/av.h +++ b/bacnet-stack/demo/object/av.h @@ -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 diff --git a/bacnet-stack/demo/object/bacfile.h b/bacnet-stack/demo/object/bacfile.h index 5285512e..4cd53a13 100644 --- a/bacnet-stack/demo/object/bacfile.h +++ b/bacnet-stack/demo/object/bacfile.h @@ -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 diff --git a/bacnet-stack/demo/object/bi.c b/bacnet-stack/demo/object/bi.c index 827e8bea..3c0828cc 100644 --- a/bacnet-stack/demo/object/bi.c +++ b/bacnet-stack/demo/object/bi.c @@ -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; } diff --git a/bacnet-stack/demo/object/bi.h b/bacnet-stack/demo/object/bi.h index 8a9862ab..dd0a9c9f 100644 --- a/bacnet-stack/demo/object/bi.h +++ b/bacnet-stack/demo/object/bi.h @@ -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 diff --git a/bacnet-stack/demo/object/bo.h b/bacnet-stack/demo/object/bo.h index 90224350..f3c95c94 100644 --- a/bacnet-stack/demo/object/bo.h +++ b/bacnet-stack/demo/object/bo.h @@ -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 diff --git a/bacnet-stack/demo/object/bv.h b/bacnet-stack/demo/object/bv.h index dcb33904..8d437ac2 100644 --- a/bacnet-stack/demo/object/bv.h +++ b/bacnet-stack/demo/object/bv.h @@ -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 diff --git a/bacnet-stack/demo/object/device-client.c b/bacnet-stack/demo/object/device-client.c new file mode 100644 index 00000000..4a32e7ad --- /dev/null +++ b/bacnet-stack/demo/object/device-client.c @@ -0,0 +1,908 @@ +/************************************************************************** +* +* Copyright (C) 2011 Steve Karg +* +* 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 +#include +#include /* for memmove */ +#include /* 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++; + } +} diff --git a/bacnet-stack/demo/object/device.c b/bacnet-stack/demo/object/device.c index 7050ec96..1134892e 100644 --- a/bacnet-stack/demo/object/device.c +++ b/bacnet-stack/demo/object/device.c @@ -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; diff --git a/bacnet-stack/demo/object/device.h b/bacnet-stack/demo/object/device.h index 8c84eeb5..084efea0 100644 --- a/bacnet-stack/demo/object/device.h +++ b/bacnet-stack/demo/object/device.h @@ -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 diff --git a/bacnet-stack/demo/object/lc.h b/bacnet-stack/demo/object/lc.h index 09704288..02aec0a8 100644 --- a/bacnet-stack/demo/object/lc.h +++ b/bacnet-stack/demo/object/lc.h @@ -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 diff --git a/bacnet-stack/demo/object/lsp.h b/bacnet-stack/demo/object/lsp.h index 402622c9..0db654f7 100644 --- a/bacnet-stack/demo/object/lsp.h +++ b/bacnet-stack/demo/object/lsp.h @@ -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 diff --git a/bacnet-stack/demo/object/ms-input.h b/bacnet-stack/demo/object/ms-input.h index 4a8fbe2c..9f71311b 100644 --- a/bacnet-stack/demo/object/ms-input.h +++ b/bacnet-stack/demo/object/ms-input.h @@ -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 diff --git a/bacnet-stack/demo/object/mso.h b/bacnet-stack/demo/object/mso.h index 829b2e37..fe9a642b 100644 --- a/bacnet-stack/demo/object/mso.h +++ b/bacnet-stack/demo/object/mso.h @@ -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 diff --git a/bacnet-stack/demo/object/nc.h b/bacnet-stack/demo/object/nc.h index 14552f3f..04c0ea68 100644 --- a/bacnet-stack/demo/object/nc.h +++ b/bacnet-stack/demo/object/nc.h @@ -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 */ diff --git a/bacnet-stack/demo/object/trendlog.h b/bacnet-stack/demo/object/trendlog.h index 336686bc..1caef24e 100644 --- a/bacnet-stack/demo/object/trendlog.h +++ b/bacnet-stack/demo/object/trendlog.h @@ -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 diff --git a/bacnet-stack/demo/ptransfer/Makefile b/bacnet-stack/demo/ptransfer/Makefile index 3bf45d01..1c2d5b7d 100644 --- a/bacnet-stack/demo/ptransfer/Makefile +++ b/bacnet-stack/demo/ptransfer/Makefile @@ -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 diff --git a/bacnet-stack/demo/ptransfer/main.c b/bacnet-stack/demo/ptransfer/main.c index 0fbc7425..6d1e1a5e 100644 --- a/bacnet-stack/demo/ptransfer/main.c +++ b/bacnet-stack/demo/ptransfer/main.c @@ -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); diff --git a/bacnet-stack/demo/ptransfer/makefile.b32 b/bacnet-stack/demo/ptransfer/makefile.b32 index 5bfcb9f5..f9d9fc77 100644 --- a/bacnet-stack/demo/ptransfer/makefile.b32 +++ b/bacnet-stack/demo/ptransfer/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/readfile/Makefile b/bacnet-stack/demo/readfile/Makefile index 72d28828..235f65c7 100644 --- a/bacnet-stack/demo/readfile/Makefile +++ b/bacnet-stack/demo/readfile/Makefile @@ -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} diff --git a/bacnet-stack/demo/readfile/main.c b/bacnet-stack/demo/readfile/main.c index 8b655c2f..5d10af92 100644 --- a/bacnet-stack/demo/readfile/main.c +++ b/bacnet-stack/demo/readfile/main.c @@ -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); diff --git a/bacnet-stack/demo/readfile/makefile.b32 b/bacnet-stack/demo/readfile/makefile.b32 index 759c1d2d..12591afc 100644 --- a/bacnet-stack/demo/readfile/makefile.b32 +++ b/bacnet-stack/demo/readfile/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/readprop/Makefile b/bacnet-stack/demo/readprop/Makefile index a9dc49a7..836ee012 100644 --- a/bacnet-stack/demo/readprop/Makefile +++ b/bacnet-stack/demo/readprop/Makefile @@ -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} diff --git a/bacnet-stack/demo/readprop/main.c b/bacnet-stack/demo/readprop/main.c index e7b1a5c9..1e68f0ee 100644 --- a/bacnet-stack/demo/readprop/main.c +++ b/bacnet-stack/demo/readprop/main.c @@ -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); diff --git a/bacnet-stack/demo/readprop/makefile.b32 b/bacnet-stack/demo/readprop/makefile.b32 index d1c7d2a9..83181339 100644 --- a/bacnet-stack/demo/readprop/makefile.b32 +++ b/bacnet-stack/demo/readprop/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/readpropm/Makefile b/bacnet-stack/demo/readpropm/Makefile index 9b7b955c..2d38b8f6 100644 --- a/bacnet-stack/demo/readpropm/Makefile +++ b/bacnet-stack/demo/readpropm/Makefile @@ -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} diff --git a/bacnet-stack/demo/readpropm/main.c b/bacnet-stack/demo/readpropm/main.c index b2be57c0..784ca2b2 100644 --- a/bacnet-stack/demo/readpropm/main.c +++ b/bacnet-stack/demo/readpropm/main.c @@ -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); diff --git a/bacnet-stack/demo/readpropm/makefile.b32 b/bacnet-stack/demo/readpropm/makefile.b32 index d60bdbd2..99dc89f0 100644 --- a/bacnet-stack/demo/readpropm/makefile.b32 +++ b/bacnet-stack/demo/readpropm/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/readrange/main.c b/bacnet-stack/demo/readrange/main.c index d7e68bd4..140427a6 100644 --- a/bacnet-stack/demo/readrange/main.c +++ b/bacnet-stack/demo/readrange/main.c @@ -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( diff --git a/bacnet-stack/demo/reinit/Makefile b/bacnet-stack/demo/reinit/Makefile index a9609f29..42984e9f 100644 --- a/bacnet-stack/demo/reinit/Makefile +++ b/bacnet-stack/demo/reinit/Makefile @@ -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} diff --git a/bacnet-stack/demo/reinit/main.c b/bacnet-stack/demo/reinit/main.c index cb9361b7..c07e9cf6 100644 --- a/bacnet-stack/demo/reinit/main.c +++ b/bacnet-stack/demo/reinit/main.c @@ -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); diff --git a/bacnet-stack/demo/reinit/makefile.b32 b/bacnet-stack/demo/reinit/makefile.b32 index 71ef2b53..f32dc1c8 100644 --- a/bacnet-stack/demo/reinit/makefile.b32 +++ b/bacnet-stack/demo/reinit/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/scov/Makefile b/bacnet-stack/demo/scov/Makefile index 4dcaafc4..0b5d70ba 100644 --- a/bacnet-stack/demo/scov/Makefile +++ b/bacnet-stack/demo/scov/Makefile @@ -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} diff --git a/bacnet-stack/demo/scov/main.c b/bacnet-stack/demo/scov/main.c index 96c663d8..53a88278 100644 --- a/bacnet-stack/demo/scov/main.c +++ b/bacnet-stack/demo/scov/main.c @@ -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); diff --git a/bacnet-stack/demo/scov/makefile.b32 b/bacnet-stack/demo/scov/makefile.b32 index 8e42bdb7..4107b3ef 100644 --- a/bacnet-stack/demo/scov/makefile.b32 +++ b/bacnet-stack/demo/scov/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/server/main.c b/bacnet-stack/demo/server/main.c index 9d7db810..83bf9e0a 100644 --- a/bacnet-stack/demo/server/main.c +++ b/bacnet-stack/demo/server/main.c @@ -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) { diff --git a/bacnet-stack/demo/timesync/Makefile b/bacnet-stack/demo/timesync/Makefile index ef39a83c..28ce9043 100644 --- a/bacnet-stack/demo/timesync/Makefile +++ b/bacnet-stack/demo/timesync/Makefile @@ -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} diff --git a/bacnet-stack/demo/timesync/main.c b/bacnet-stack/demo/timesync/main.c index 5b178b2d..0625c78c 100644 --- a/bacnet-stack/demo/timesync/main.c +++ b/bacnet-stack/demo/timesync/main.c @@ -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); diff --git a/bacnet-stack/demo/timesync/makefile.b32 b/bacnet-stack/demo/timesync/makefile.b32 index b53157d3..2b676438 100644 --- a/bacnet-stack/demo/timesync/makefile.b32 +++ b/bacnet-stack/demo/timesync/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/ucov/Makefile b/bacnet-stack/demo/ucov/Makefile index 395aec7a..703cd74f 100644 --- a/bacnet-stack/demo/ucov/Makefile +++ b/bacnet-stack/demo/ucov/Makefile @@ -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} diff --git a/bacnet-stack/demo/ucov/main.c b/bacnet-stack/demo/ucov/main.c index 052d9727..c2148b2a 100644 --- a/bacnet-stack/demo/ucov/main.c +++ b/bacnet-stack/demo/ucov/main.c @@ -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); diff --git a/bacnet-stack/demo/ucov/makefile.b32 b/bacnet-stack/demo/ucov/makefile.b32 index 6f416712..c590cbb0 100644 --- a/bacnet-stack/demo/ucov/makefile.b32 +++ b/bacnet-stack/demo/ucov/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/uptransfer/Makefile b/bacnet-stack/demo/uptransfer/Makefile index eb43cc87..9d3b38b1 100644 --- a/bacnet-stack/demo/uptransfer/Makefile +++ b/bacnet-stack/demo/uptransfer/Makefile @@ -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} diff --git a/bacnet-stack/demo/uptransfer/main.c b/bacnet-stack/demo/uptransfer/main.c index cedb4b4d..344dc6ab 100644 --- a/bacnet-stack/demo/uptransfer/main.c +++ b/bacnet-stack/demo/uptransfer/main.c @@ -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); diff --git a/bacnet-stack/demo/uptransfer/makefile.b32 b/bacnet-stack/demo/uptransfer/makefile.b32 index 16bec5df..a77d4123 100644 --- a/bacnet-stack/demo/uptransfer/makefile.b32 +++ b/bacnet-stack/demo/uptransfer/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/whohas/Makefile b/bacnet-stack/demo/whohas/Makefile index 51125e75..57387a3e 100644 --- a/bacnet-stack/demo/whohas/Makefile +++ b/bacnet-stack/demo/whohas/Makefile @@ -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} diff --git a/bacnet-stack/demo/whohas/main.c b/bacnet-stack/demo/whohas/main.c index 859133e2..7bb936eb 100644 --- a/bacnet-stack/demo/whohas/main.c +++ b/bacnet-stack/demo/whohas/main.c @@ -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); diff --git a/bacnet-stack/demo/whohas/makefile.b32 b/bacnet-stack/demo/whohas/makefile.b32 index a800fa12..c0f93de9 100644 --- a/bacnet-stack/demo/whohas/makefile.b32 +++ b/bacnet-stack/demo/whohas/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/whois/Makefile b/bacnet-stack/demo/whois/Makefile index 00ef02f2..2c117481 100644 --- a/bacnet-stack/demo/whois/Makefile +++ b/bacnet-stack/demo/whois/Makefile @@ -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} diff --git a/bacnet-stack/demo/whois/main.c b/bacnet-stack/demo/whois/main.c index 72f26714..77d75975 100644 --- a/bacnet-stack/demo/whois/main.c +++ b/bacnet-stack/demo/whois/main.c @@ -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 diff --git a/bacnet-stack/demo/whois/makefile.b32 b/bacnet-stack/demo/whois/makefile.b32 index d4737449..468ffda6 100644 --- a/bacnet-stack/demo/whois/makefile.b32 +++ b/bacnet-stack/demo/whois/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/whoisrouter/Makefile b/bacnet-stack/demo/whoisrouter/Makefile index 585f238a..ae264288 100644 --- a/bacnet-stack/demo/whoisrouter/Makefile +++ b/bacnet-stack/demo/whoisrouter/Makefile @@ -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} diff --git a/bacnet-stack/demo/whoisrouter/main.c b/bacnet-stack/demo/whoisrouter/main.c index a5b8249a..a3b741eb 100644 --- a/bacnet-stack/demo/whoisrouter/main.c +++ b/bacnet-stack/demo/whoisrouter/main.c @@ -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); diff --git a/bacnet-stack/demo/whoisrouter/makefile.b32 b/bacnet-stack/demo/whoisrouter/makefile.b32 index 9a45d15a..18be31d4 100644 --- a/bacnet-stack/demo/whoisrouter/makefile.b32 +++ b/bacnet-stack/demo/whoisrouter/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/writefile/Makefile b/bacnet-stack/demo/writefile/Makefile index 6d212166..f26b1fe4 100644 --- a/bacnet-stack/demo/writefile/Makefile +++ b/bacnet-stack/demo/writefile/Makefile @@ -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} diff --git a/bacnet-stack/demo/writefile/main.c b/bacnet-stack/demo/writefile/main.c index 30836d79..4cfcafeb 100644 --- a/bacnet-stack/demo/writefile/main.c +++ b/bacnet-stack/demo/writefile/main.c @@ -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); diff --git a/bacnet-stack/demo/writefile/makefile.b32 b/bacnet-stack/demo/writefile/makefile.b32 index 3a623ed9..61f92549 100644 --- a/bacnet-stack/demo/writefile/makefile.b32 +++ b/bacnet-stack/demo/writefile/makefile.b32 @@ -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) diff --git a/bacnet-stack/demo/writeprop/Makefile b/bacnet-stack/demo/writeprop/Makefile index 2667a8c4..5a9587f7 100644 --- a/bacnet-stack/demo/writeprop/Makefile +++ b/bacnet-stack/demo/writeprop/Makefile @@ -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} diff --git a/bacnet-stack/demo/writeprop/main.c b/bacnet-stack/demo/writeprop/main.c index 4a835547..61bca2b5 100644 --- a/bacnet-stack/demo/writeprop/main.c +++ b/bacnet-stack/demo/writeprop/main.c @@ -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); diff --git a/bacnet-stack/demo/writeprop/makefile.b32 b/bacnet-stack/demo/writeprop/makefile.b32 index 567b7401..2ce1d2f5 100644 --- a/bacnet-stack/demo/writeprop/makefile.b32 +++ b/bacnet-stack/demo/writeprop/makefile.b32 @@ -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) diff --git a/bacnet-stack/include/handlers.h b/bacnet-stack/include/handlers.h index 1d6a743f..6d47d4e4 100644 --- a/bacnet-stack/include/handlers.h +++ b/bacnet-stack/include/handlers.h @@ -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); diff --git a/bacnet-stack/ports/win32/main.c b/bacnet-stack/ports/win32/main.c index 61505952..24bf9333 100644 --- a/bacnet-stack/ports/win32/main.c +++ b/bacnet-stack/ports/win32/main.c @@ -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);