diff --git a/CMakeLists.txt b/CMakeLists.txt index 1247a0dc..6a644300 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,11 @@ option( "enable property lists" ON) +option( + BACNET_PROPERTY_ARRAY_LISTS + "enable property array lists" + ON) + option( BACNET_BUILD_PIFACE_APP "compile the piface app" @@ -531,7 +536,8 @@ target_compile_definitions( $<$:BACDL_MSTP> $<$:BACDL_ETHERNET> $<$:BACDL_NONE> - $<$:BACNET_PROPERTY_LISTS> + $<$:BACNET_PROPERTY_LISTS=1> + $<$:BACNET_PROPERTY_ARRAY_LISTS=1> $<$:BAC_ROUTING> $<$>:BACNET_STACK_STATIC_DEFINE> PRIVATE diff --git a/apps/Makefile b/apps/Makefile index 524c411e..12da99ec 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -174,6 +174,7 @@ BACNET_DEFINES += -DBACFILE BACNET_DEFINES += -DINTRINSIC_REPORTING BACNET_DEFINES += -DBACNET_TIME_MASTER BACNET_DEFINES += -DBACNET_PROPERTY_LISTS=1 +BACNET_DEFINES += -DBACNET_PROPERTY_ARRAY_LISTS=1 BACNET_DEFINES += -DBACNET_PROTOCOL_REVISION=24 # put all the flags together diff --git a/src/bacnet/basic/object/structured_view.c b/src/bacnet/basic/object/structured_view.c index b4112a6d..f37ca217 100644 --- a/src/bacnet/basic/object/structured_view.c +++ b/src/bacnet/basic/object/structured_view.c @@ -27,6 +27,7 @@ #include "bacnet/npdu.h" #include "bacnet/abort.h" #include "bacnet/proplist.h" +#include "bacnet/property.h" #include "bacnet/reject.h" #include "bacnet/rp.h" #include "bacnet/basic/services.h" @@ -66,14 +67,6 @@ static const int Properties_Optional[] = { static const int Properties_Proprietary[] = { -1 }; - -/* standard properties that are arrays for this object, - but not necessary supported in this object */ -static const int BACnetARRAY_Properties[] = { - PROP_SUBORDINATE_LIST, PROP_SUBORDINATE_ANNOTATIONS, PROP_SUBORDINATE_TAGS, - PROP_SUBORDINATE_NODE_TYPES, PROP_SUBORDINATE_RELATIONSHIPS, PROP_TAGS, - -1 -}; /* clang-format on */ /** @@ -633,16 +626,6 @@ int Structured_View_Subordinate_Relationships_Element_Encode( return apdu_len; } -/** - * @brief Determine if the object property is a BACnetARRAY property - * @param object_property - object-property to be checked - * @return true if the property is a BACnetARRAY property - */ -static bool BACnetARRAY_Property(int object_property) -{ - return property_list_member(BACnetARRAY_Properties, object_property); -} - /** * ReadProperty handler for this object. For the given ReadProperty * data, the application_data is loaded or the error flags are set. @@ -660,12 +643,12 @@ int Structured_View_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) uint32_t count = 0; uint8_t *apdu = NULL; uint16_t apdu_max = 0; + bool is_array = false; if ((rpdata == NULL) || (rpdata->application_data == NULL) || (rpdata->application_data_len == 0)) { return 0; } - apdu = rpdata->application_data; apdu_max = rpdata->application_data_len; switch (rpdata->object_property) { @@ -775,7 +758,9 @@ int Structured_View_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) break; } /* only array properties can have array options */ - if ((apdu_len >= 0) && (!BACnetARRAY_Property(rpdata->object_property)) && + is_array = property_list_bacnet_array_member( + rpdata->object_type, rpdata->object_property); + if ((apdu_len >= 0) && (!is_array) && (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/src/bacnet/basic/object/time_value.c b/src/bacnet/basic/object/time_value.c index 07477029..b4831093 100644 --- a/src/bacnet/basic/object/time_value.c +++ b/src/bacnet/basic/object/time_value.c @@ -63,9 +63,10 @@ static const int Time_Value_Properties_Proprietary[] = { -1 }; /* standard properties that are arrays for this object, but not necessary supported in this object */ -static const int BACnetARRAY_Properties[] = { PROP_EVENT_TIME_STAMPS, - PROP_EVENT_MESSAGE_TEXTS, PROP_EVENT_MESSAGE_TEXTS_CONFIG, - PROP_VALUE_SOURCE_ARRAY, PROP_COMMAND_TIME_ARRAY, PROP_TAGS, -1 }; +static const int BACnetARRAY_Properties[] = { + PROP_PRIORITY_ARRAY, PROP_EVENT_TIME_STAMPS, PROP_EVENT_MESSAGE_TEXTS, + PROP_EVENT_MESSAGE_TEXTS_CONFIG, PROP_VALUE_SOURCE_ARRAY, + PROP_COMMAND_TIME_ARRAY, PROP_TAGS, -1 }; /** * Returns the list of required, optional, and proprietary properties. diff --git a/src/bacnet/property.c b/src/bacnet/property.c index 22929a56..12ab0aad 100644 --- a/src/bacnet/property.c +++ b/src/bacnet/property.c @@ -1,36 +1,14 @@ -/*####COPYRIGHTBEGIN#### - ------------------------------------------- - Copyright (C) 2012 Steve Karg - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to: - The Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA. - - As a special exception, if other files instantiate templates or - use macros or inline functions from this file, or you compile - this file and link it with other works to produce a work based - on this file, this file does not by itself cause the resulting - work to be covered by the GNU General Public License. However - the source code for this file must still be made available in - accordance with section (3) of the GNU General Public License. - - This exception does not invalidate any other reasons why a work - based on this file might be covered by the GNU General Public - License. - ------------------------------------------- -####COPYRIGHTEND####*/ +/** + * @file + * @brief Static sets of BACnet Property members for each object type + * @author Steve Karg + * @date 2012 + * @section LICENSE + * + * Copyright (C) 2012 Steve Karg + * + * SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 + */ #include /* BACnet Stack defines - first */ #include "bacnet/bacdef.h" @@ -45,6 +23,10 @@ #define BACNET_PROPERTY_LISTS 0 #endif +#ifndef BACNET_PROPERTY_ARRAY_LISTS +#define BACNET_PROPERTY_ARRAY_LISTS 0 +#endif + #if BACNET_PROPERTY_LISTS /** @file property.c List of Required and Optional object properties */ /* note: the PROP_PROPERTY_LIST is NOT included in these lists, on purpose */ @@ -416,6 +398,19 @@ static const int Color_Properties_Optional[] = { PROP_RELIABILITY, PROP_AUDITABLE_OPERATIONS, PROP_TAGS, PROP_PROFILE_LOCATION, PROP_PROFILE_NAME, -1 }; +static const int Color_Temperature_Properties_Required[] = { + PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE, + PROP_PRESENT_VALUE, PROP_TRACKING_VALUE, PROP_COLOR_COMMAND, + PROP_IN_PROGRESS, PROP_DEFAULT_COLOR_TEMPERATURE, PROP_DEFAULT_FADE_TIME, + PROP_DEFAULT_RAMP_RATE, PROP_DEFAULT_STEP_INCREMENT, -1 +}; + +static const int Color_Temperature_Properties_Optional[] = { + PROP_DESCRIPTION, PROP_MIN_PRES_VALUE, PROP_MAX_PRES_VALUE, + PROP_TRANSITION, PROP_VALUE_SOURCE, PROP_AUDIT_LEVEL, + PROP_AUDITABLE_OPERATIONS, PROP_TAGS, PROP_PROFILE_LOCATION, + PROP_PROFILE_NAME, -1 }; + static const int Credential_Data_Input_Properties_Required[] = { PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, PROP_RELIABILITY, @@ -1166,6 +1161,9 @@ const int *property_list_optional(BACNET_OBJECT_TYPE object_type) case OBJECT_COLOR: pList = Color_Properties_Optional; break; + case OBJECT_COLOR_TEMPERATURE: + pList = Color_Temperature_Properties_Optional; + break; case OBJECT_CREDENTIAL_DATA_INPUT: pList = Credential_Data_Input_Properties_Optional; break; @@ -1374,6 +1372,9 @@ const int *property_list_required(BACNET_OBJECT_TYPE object_type) case OBJECT_COLOR: pList = Color_Properties_Required; break; + case OBJECT_COLOR_TEMPERATURE: + pList = Color_Temperature_Properties_Required; + break; case OBJECT_CREDENTIAL_DATA_INPUT: pList = Credential_Data_Input_Properties_Required; break; @@ -1595,3 +1596,72 @@ unsigned property_list_special_count( return count; } #endif + +#if BACNET_PROPERTY_ARRAY_LISTS +/* standard properties that are arrays + but not necessary supported in every object */ + +/* clang format off */ +static const int Properties_BACnetARRAY[] = { + PROP_AUTHENTICATION_FACTORS, PROP_ASSIGNED_ACCESS_RIGHTS, + PROP_PRIORITY_ARRAY, PROP_VALUE_SOURCE_ARRAY, PROP_COMMAND_TIME_ARRAY, + PROP_ALARM_VALUES, PROP_FAULT_VALUES, + PROP_EVENT_TIME_STAMPS, PROP_EVENT_MESSAGE_TEXTS, + PROP_EVENT_MESSAGE_TEXTS_CONFIG, + PROP_SUPPORTED_FORMATS, PROP_SUPPORTED_FORMAT_CLASSES, + PROP_SUBORDINATE_LIST, PROP_SUBORDINATE_ANNOTATIONS, PROP_SUBORDINATE_TAGS, + PROP_SUBORDINATE_NODE_TYPES, PROP_SUBORDINATE_RELATIONSHIPS, + PROP_GROUP_MEMBERS, PROP_GROUP_MEMBER_NAMES, + PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES, PROP_EXECUTION_DELAY, + PROP_CONTROL_GROUPS, PROP_BIT_TEXT, PROP_PORT_FILTER, + PROP_NOTIFICATION_CLASS, PROP_STATE_CHANGE_VALUES, + PROP_LINK_SPEEDS, PROP_IP_DNS_SERVER, PROP_IPV6_DNS_SERVER, + PROP_FLOOR_TEXT, PROP_CAR_DOOR_TEXT, PROP_ASSIGNED_LANDING_CALLS, + PROP_MAKING_CAR_CALL, PROP_REGISTERED_CAR_CALL, PROP_CAR_DOOR_STATUS, + PROP_CAR_DOOR_COMMAND, PROP_LANDING_DOOR_STATUS, + PROP_STAGES, PROP_STAGE_NAMES, PROP_TARGET_REFERENCES, + PROP_MONITORED_OBJECTS, PROP_TAGS, -1 +}; +/* clang format on */ + +/** + * 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_bacnet_array(void) +{ + return Properties_BACnetARRAY; +} + +/** + * @brief Determine if the object property is a BACnetARRAY property + * @param object_type - object-type to be checked + * @param object_property - object-property to be checked + * @return true if the property is a BACnetARRAY property + */ +bool property_list_bacnet_array_member( + BACNET_OBJECT_TYPE object_type, + BACNET_PROPERTY_ID object_property) +{ + switch (object_type) { + case OBJECT_GLOBAL_GROUP: + switch (object_property) { + case PROP_PRESENT_VALUE: + /* special - the only present-value that is an array! */ + return true; + default: + break; + } + break; + default: + break; + } + + return property_list_member(Properties_BACnetARRAY, object_property); +} +#endif diff --git a/src/bacnet/property.h b/src/bacnet/property.h index 17682568..7e55f806 100644 --- a/src/bacnet/property.h +++ b/src/bacnet/property.h @@ -1,28 +1,16 @@ -/************************************************************************** -* -* Copyright (C) 2012 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. -*********************************************************************/ -#ifndef PROPERTY_H -#define PROPERTY_H +/** + * @file + * @brief Static sets of BACnet Property members for each object type + * @author Steve Karg + * @date 2012 + * @section LICENSE + * + * Copyright (C) 2012 Steve Karg + * + * SPDX-License-Identifier: MIT + */ +#ifndef BACNET_PROPERTY_H +#define BACNET_PROPERTY_H #include #include @@ -58,6 +46,14 @@ extern "C" { BACNET_OBJECT_TYPE object_type, BACNET_PROPERTY_ID special_property); + BACNET_STACK_EXPORT + const int *property_list_bacnet_array( + void); + BACNET_STACK_EXPORT + bool property_list_bacnet_array_member( + BACNET_OBJECT_TYPE object_type, + BACNET_PROPERTY_ID object_property); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/test/bacnet/basic/object/device/CMakeLists.txt b/test/bacnet/basic/object/device/CMakeLists.txt index b4535ded..0cdbc537 100644 --- a/test/bacnet/basic/object/device/CMakeLists.txt +++ b/test/bacnet/basic/object/device/CMakeLists.txt @@ -23,6 +23,7 @@ set(ZTST_DIR "${TST_DIR}/ztest/src") add_compile_definitions( BIG_ENDIAN=0 CONFIG_ZTEST=1 + BACNET_PROPERTY_ARRAY_LISTS=1 ) include_directories( @@ -95,6 +96,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/memcopy.c ${SRC_DIR}/bacnet/npdu.c ${SRC_DIR}/bacnet/proplist.c + ${SRC_DIR}/bacnet/property.c ${SRC_DIR}/bacnet/reject.c ${SRC_DIR}/bacnet/timestamp.c ${SRC_DIR}/bacnet/wp.c diff --git a/test/bacnet/basic/object/structured_view/CMakeLists.txt b/test/bacnet/basic/object/structured_view/CMakeLists.txt index 96712101..b39c76da 100644 --- a/test/bacnet/basic/object/structured_view/CMakeLists.txt +++ b/test/bacnet/basic/object/structured_view/CMakeLists.txt @@ -23,6 +23,7 @@ set(ZTST_DIR "${TST_DIR}/ztest/src") add_compile_definitions( BIG_ENDIAN=0 CONFIG_ZTEST=1 + BACNET_PROPERTY_ARRAY_LISTS=1 ) include_directories( @@ -51,6 +52,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/hostnport.c ${SRC_DIR}/bacnet/lighting.c ${SRC_DIR}/bacnet/proplist.c + ${SRC_DIR}/bacnet/property.c ${SRC_DIR}/bacnet/timestamp.c ${SRC_DIR}/bacnet/wp.c ${SRC_DIR}/bacnet/weeklyschedule.c diff --git a/test/bacnet/property/CMakeLists.txt b/test/bacnet/property/CMakeLists.txt index 3938e68f..284018bc 100644 --- a/test/bacnet/property/CMakeLists.txt +++ b/test/bacnet/property/CMakeLists.txt @@ -24,6 +24,7 @@ add_compile_definitions( BIG_ENDIAN=0 CONFIG_ZTEST=1 BACNET_PROPERTY_LISTS=1 + BACNET_PROPERTY_ARRAY_LISTS=1 ) include_directories( diff --git a/test/bacnet/property/src/main.c b/test/bacnet/property/src/main.c index 542927aa..e22e8c26 100644 --- a/test/bacnet/property/src/main.c +++ b/test/bacnet/property/src/main.c @@ -1,13 +1,11 @@ -/* - * Copyright (c) 2020 Legrand North America, LLC. +/** + * @file + * @brief Unit test for BACnet property special lists + * @author Steve Karg + * @date 2012 * * SPDX-License-Identifier: MIT */ - -/* @file - * @brief test BACnet integer encode/decode APIs - */ - #include #include @@ -30,6 +28,7 @@ void testPropList(void) BACNET_PROPERTY_ID property = MAX_BACNET_PROPERTY_ID; unsigned object_id = 0, object_name = 0, object_type = 0; struct special_property_list_t property_list = { 0 }; + bool status = false; for (i = 0; i < OBJECT_PROPRIETARY_MIN; i++) { count = property_list_special_count((BACNET_OBJECT_TYPE)i, PROP_ALL); @@ -68,7 +67,24 @@ void testPropList(void) property_list.Required.pList, PROP_OBJECT_NAME), NULL); } + /* property is a BACnetARRAY */ + for (i = 0; i < OBJECT_PROPRIETARY_MIN; i++) { + object_type = i; + status = + property_list_bacnet_array_member(object_type, PROP_PRESENT_VALUE); + if (object_type == OBJECT_GLOBAL_GROUP) { + zassert_true(status, NULL); + } else { + zassert_false(status, NULL); + } + status = + property_list_bacnet_array_member(object_type, PROP_PRIORITY_ARRAY); + zassert_true(status, NULL); + } + count = property_list_count(property_list_bacnet_array()); + zassert_true(count > 0, NULL); } + /** * @} */ diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 90f0b330..5364f17e 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -460,6 +460,7 @@ zephyr_library_compile_definitions( $<$:BACDL_NONE> $<$:BACNET_BASIC_OBJECTS> $<$:BACNET_PROPERTY_LISTS=1> + $<$:BACNET_PROPERTY_ARRAY_LISTS=1> $<$:BACNET_ROUTING> $<$:BACAPP_PRINT_ENABLED=1> $<$:BACAPP_SNPRINTF_ENABLED=1> @@ -494,6 +495,7 @@ target_compile_definitions( $<$:BACDL_ETHERNET> $<$:BACDL_NONE> $<$:BACNET_PROPERTY_LISTS=1> + $<$:BACNET_PROPERTY_ARRAY_LISTS=1> $<$:BACNET_ROUTING> $<$:BACAPP_PRINT_ENABLED=1> $<$:BACAPP_SNPRINTF_ENABLED=1> diff --git a/zephyr/Kconfig b/zephyr/Kconfig index a3ea4a0e..bd05446e 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -44,6 +44,11 @@ config BACNET_PROPERTY_LISTS help Enable BACnet Property Lists +config BACNET_PROPERTY_ARRAY_LISTS + bool "BACnetARRAY Property Lists" + help + Enable BACnetARRAY Property Lists + config BACDL_ETHERNET bool "BACnet Ethernet datalink" help diff --git a/zephyr/tests/bacnet/property/CMakeLists.txt b/zephyr/tests/bacnet/property/CMakeLists.txt index 57abe7e0..c356e803 100644 --- a/zephyr/tests/bacnet/property/CMakeLists.txt +++ b/zephyr/tests/bacnet/property/CMakeLists.txt @@ -40,7 +40,10 @@ if(BOARD STREQUAL unit_testing) ${BACNET_SRC}/basic/sys/days.c ) - add_definitions(-DBACNET_PROPERTY_LISTS=1) + add_definitions( + -DBACNET_PROPERTY_LISTS=1 + -DBACNET_PROPERTY_ARRAY_LISTS=1 + ) set(CONF_FILE "${CONF_FILE};prj.unit_testing.conf") find_package(Zephyr COMPONENTS unittest REQUIRED HINTS $ENV{ZEPHYR_BASE}) diff --git a/zephyr/tests/bacnet/property/prj.conf b/zephyr/tests/bacnet/property/prj.conf index 3cb7c121..bdb885a3 100644 --- a/zephyr/tests/bacnet/property/prj.conf +++ b/zephyr/tests/bacnet/property/prj.conf @@ -1,3 +1,4 @@ CONFIG_ZTEST=y CONFIG_BACNETSTACK=y CONFIG_BACNET_PROPERTY_LISTS=y +CONFIG_BACNET_PROPERTY_ARRAY_LISTS=y diff --git a/zephyr/tests/bacnet/property/prj.unit_testing.conf b/zephyr/tests/bacnet/property/prj.unit_testing.conf index 03e311e3..32e6f1e8 100644 --- a/zephyr/tests/bacnet/property/prj.unit_testing.conf +++ b/zephyr/tests/bacnet/property/prj.unit_testing.conf @@ -1,3 +1,4 @@ CONFIG_ZTEST=y #CONFIG_BACNETSTACK=y #CONFIG_BACNET_PROPERTY_LISTS=y +#CONFIG_BACNET_PROPERTY_ARRAY_LISTS=y