From 2f0bf7744a9e03f0764cd468a056948a1eadd07d Mon Sep 17 00:00:00 2001 From: skarg Date: Fri, 15 Nov 2013 20:51:38 +0000 Subject: [PATCH] Added property-list property to Lighting Output and Channel objects (untested). Fixed some compiler warnings. --- bacnet-stack/demo/object/channel.c | 31 +- bacnet-stack/demo/object/device.c | 19 +- bacnet-stack/demo/object/lo.c | 34 +- bacnet-stack/include/proplist.h | 21 +- bacnet-stack/include/rpm.h | 13 +- bacnet-stack/src/proplist.c | 503 ++++++++++++++++++++--------- 6 files changed, 408 insertions(+), 213 deletions(-) diff --git a/bacnet-stack/demo/object/channel.c b/bacnet-stack/demo/object/channel.c index 005c8661..86293824 100644 --- a/bacnet-stack/demo/object/channel.c +++ b/bacnet-stack/demo/object/channel.c @@ -42,6 +42,7 @@ #include "config.h" /* the custom stuff */ #include "wp.h" #include "handlers.h" +#include "proplist.h" #include "lighting.h" #include "device.h" #if defined (CHANNEL_LIGHTING_COMMAND) || defined (BACAPP_LIGHTING_COMMAND) @@ -74,22 +75,8 @@ struct bacnet_channel_object { struct bacnet_channel_object Channel[BACNET_CHANNELS_MAX]; -/* These three arrays are used by the ReadPropertyMultiple handler */ -static const int Properties_Required[] = { - PROP_OBJECT_IDENTIFIER, - PROP_OBJECT_NAME, - PROP_OBJECT_TYPE, - PROP_PRESENT_VALUE, - PROP_LAST_PRIORITY, - PROP_WRITE_STATUS, - PROP_STATUS_FLAGS, - PROP_OUT_OF_SERVICE, - PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES, - PROP_CHANNEL_NUMBER, - PROP_CONTROL_GROUPS, - -1 -}; - +/* These arrays are used by the ReadPropertyMultiple handler + property-list property (as of protocol-revision 14) */ static const int Properties_Optional[] = { -1 }; @@ -114,7 +101,7 @@ void Channel_Property_Lists(const int **pRequired, const int **pProprietary) { if (pRequired) - *pRequired = Properties_Required; + *pRequired = property_list_required(OBJECT_CHANNEL); if (pOptional) *pOptional = Properties_Optional; if (pProprietary) @@ -1374,6 +1361,7 @@ int Channel_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata) bool state = false; BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *pMember = NULL; uint8_t *apdu = NULL; + const int *pRequired = NULL, *pOptional = NULL, *pProprietary = NULL; if ((rpdata == NULL) || (rpdata->application_data == NULL) || (rpdata->application_data_len == 0)) { @@ -1512,6 +1500,14 @@ int Channel_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata) } } break; + case PROP_PROPERTY_LIST: + Channel_Property_Lists(&pRequired, &pOptional, &pProprietary); + apdu_len = property_list_encode( + rpdata, + pRequired, + pOptional, + pProprietary); + break; default: rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY; @@ -1521,6 +1517,7 @@ int Channel_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata) /* only array properties can have array options */ if ((apdu_len >= 0) && (rpdata->object_property != PROP_PRIORITY_ARRAY) + && (rpdata->object_property != PROP_PROPERTY_LIST) && (rpdata->array_index != BACNET_ARRAY_ALL)) { rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; diff --git a/bacnet-stack/demo/object/device.c b/bacnet-stack/demo/object/device.c index 08128bc9..d924b40c 100644 --- a/bacnet-stack/demo/object/device.c +++ b/bacnet-stack/demo/object/device.c @@ -426,21 +426,6 @@ rr_info_function Device_Objects_RR_Info( return (pObject != NULL ? pObject->Object_RR_Info : NULL); } -static unsigned property_list_count( - const int *pList) -{ - unsigned property_count = 0; - - if (pList) { - while (*pList != -1) { - property_count++; - pList++; - } - } - - return property_count; -} - /** For a given object type, returns the special property list. * This function is used for ReadPropertyMultiple calls which want * just Required, just Optional, or All properties. @@ -1143,10 +1128,10 @@ int tm_isdst Daylight Savings flag. */ #if defined(_MSC_VER) time(&tTemp); - tblock = localtime(&tTemp); + tblock = (struct tm *)localtime(&tTemp); #else if (gettimeofday(&tv, NULL) == 0) { - tblock = localtime(&tv.tv_sec); + tblock = (struct tm *)localtime((const time_t *)&tv.tv_sec); } #endif diff --git a/bacnet-stack/demo/object/lo.c b/bacnet-stack/demo/object/lo.c index d92d62b4..3f477174 100644 --- a/bacnet-stack/demo/object/lo.c +++ b/bacnet-stack/demo/object/lo.c @@ -39,6 +39,7 @@ #include "wp.h" #include "lighting.h" #include "handlers.h" +#include "proplist.h" /* me! */ #include "lo.h" @@ -72,21 +73,8 @@ struct lighting_output_object { }; struct lighting_output_object Lighting_Output[MAX_LIGHTING_OUTPUTS]; -/* These three arrays are used by the ReadPropertyMultiple handler */ -static const int Properties_Required[] = { - PROP_OBJECT_IDENTIFIER, - PROP_OBJECT_NAME, - PROP_OBJECT_TYPE, - PROP_PRESENT_VALUE, - PROP_STATUS_FLAGS, - PROP_EVENT_STATE, - PROP_OUT_OF_SERVICE, - PROP_UNITS, - PROP_PRIORITY_ARRAY, - PROP_RELINQUISH_DEFAULT, - -1 -}; - +/* These arrays are used by the ReadPropertyMultiple handler and + property-list property (as of protocol-revision 14) */ static const int Properties_Optional[] = { -1 }; @@ -112,7 +100,7 @@ void Lighting_Output_Property_Lists( const int **pProprietary) { if (pRequired) - *pRequired = Properties_Required; + *pRequired = property_list_required(OBJECT_LIGHTING_OUTPUT); if (pOptional) *pOptional = Properties_Optional; if (pProprietary) @@ -963,6 +951,7 @@ int Lighting_Output_Read_Property( unsigned i = 0; bool state = false; uint8_t *apdu = NULL; + const int *pRequired = NULL, *pOptional = NULL, *pProprietary = NULL; if ((rpdata == NULL) || (rpdata->application_data == NULL) || (rpdata->application_data_len == 0)) { @@ -1051,12 +1040,12 @@ int Lighting_Output_Read_Property( break; case PROP_PRIORITY_ARRAY: /* Array element zero is the number of elements in the array */ - if (rpdata->array_index == 0) + if (rpdata->array_index == 0) { apdu_len = encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY); /* if no index was specified, then try to encode the entire list */ /* into one packet. */ - else if (rpdata->array_index == BACNET_ARRAY_ALL) { + } else if (rpdata->array_index == BACNET_ARRAY_ALL) { for (i = 1; i <= BACNET_MAX_PRIORITY; i++) { if (Lighting_Output_Priority_Active( rpdata->object_instance, i)) { @@ -1110,6 +1099,14 @@ int Lighting_Output_Read_Property( apdu_len = encode_application_unsigned(&apdu[0], unsigned_value); break; + case PROP_PROPERTY_LIST: + Lighting_Output_Property_Lists(&pRequired, &pOptional, &pProprietary); + apdu_len = property_list_encode( + rpdata, + pRequired, + pOptional, + pProprietary); + break; default: rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY; @@ -1118,6 +1115,7 @@ int Lighting_Output_Read_Property( } /* only array properties can have array options */ if ((apdu_len >= 0) && (rpdata->object_property != PROP_PRIORITY_ARRAY) && + (rpdata->object_property != PROP_PROPERTY_LIST) && (rpdata->array_index != BACNET_ARRAY_ALL)) { rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; diff --git a/bacnet-stack/include/proplist.h b/bacnet-stack/include/proplist.h index 2ef6e933..61cf1c4b 100644 --- a/bacnet-stack/include/proplist.h +++ b/bacnet-stack/include/proplist.h @@ -28,10 +28,20 @@ #include #include "bacdef.h" #include "bacenum.h" -#include "rpm.h" +#include "rp.h" /** @file proplist.h Library of all required and optional object properties */ +struct property_list_t { + const int *pList; + unsigned count; +}; + +struct special_property_list_t { + struct property_list_t Required; + struct property_list_t Optional; + struct property_list_t Proprietary; +}; #ifdef __cplusplus extern "C" { @@ -39,6 +49,10 @@ extern "C" { unsigned property_list_count( const int *pList); + const int * property_list_optional( + BACNET_OBJECT_TYPE object_type); + const int * property_list_required( + BACNET_OBJECT_TYPE object_type); void property_list_special( BACNET_OBJECT_TYPE object_type, struct special_property_list_t *pPropertyList); @@ -49,6 +63,11 @@ extern "C" { unsigned property_list_special_count( BACNET_OBJECT_TYPE object_type, BACNET_PROPERTY_ID special_property); + int property_list_encode( + BACNET_READ_PROPERTY_DATA * rpdata, + const int *pListRequired, + const int *pListOptional, + const int *pListProprietary); #ifdef __cplusplus } diff --git a/bacnet-stack/include/rpm.h b/bacnet-stack/include/rpm.h index 6e37c5fc..6b09bf7b 100644 --- a/bacnet-stack/include/rpm.h +++ b/bacnet-stack/include/rpm.h @@ -29,7 +29,7 @@ #include "bacenum.h" #include "bacdef.h" #include "bacapp.h" - +#include "proplist.h" /* * Bundle together commonly used data items for convenience when calling * rpm helper functions. @@ -69,17 +69,6 @@ typedef void ( const int **pOptional, const int **pProprietary); -struct property_list_t { - const int *pList; - unsigned count; -}; - -struct special_property_list_t { - struct property_list_t Required; - struct property_list_t Optional; - struct property_list_t Proprietary; -}; - typedef void ( *rpm_object_property_lists_function) ( BACNET_OBJECT_TYPE object_type, diff --git a/bacnet-stack/src/proplist.c b/bacnet-stack/src/proplist.c index 409b5c50..8a279ae1 100644 --- a/bacnet-stack/src/proplist.c +++ b/bacnet-stack/src/proplist.c @@ -34,7 +34,10 @@ #include #include "bacenum.h" #include "bacdef.h" +#include "bacdcode.h" +#include "bacenum.h" #include "rpm.h" +#include "rp.h" #include "proplist.h" /** @file proplist.c List of Required and Optional object properties */ @@ -754,6 +757,189 @@ unsigned property_list_count( return property_count; } +/** + * Function that returns the list of all Optional properties + * of known standard objects. + * + * @param object_type - enumerated BACNET_OBJECT_TYPE + * @return returns a pointer to a '-1' terminated array of + * type 'int' that contain BACnet object properties for the given object + * type. + */ +const int * property_list_optional( + BACNET_OBJECT_TYPE object_type) +{ + const int * pList = NULL; + + switch (object_type) { + case OBJECT_DEVICE: + pList = Device_Properties_Optional; + break; + case OBJECT_ACCUMULATOR: + pList = Accumulator_Properties_Optional; + break; + case OBJECT_ANALOG_INPUT: + pList = Analog_Input_Properties_Optional; + break; + case OBJECT_ANALOG_OUTPUT: + pList = Analog_Output_Properties_Optional; + break; + case OBJECT_ANALOG_VALUE: + pList = Analog_Value_Properties_Optional; + break; + case OBJECT_AVERAGING: + pList = Averaging_Properties_Optional; + break; + case OBJECT_BINARY_INPUT: + pList = Binary_Input_Properties_Optional; + break; + case OBJECT_BINARY_OUTPUT: + pList = Binary_Output_Properties_Optional; + break; + case OBJECT_BINARY_VALUE: + pList = Binary_Value_Properties_Optional; + break; + case OBJECT_CALENDAR: + pList = Calendar_Properties_Optional; + break; + case OBJECT_CHANNEL: + pList = Channel_Properties_Optional; + break; + case OBJECT_COMMAND: + pList = Command_Properties_Optional; + break; + case OBJECT_CHARACTERSTRING_VALUE: + pList = + CharacterString_Value_Properties_Optional; + break; + case OBJECT_LOAD_CONTROL: + pList = Load_Control_Properties_Optional; + break; + case OBJECT_LIFE_SAFETY_POINT: + pList = + Life_Safety_Point_Properties_Optional; + break; + case OBJECT_MULTI_STATE_INPUT: + pList = + Multistate_Input_Properties_Optional; + break; + case OBJECT_MULTI_STATE_OUTPUT: + pList = + Multistate_Output_Properties_Optional; + break; + case OBJECT_MULTI_STATE_VALUE: + pList = + Multistate_Value_Properties_Optional; + break; + case OBJECT_NOTIFICATION_CLASS: + pList = + Notification_Class_Properties_Optional; + break; + case OBJECT_TRENDLOG: + pList = Trend_Log_Properties_Optional; + break; + case OBJECT_FILE: + pList = File_Properties_Optional; + break; + default: + break; + } + + return pList; +} + +/** + * Function that returns the list of Required properties + * of known standard objects. + * + * @param object_type - enumerated BACNET_OBJECT_TYPE + * @return returns a pointer to a '-1' terminated array of + * type 'int' that contain BACnet object properties for the given object + * type. + */ +const int * property_list_required( + BACNET_OBJECT_TYPE object_type) +{ + const int * pList = NULL; + + switch (object_type) { + case OBJECT_DEVICE: + pList = Device_Properties_Required; + break; + case OBJECT_ACCUMULATOR: + pList = Accumulator_Properties_Required; + break; + case OBJECT_ANALOG_INPUT: + pList = Analog_Input_Properties_Required; + break; + case OBJECT_ANALOG_OUTPUT: + pList = Analog_Output_Properties_Required; + break; + case OBJECT_ANALOG_VALUE: + pList = Analog_Value_Properties_Required; + break; + case OBJECT_AVERAGING: + pList = Averaging_Properties_Required; + break; + case OBJECT_BINARY_INPUT: + pList = Binary_Input_Properties_Required; + break; + case OBJECT_BINARY_OUTPUT: + pList = Binary_Output_Properties_Required; + break; + case OBJECT_BINARY_VALUE: + pList = Binary_Value_Properties_Required; + break; + case OBJECT_CALENDAR: + pList = Calendar_Properties_Required; + break; + case OBJECT_CHANNEL: + pList = Channel_Properties_Required; + break; + case OBJECT_COMMAND: + pList = Command_Properties_Required; + break; + case OBJECT_CHARACTERSTRING_VALUE: + pList = + CharacterString_Value_Properties_Required; + break; + case OBJECT_LOAD_CONTROL: + pList = Load_Control_Properties_Required; + break; + case OBJECT_LIFE_SAFETY_POINT: + pList = + Life_Safety_Point_Properties_Required; + break; + case OBJECT_MULTI_STATE_INPUT: + pList = + Multistate_Input_Properties_Required; + break; + case OBJECT_MULTI_STATE_OUTPUT: + pList = + Multistate_Output_Properties_Required; + break; + case OBJECT_MULTI_STATE_VALUE: + pList = + Multistate_Value_Properties_Required; + break; + case OBJECT_NOTIFICATION_CLASS: + pList = + Notification_Class_Properties_Required; + break; + case OBJECT_TRENDLOG: + pList = Trend_Log_Properties_Required; + break; + case OBJECT_FILE: + pList = File_Properties_Required; + break; + default: + pList = Default_Properties_Required; + break; + } + + return pList; +} + /** * Function that returns the list of Required or Optional properties * of known standard objects. @@ -770,158 +956,14 @@ void property_list_special( if (pPropertyList == NULL) { return; } + pPropertyList->Required.pList = property_list_required(object_type); + pPropertyList->Optional.pList = property_list_optional(object_type); pPropertyList->Proprietary.pList = NULL; - switch (object_type) { - case OBJECT_DEVICE: - pPropertyList->Required.pList = Device_Properties_Required; - pPropertyList->Optional.pList = Device_Properties_Optional; - break; - break; - case OBJECT_ACCUMULATOR: - pPropertyList->Required.pList = Accumulator_Properties_Required; - pPropertyList->Optional.pList = Accumulator_Properties_Optional; - break; - case OBJECT_ANALOG_INPUT: - pPropertyList->Required.pList = Analog_Input_Properties_Required; - pPropertyList->Optional.pList = Analog_Input_Properties_Optional; - break; - case OBJECT_ANALOG_OUTPUT: - pPropertyList->Required.pList = Analog_Output_Properties_Required; - pPropertyList->Optional.pList = Analog_Output_Properties_Optional; - break; - case OBJECT_ANALOG_VALUE: - pPropertyList->Required.pList = Analog_Value_Properties_Required; - pPropertyList->Optional.pList = Analog_Value_Properties_Optional; - break; - case OBJECT_AVERAGING: - pPropertyList->Required.pList = Averaging_Properties_Required; - pPropertyList->Optional.pList = Averaging_Properties_Optional; - break; - case OBJECT_BINARY_INPUT: - pPropertyList->Required.pList = Binary_Input_Properties_Required; - pPropertyList->Optional.pList = Binary_Input_Properties_Optional; - break; - case OBJECT_BINARY_OUTPUT: - pPropertyList->Required.pList = Binary_Output_Properties_Required; - pPropertyList->Optional.pList = Binary_Output_Properties_Optional; - break; - case OBJECT_BINARY_VALUE: - pPropertyList->Required.pList = Binary_Value_Properties_Required; - pPropertyList->Optional.pList = Binary_Value_Properties_Optional; - break; - case OBJECT_CALENDAR: - pPropertyList->Required.pList = Calendar_Properties_Required; - pPropertyList->Optional.pList = Calendar_Properties_Optional; - break; - case OBJECT_CHANNEL: - pPropertyList->Required.pList = Channel_Properties_Required; - pPropertyList->Optional.pList = Channel_Properties_Optional; - break; - case OBJECT_COMMAND: - pPropertyList->Required.pList = Command_Properties_Required; - pPropertyList->Optional.pList = Command_Properties_Optional; - break; - case OBJECT_CHARACTERSTRING_VALUE: - pPropertyList->Required.pList = - CharacterString_Value_Properties_Required; - pPropertyList->Optional.pList = - CharacterString_Value_Properties_Optional; - break; - case OBJECT_LOAD_CONTROL: - pPropertyList->Required.pList = Load_Control_Properties_Required; - pPropertyList->Optional.pList = Load_Control_Properties_Optional; - break; - case OBJECT_LIFE_SAFETY_POINT: - pPropertyList->Required.pList = - Life_Safety_Point_Properties_Required; - pPropertyList->Optional.pList = - Life_Safety_Point_Properties_Optional; - break; - case OBJECT_MULTI_STATE_INPUT: - pPropertyList->Required.pList = - Multistate_Input_Properties_Required; - pPropertyList->Optional.pList = - Multistate_Input_Properties_Optional; - break; - case OBJECT_MULTI_STATE_OUTPUT: - pPropertyList->Required.pList = - Multistate_Output_Properties_Required; - pPropertyList->Optional.pList = - Multistate_Output_Properties_Optional; - break; - case OBJECT_MULTI_STATE_VALUE: - pPropertyList->Required.pList = - Multistate_Value_Properties_Required; - pPropertyList->Optional.pList = - Multistate_Value_Properties_Optional; - break; - case OBJECT_NOTIFICATION_CLASS: - pPropertyList->Required.pList = - Notification_Class_Properties_Required; - pPropertyList->Optional.pList = - Notification_Class_Properties_Optional; - break; - case OBJECT_TRENDLOG: - pPropertyList->Required.pList = Trend_Log_Properties_Required; - pPropertyList->Optional.pList = Trend_Log_Properties_Optional; - break; - case OBJECT_FILE: - pPropertyList->Required.pList = File_Properties_Required; - pPropertyList->Optional.pList = File_Properties_Optional; - break; - case OBJECT_EVENT_ENROLLMENT: - case OBJECT_GROUP: - case OBJECT_LOOP: - case OBJECT_PROGRAM: - case OBJECT_SCHEDULE: - case OBJECT_LIFE_SAFETY_ZONE: - case OBJECT_PULSE_CONVERTER: - case OBJECT_EVENT_LOG: - case OBJECT_GLOBAL_GROUP: - case OBJECT_TREND_LOG_MULTIPLE: - case OBJECT_STRUCTURED_VIEW: - case OBJECT_ACCESS_DOOR: - case OBJECT_LIGHTING_OUTPUT: - case OBJECT_ACCESS_CREDENTIAL: - case OBJECT_ACCESS_POINT: - case OBJECT_ACCESS_RIGHTS: - case OBJECT_ACCESS_USER: - case OBJECT_ACCESS_ZONE: - case OBJECT_CREDENTIAL_DATA_INPUT: - case OBJECT_NETWORK_SECURITY: - case OBJECT_BITSTRING_VALUE: - case OBJECT_DATE_PATTERN_VALUE: - case OBJECT_DATE_VALUE: - case OBJECT_DATETIME_PATTERN_VALUE: - case OBJECT_DATETIME_VALUE: - case OBJECT_INTEGER_VALUE: - case OBJECT_LARGE_ANALOG_VALUE: - case OBJECT_OCTETSTRING_VALUE: - case OBJECT_POSITIVE_INTEGER_VALUE: - case OBJECT_TIME_PATTERN_VALUE: - case OBJECT_TIME_VALUE: - case OBJECT_NOTIFICATION_FORWARDER: - case OBJECT_ALERT_ENROLLMENT: - pPropertyList->Required.pList = Default_Properties_Required; - pPropertyList->Optional.pList = NULL; - pPropertyList->Proprietary.pList = NULL; - break; - default: - /* proprietary objects */ - pPropertyList->Required.pList = Default_Properties_Required; - pPropertyList->Optional.pList = NULL; - pPropertyList->Proprietary.pList = NULL; - break; - } /* Fetch the counts if available otherwise zero them */ pPropertyList->Required.count = - pPropertyList->Required.pList == - NULL ? 0 : property_list_count(pPropertyList->Required.pList); - + property_list_count(pPropertyList->Required.pList); pPropertyList->Optional.count = - pPropertyList->Optional.pList == - NULL ? 0 : property_list_count(pPropertyList->Optional.pList); - + property_list_count(pPropertyList->Optional.pList); pPropertyList->Proprietary.count = 0; return; @@ -994,6 +1036,171 @@ unsigned property_list_special_count( return count; } +/** + * ReadProperty handler for this property. For the given ReadProperty + * data, the application_data is loaded or the error flags are set. + * + * @param rpdata - ReadProperty data, including requested data and + * data for the reply, or error response. + * + * @return number of APDU bytes in the response, or + * BACNET_STATUS_ERROR on error. + */ +int property_list_encode( + BACNET_READ_PROPERTY_DATA * rpdata, + const int *pListRequired, + const int *pListOptional, + const int *pListProprietary) +{ + int apdu_len = 0; /* return value */ + uint8_t *apdu = NULL; + int max_apdu_len = 0; + unsigned count = 0; + unsigned required_count = 0; + unsigned optional_count = 0; + unsigned proprietary_count = 0; + int len = 0; + unsigned i = 0; /* loop index */ + + required_count = property_list_count(pListRequired); + if (required_count >= 3) { + /* less the 3 always required properties */ + count -= 3; + } else { + count = 0; + } + optional_count = property_list_count(pListOptional); + proprietary_count = property_list_count(pListProprietary); + /* total of all counts */ + count = required_count + optional_count + proprietary_count; + if ((rpdata == NULL) || (rpdata->application_data == NULL) || + (rpdata->application_data_len == 0)) { + return 0; + } + apdu = rpdata->application_data; + max_apdu_len = rpdata->application_data_len; + switch (rpdata->object_property) { + case PROP_PROPERTY_LIST: + if (rpdata->array_index == 0) { + /* Array element zero is the number of elements in the array */ + apdu_len = + encode_application_unsigned(&apdu[0], count); + } else if (rpdata->array_index == BACNET_ARRAY_ALL) { + /* if no index was specified, then try to encode the entire list */ + /* into one packet. */ + if (required_count > 3) { + for (i = 0; i < required_count; i++) { + if ((pListRequired[i] == PROP_OBJECT_TYPE) || + (pListRequired[i] == PROP_OBJECT_IDENTIFIER) || + (pListRequired[i] == PROP_OBJECT_NAME)) { + continue; + } else { + len = + encode_application_enumerated(&apdu[apdu_len], + pListRequired[i]); + } + /* add it if we have room */ + if ((apdu_len + len) < max_apdu_len) { + apdu_len += len; + } else { + rpdata->error_class = ERROR_CLASS_SERVICES; + rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT; + apdu_len = BACNET_STATUS_ERROR; + break; + } + } + } + if (optional_count) { + for (i = 0; i < optional_count; i++) { + len = + encode_application_enumerated(&apdu[apdu_len], + pListOptional[i]); + /* add it if we have room */ + if ((apdu_len + len) < max_apdu_len) { + apdu_len += len; + } else { + rpdata->error_class = ERROR_CLASS_SERVICES; + rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT; + apdu_len = BACNET_STATUS_ERROR; + break; + } + } + } + if (proprietary_count) { + for (i = 0; i < proprietary_count; i++) { + len = + encode_application_enumerated(&apdu[apdu_len], + pListProprietary[i]); + /* add it if we have room */ + if ((apdu_len + len) < max_apdu_len) { + apdu_len += len; + } else { + rpdata->error_class = ERROR_CLASS_SERVICES; + rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT; + apdu_len = BACNET_STATUS_ERROR; + break; + } + } + } + } else { + if (rpdata->array_index <= count) { + count = 0; + if (required_count > 3) { + for (i = 0; i < required_count; i++) { + if ((pListRequired[i] == PROP_OBJECT_TYPE) || + (pListRequired[i] == PROP_OBJECT_IDENTIFIER) || + (pListRequired[i] == PROP_OBJECT_NAME)) { + continue; + } else { + count++; + } + if (count == rpdata->array_index) { + apdu_len = encode_application_enumerated( + &apdu[apdu_len], + pListRequired[i]); + break; + } + } + } + if ((apdu_len == 0) && (optional_count > 0)) { + for (i = 0; i < optional_count; i++) { + count++; + if (count == rpdata->array_index) { + apdu_len = encode_application_enumerated( + &apdu[apdu_len], + pListOptional[i]); + break; + } + } + } + if ((apdu_len == 0) && (proprietary_count > 0)) { + for (i = 0; i < proprietary_count; i++) { + count++; + if (count == rpdata->array_index) { + apdu_len = encode_application_enumerated( + &apdu[apdu_len], + pListProprietary[i]); + break; + } + } + } + } else { + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; + apdu_len = BACNET_STATUS_ERROR; + } + } + break; + default: + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY; + apdu_len = BACNET_STATUS_ERROR; + break; + } + + return apdu_len; +} + #ifdef TEST #include #include