From 61730e3d8744c619fb03e05d2f2765adb6b78a63 Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Tue, 6 Aug 2024 08:28:01 -0500 Subject: [PATCH] Fixed load control object and unit test. Added recipe to Makefile for Zephyr OS twister unit testing. (#710) --- .gitignore | 1 + Makefile | 13 + src/bacnet/bacapp.c | 334 +++++++- src/bacnet/bacapp.h | 13 + src/bacnet/bacenum.h | 10 +- src/bacnet/bactext.c | 1 + src/bacnet/basic/object/ao.c | 3 +- src/bacnet/basic/object/lc.c | 731 ++++++++++++------ src/bacnet/basic/object/lc.h | 36 +- src/bacnet/config.h | 5 +- test/CMakeLists.txt | 2 +- test/bacnet/basic/object/ai/CMakeLists.txt | 4 +- test/bacnet/basic/object/ao/CMakeLists.txt | 4 +- test/bacnet/basic/object/av/CMakeLists.txt | 4 +- .../basic/object/bacfile/CMakeLists.txt | 7 +- test/bacnet/basic/object/bi/CMakeLists.txt | 4 +- .../object/bitstring_value/CMakeLists.txt | 4 +- test/bacnet/basic/object/blo/CMakeLists.txt | 2 +- test/bacnet/basic/object/bo/CMakeLists.txt | 4 +- test/bacnet/basic/object/bv/CMakeLists.txt | 4 +- .../basic/object/calendar/CMakeLists.txt | 2 +- .../basic/object/channel/CMakeLists.txt | 2 +- .../basic/object/color_object/CMakeLists.txt | 2 +- .../object/color_temperature/CMakeLists.txt | 2 +- .../basic/object/command/CMakeLists.txt | 4 +- .../credential_data_input/CMakeLists.txt | 4 +- test/bacnet/basic/object/lc/CMakeLists.txt | 14 +- test/bacnet/basic/object/lc/src/main.c | 499 +++++------- test/bacnet/basic/object/lc/stubs.c | 44 -- test/bacnet/basic/object/lo/CMakeLists.txt | 2 +- test/bacnet/basic/object/lsz/CMakeLists.txt | 4 +- .../basic/object/ms-input/CMakeLists.txt | 4 +- test/bacnet/basic/object/mso/CMakeLists.txt | 4 +- test/bacnet/basic/object/msv/CMakeLists.txt | 4 +- .../basic/object/netport/CMakeLists.txt | 4 +- .../basic/object/schedule/CMakeLists.txt | 4 +- .../object/structured_view/CMakeLists.txt | 4 +- .../basic/object/{mock => test}/apdu_mock.c | 0 .../stubs.c => test/datetime_local.c} | 28 +- .../basic/object/{mock => test}/device_mock.c | 0 .../basic/object/{ => test}/property_test.c | 0 .../basic/object/{ => test}/property_test.h | 0 .../basic/object/{mock => test}/tsm_mock.c | 0 .../basic/object/time_value/CMakeLists.txt | 8 +- .../basic/object/trendlog/CMakeLists.txt | 6 +- .../bacnet/basic/object/ai/CMakeLists.txt | 2 +- .../bacnet/basic/object/ao/CMakeLists.txt | 2 +- .../bacnet/basic/object/av/CMakeLists.txt | 2 +- .../bacnet/basic/object/bi/CMakeLists.txt | 2 +- .../bacnet/basic/object/bo/CMakeLists.txt | 2 +- .../bacnet/basic/object/bv/CMakeLists.txt | 2 +- .../basic/object/calendar/CMakeLists.txt | 3 +- .../basic/object/color_object/CMakeLists.txt | 3 +- .../object/color_temperature/CMakeLists.txt | 3 +- .../basic/object/command/CMakeLists.txt | 2 +- .../credential_data_input/CMakeLists.txt | 2 +- .../bacnet/basic/object/lo/CMakeLists.txt | 3 +- .../basic/object/ms-input/CMakeLists.txt | 2 +- .../bacnet/basic/object/mso/CMakeLists.txt | 2 +- .../bacnet/basic/object/msv/CMakeLists.txt | 2 +- .../basic/object/netport/CMakeLists.txt | 2 +- .../basic/object/schedule/CMakeLists.txt | 2 +- .../basic/object/time_value/CMakeLists.txt | 6 +- 63 files changed, 1191 insertions(+), 684 deletions(-) delete mode 100644 test/bacnet/basic/object/lc/stubs.c rename test/bacnet/basic/object/{mock => test}/apdu_mock.c (100%) rename test/bacnet/basic/object/{time_value/stubs.c => test/datetime_local.c} (50%) rename test/bacnet/basic/object/{mock => test}/device_mock.c (100%) rename test/bacnet/basic/object/{ => test}/property_test.c (100%) rename test/bacnet/basic/object/{ => test}/property_test.h (100%) rename test/bacnet/basic/object/{mock => test}/tsm_mock.c (100%) diff --git a/.gitignore b/.gitignore index 0be69d3d..c55d1583 100644 --- a/.gitignore +++ b/.gitignore @@ -71,6 +71,7 @@ CMakeLists.txt.user Obj/ Release/ +/twister-out/* /test/build/ /cmake-build-* /.idea diff --git a/Makefile b/Makefile index 0f26c338..4e2896a6 100644 --- a/Makefile +++ b/Makefile @@ -450,3 +450,16 @@ test: .PHONY: retest retest: $(MAKE) -s -j -C test retest + +# Zephyr unit testing with twister +# expects zephyr to be installed in ../zephyr in Workspace +# expects ZEPHYR_BASE to be set. E.g. source ../zephyr/zephyr-env.sh +# see https://docs.zephyrproject.org/latest/getting_started/index.html +TWISTER_RESULTS=../twister-out.unit_testing +.PHONY: twister +twister: + $(ZEPHYR_BASE)/scripts/twister -O $(TWISTER_RESULTS) -p unit_testing -T zephyr/tests + +.PHONY: twister-clean +twister-clean: + -rm -rf $(TWISTER_RESULTS) diff --git a/src/bacnet/bacapp.c b/src/bacnet/bacapp.c index 9f5450ce..be76eb72 100644 --- a/src/bacnet/bacapp.c +++ b/src/bacnet/bacapp.c @@ -81,7 +81,6 @@ static int bacnet_scale_encode(uint8_t *apdu, BACNET_SCALE *value) static int bacnet_scale_decode(uint8_t *apdu, size_t apdu_size, BACNET_SCALE *value) { - int len = 0; int apdu_len = 0; BACNET_TAG tag = { 0 }; int32_t signed_value = 0; @@ -90,28 +89,25 @@ bacnet_scale_decode(uint8_t *apdu, size_t apdu_size, BACNET_SCALE *value) if (!apdu) { return BACNET_STATUS_ERROR; } - len = bacnet_tag_decode(&apdu[apdu_len], apdu_size - apdu_len, &tag); - if (len <= 0) { + apdu_len = bacnet_tag_decode(apdu, apdu_size, &tag); + if (apdu_len <= 0) { return BACNET_STATUS_ERROR; } switch (tag.number) { case 0: - len = bacnet_real_context_decode( - &apdu[apdu_len], apdu_size - apdu_len, tag.number, &real_value); - if (len > 0) { + apdu_len = bacnet_real_context_decode( + apdu, apdu_size, tag.number, &real_value); + if (apdu_len > 0) { value->float_scale = true; value->type.real_scale = real_value; - apdu_len += len; } break; case 1: - len = bacnet_signed_context_decode( - &apdu[apdu_len], apdu_size - apdu_len, tag.number, - &signed_value); - if (len > 0) { + apdu_len = bacnet_signed_context_decode( + apdu, apdu_size, tag.number, &signed_value); + if (apdu_len > 0) { value->float_scale = false; value->type.integer_scale = signed_value; - apdu_len += len; } break; default: @@ -149,6 +145,151 @@ static bool bacnet_scale_same(BACNET_SCALE *value1, BACNET_SCALE *value2) } #endif +#if defined(BACAPP_SHED_LEVEL) +/** + * @brief Encode a BACnetScale value. + * + * BACnetScale ::= CHOICE { + * float-scale [0] REAL, + * integer-scale [1] INTEGER + * } + * + * @param apdu - buffer to encode to + * @param value - value to encode + * @return number of bytes encoded + */ +static int bacnet_shed_level_encode(uint8_t *apdu, BACNET_SHED_LEVEL *value) +{ + int apdu_len = 0; + + if (!value) { + return 0; + } + switch (value->type) { + case BACNET_SHED_TYPE_PERCENT: + apdu_len = encode_context_unsigned(apdu, 0, + value->value.percent); + break; + case BACNET_SHED_TYPE_AMOUNT: + apdu_len = encode_context_real(apdu, 2, + value->value.amount); + break; + case BACNET_SHED_TYPE_LEVEL: + apdu_len = encode_context_unsigned(apdu, 1, + value->value.level); + break; + default: + break; + } + + return apdu_len; +} +#endif + +#if defined(BACAPP_SHED_LEVEL) +/** + * @brief Decode a BACnetShedLevel value. + * + * BACnetShedLevel ::= CHOICE { + * percent [0] Unsigned, + * level [1] Unsigned, + * amount [2] REAL + * } + * + * @param apdu - buffer to decode to + * @param apdu_size - size of the buffer + * @param value - value to encode + * @return number of bytes decoded, or BACNET_STATUS_ERROR on error + */ +static int +bacnet_shed_level_decode(uint8_t *apdu, size_t apdu_size, BACNET_SHED_LEVEL *value) +{ + int apdu_len = 0; + BACNET_TAG tag = { 0 }; + BACNET_UNSIGNED_INTEGER unsigned_value = 0; + float real_value = 0.0f; + + if (!apdu) { + return BACNET_STATUS_ERROR; + } + apdu_len = bacnet_tag_decode(apdu, apdu_size, &tag); + if (apdu_len <= 0) { + return BACNET_STATUS_ERROR; + } + switch (tag.number) { + case 0: + /* percent - Unsigned */ + apdu_len = bacnet_unsigned_context_decode( + apdu, apdu_size, tag.number, &unsigned_value); + if (apdu_len > 0) { + value->value.percent = unsigned_value; + value->type = BACNET_SHED_TYPE_PERCENT; + } + break; + case 1: + /* level - Unsigned */ + apdu_len = bacnet_unsigned_context_decode( + apdu, apdu_size, tag.number, &unsigned_value); + if (apdu_len > 0) { + value->value.level = unsigned_value; + value->type = BACNET_SHED_TYPE_LEVEL; + } + break; + + case 2: + apdu_len = bacnet_real_context_decode( + apdu, apdu_size, tag.number, &real_value); + if (apdu_len > 0) { + value->type = BACNET_SHED_TYPE_AMOUNT; + value->value.amount = real_value; + } + break; + default: + return BACNET_STATUS_ERROR; + } + + return apdu_len; +} +#endif + +#if defined(BACAPP_SHED_LEVEL) +static bool +bacnet_shed_level_same(BACNET_SHED_LEVEL *value1, BACNET_SHED_LEVEL *value2) +{ + bool status = false; + + if (value1 && value2) { + status = true; + if (value1->type != value2->type) { + status = false; + } else { + switch (value1->type) { + case BACNET_SHED_TYPE_PERCENT: + if (value1->value.percent != value2->value.percent) { + status = false; + } + break; + case BACNET_SHED_TYPE_AMOUNT: + if (islessgreater( + value1->value.amount, value2->value.amount)) { + status = false; + } + break; + case BACNET_SHED_TYPE_LEVEL: + if (value1->value.level != value2->value.level) { + status = false; + } + break; + default: + break; + } + } + } + + return status; +} +#endif + /** * @brief Encode application data given by a pointer into the APDU. * @param apdu - Pointer to the buffer to encode to, or NULL for length @@ -355,6 +496,13 @@ int bacapp_encode_application_data( /* BACnetScale */ apdu_len = bacnet_scale_encode(apdu, &value->type.Scale); break; +#endif +#if defined(BACAPP_SHED_LEVEL) + case BACNET_APPLICATION_TAG_SHED_LEVEL: + /* BACnetShedLevel */ + apdu_len = bacnet_shed_level_encode(apdu, + &value->type.Shed_Level); + break; #endif default: break; @@ -769,6 +917,7 @@ int bacapp_encode_context_data_value( case BACNET_APPLICATION_TAG_FDT_ENTRY: case BACNET_APPLICATION_TAG_ACTION_COMMAND: case BACNET_APPLICATION_TAG_SCALE: + case BACNET_APPLICATION_TAG_SHED_LEVEL: /* complex data is enclosed in open/close tags */ len = encode_opening_tag(apdu, context_tag_number); apdu_len += len; @@ -1098,6 +1247,11 @@ int bacapp_known_property_tag( case PROP_SCALE: /* BACnetScale */ return BACNET_APPLICATION_TAG_SCALE; + case PROP_ACTUAL_SHED_LEVEL: + case PROP_EXPECTED_SHED_LEVEL: + case PROP_REQUESTED_SHED_LEVEL: + /* BACnetShedLevel */ + return BACNET_APPLICATION_TAG_SHED_LEVEL; case PROP_FD_BBMD_ADDRESS: case PROP_BACNET_IP_GLOBAL_ADDRESS: @@ -1399,6 +1553,13 @@ int bacapp_decode_application_tag_value( /* BACnetScale */ apdu_len = bacnet_scale_decode(apdu, apdu_size, &value->type.Scale); break; +#endif +#if defined(BACAPP_SHED_LEVEL) + case BACNET_APPLICATION_TAG_SHED_LEVEL: + /* BACnetShedLevel */ + apdu_len = bacnet_shed_level_decode( + apdu, apdu_size, &value->type.Shed_Level); + break; #endif default: break; @@ -1698,6 +1859,43 @@ int bacapp_snprintf_shift(int len, char **buf, size_t *buf_size) return len; } +#if defined(BACAPP_SHED_LEVEL) +/** + * @brief Print a value to a string for EPICS + * @param str - destination string, or NULL for length only + * @param str_len - length of the destination string, or 0 for length only + * @param value - value to be printed + * @return number of characters written to the string + */ +int bacapp_snprintf_shed_level( + char *str, size_t str_len, BACNET_SHED_LEVEL *value) +{ + int length = 0; + + switch (value->type) { + case BACNET_SHED_TYPE_PERCENT: + length = bacapp_snprintf( + str, str_len, "%u%%",(unsigned) + value->value.percent); + break; + case BACNET_SHED_TYPE_LEVEL: + length = bacapp_snprintf( + str, str_len, "%u",(unsigned) + value->value.level); + break; + case BACNET_SHED_TYPE_AMOUNT: + length = bacapp_snprintf( + str, str_len, "%f", + value->value.amount); + break; + default: + break; + } + + return length; +} +#endif + /** * @brief Print a value to a string for EPICS * @param str - destination string, or NULL for length only @@ -3018,6 +3216,12 @@ int bacapp_snprintf_value( (long)value->type.Scale.type.integer_scale); } break; +#endif +#if defined(BACAPP_SHED_LEVEL) + case BACNET_APPLICATION_TAG_SHED_LEVEL: + ret_val = bacapp_snprintf_shed_level( + str, str_len, &value->type.Shed_Level); + break; #endif default: ret_val = bacapp_snprintf( @@ -3295,6 +3499,97 @@ static bool strtod_checked(const char *s, double *out) } #endif +#if defined(BACAPP_SCALE) +/** + * @brief Parse a string into a BACnetScale value + * @param value [out] The BACnetScale value + * @param argv [in] The string to parse + * @return True on success, else False + */ +bool bacnet_scale_from_ascii(BACNET_SCALE *value, const char *argv) +{ + bool status = false; + int count; + unsigned integer_scale; + float float_scale; + const char *decimal_point; + + if (!status) { + decimal_point = strchr(argv, '.'); + if (decimal_point) { + count = sscanf(argv, "%f", &float_scale); + if (count == 1) { + value->float_scale = true; + value->type.real_scale = float_scale; + status = true; + } + } + } + if (!status) { + count = sscanf(argv, "%u", &integer_scale); + if (count == 1) { + value->float_scale = false; + value->type.integer_scale = integer_scale; + status = true; + } + } + + return status; +} +#endif + +#if defined(BACAPP_SHED_LEVEL) +/** + * @brief Parse a string into a BACnet Shed Level value + * @param value [out] The BACnet Shed Level value + * @param argv [in] The string to parse + * @return True on success, else False + */ +bool bacnet_shed_level_from_ascii(BACNET_SHED_LEVEL *value, const char *argv) +{ + bool status = false; + int count; + unsigned percent, level; + float amount; + const char *percentage; + const char *decimal_point; + + if (!status) { + percentage = strchr(argv, '%'); + if (percentage) { + count = sscanf(argv, "%u", &percent); + if (count == 1) { + value->type = BACNET_SHED_TYPE_PERCENT; + value->value.percent = percent; + status = true; + } + } + } + if (!status) { + decimal_point = strchr(argv, '.'); + if (decimal_point) { + count = sscanf(argv, "%f", &amount); + if (count == 1) { + value->type = BACNET_SHED_TYPE_AMOUNT; + value->value.amount = amount; + status = true; + } + } + + } + if (!status) { + count = sscanf(argv, "%u", &level); + if (count == 1) { + value->type = BACNET_SHED_TYPE_LEVEL; + value->value.level = level; + status = true; + } + } + + return status; +} +#endif + /* used to load the app data struct with the proper data converted from a command line argument. "argv" is not const to allow using strtok internally. It MAY be modified. */ @@ -3528,7 +3823,14 @@ bool bacapp_parse_application_data( #endif #if defined(BACAPP_SCALE) case BACNET_APPLICATION_TAG_SCALE: - /* BACnetScale - not implement */ + status = bacnet_scale_from_ascii( + &value->type.Scale, argv); + break; +#endif +#if defined(BACAPP_SHED_LEVEL) + case BACNET_APPLICATION_TAG_SHED_LEVEL: + status = bacnet_shed_level_from_ascii( + &value->type.Shed_Level, argv); break; #endif default: @@ -4075,6 +4377,12 @@ bool bacapp_same_value( status = bacnet_scale_same( &value->type.Scale, &test_value->type.Scale); break; +#endif +#if defined(BACAPP_SHED_LEVEL) + case BACNET_APPLICATION_TAG_SHED_LEVEL: + status = bacnet_shed_level_same( + &value->type.Shed_Level, &test_value->type.Shed_Level); + break; #endif case BACNET_APPLICATION_TAG_EMPTYLIST: status = true; diff --git a/src/bacnet/bacapp.h b/src/bacnet/bacapp.h index be4eae2d..c8e87c41 100644 --- a/src/bacnet/bacapp.h +++ b/src/bacnet/bacapp.h @@ -47,6 +47,16 @@ typedef struct BACnetScale { } type; } BACNET_SCALE; +/* The shed levels for the LEVEL choice of BACnetShedLevel. */ +typedef struct { + BACNET_SHED_LEVEL_TYPE type; + union { + BACNET_UNSIGNED_INTEGER level; + BACNET_UNSIGNED_INTEGER percent; + float amount; + } value; +} BACNET_SHED_LEVEL; + struct BACnet_Application_Data_Value; typedef struct BACnet_Application_Data_Value { bool context_specific; /* true if context specific data */ @@ -146,6 +156,9 @@ typedef struct BACnet_Application_Data_Value { #endif #if defined (BACAPP_SCALE) BACNET_SCALE Scale; +#endif +#if defined(BACAPP_SHED_LEVEL) + BACNET_SHED_LEVEL Shed_Level; #endif } type; /* simple linked list if needed */ diff --git a/src/bacnet/bacenum.h b/src/bacnet/bacenum.h index c64007f1..c25dbb6e 100644 --- a/src/bacnet/bacenum.h +++ b/src/bacnet/bacenum.h @@ -1606,7 +1606,9 @@ typedef enum { /* BACnetActionCommand */ BACNET_APPLICATION_TAG_ACTION_COMMAND, /* BACnetScale */ - BACNET_APPLICATION_TAG_SCALE + BACNET_APPLICATION_TAG_SCALE, + /* BACnetShedLevel */ + BACNET_APPLICATION_TAG_SHED_LEVEL } BACNET_APPLICATION_TAG; /* note: these are not the real values, */ @@ -2253,6 +2255,12 @@ typedef enum BACnetShedState { BACNET_SHED_NON_COMPLIANT = 3 } BACNET_SHED_STATE; +typedef enum BACnetShedLevelType { + BACNET_SHED_TYPE_PERCENT, /* Unsigned */ + BACNET_SHED_TYPE_LEVEL, /* Unsigned */ + BACNET_SHED_TYPE_AMOUNT /* REAL */ +} BACNET_SHED_LEVEL_TYPE; + typedef enum BACnetLightingOperation { BACNET_LIGHTS_NONE = 0, BACNET_LIGHTS_FADE_TO = 1, diff --git a/src/bacnet/bactext.c b/src/bacnet/bactext.c index 38471939..7fbd0efa 100644 --- a/src/bacnet/bactext.c +++ b/src/bacnet/bactext.c @@ -144,6 +144,7 @@ INDTEXT_DATA bacnet_application_tag_names[] = { { BACNET_APPLICATION_TAG_NULL, { BACNET_APPLICATION_TAG_FDT_ENTRY, "BACnetFDTEntry" }, { BACNET_APPLICATION_TAG_ACTION_COMMAND, "BACnetActionCommand" }, { BACNET_APPLICATION_TAG_SCALE, "BACnetScale" }, + { BACNET_APPLICATION_TAG_SHED_LEVEL, "BACnetShedLevel" }, { 0, NULL } }; const char *bactext_application_tag_name(unsigned index) diff --git a/src/bacnet/basic/object/ao.c b/src/bacnet/basic/object/ao.c index 7b527a69..23958139 100644 --- a/src/bacnet/basic/object/ao.c +++ b/src/bacnet/basic/object/ao.c @@ -317,7 +317,8 @@ bool Analog_Output_Present_Value_Set( pObject = Keylist_Data(Object_List, object_instance); if (pObject) { if ((priority >= 1) && (priority <= BACNET_MAX_PRIORITY) && - value >= pObject->Min_Pres_Value && value <= pObject->Max_Pres_Value) { + (value >= pObject->Min_Pres_Value) && + (value <= pObject->Max_Pres_Value)) { pObject->Relinquished[priority - 1] = false; pObject->Priority_Array[priority - 1] = value; Analog_Output_Present_Value_COV_Detect( diff --git a/src/bacnet/basic/object/lc.c b/src/bacnet/basic/object/lc.c index 242ea593..8c962d58 100644 --- a/src/bacnet/basic/object/lc.c +++ b/src/bacnet/basic/object/lc.c @@ -2,7 +2,7 @@ * @file * @author Steve Karg * @date 2007 - * @brief The Load Control Objects from 135-2004-Addendum e + * @brief The Load Control Objects from 135-2004-Addendum e * @copyright SPDX-License-Identifier: MIT */ #include @@ -20,8 +20,6 @@ #include "bacnet/basic/services.h" #include "bacnet/basic/sys/debug.h" -#define PRINTF debug_printf - /* number of demo objects */ #ifndef MAX_LOAD_CONTROLS #define MAX_LOAD_CONTROLS 4 @@ -31,26 +29,10 @@ static BACNET_SHED_STATE Present_Value[MAX_LOAD_CONTROLS]; /* load control objects are required to support LEVEL */ -typedef enum BACnetShedLevelType { - BACNET_SHED_TYPE_PERCENT, /* Unsigned */ - BACNET_SHED_TYPE_LEVEL, /* Unsigned */ - BACNET_SHED_TYPE_AMOUNT /* REAL */ -} BACNET_SHED_LEVEL_TYPE; - #define DEFAULT_VALUE_PERCENT 100 #define DEFAULT_VALUE_LEVEL 0 -#define DEFAULT_VALUE_AMOUNT 0.0 +#define DEFAULT_VALUE_AMOUNT 0.0f -/* The shed levels for the LEVEL choice of BACnetShedLevel - that have meaning for this particular Load Control object. */ -typedef struct { - BACNET_SHED_LEVEL_TYPE type; - union { - unsigned level; - unsigned percent; - float amount; - } value; -} BACNET_SHED_LEVEL; /* indicates the desired load shedding */ static BACNET_SHED_LEVEL Requested_Shed_Level[MAX_LOAD_CONTROLS]; /* Indicates the amount of power that the object expects @@ -64,7 +46,6 @@ static BACNET_SHED_LEVEL Actual_Shed_Level[MAX_LOAD_CONTROLS]; by the Load Control object must be compliant with the requested shed. */ static BACNET_DATE_TIME Start_Time[MAX_LOAD_CONTROLS]; static BACNET_DATE_TIME End_Time[MAX_LOAD_CONTROLS]; -static BACNET_DATE_TIME Current_Time; /* indicates the duration of the load shed action, starting at Start_Time in minutes */ @@ -107,20 +88,39 @@ static unsigned Shed_Levels[MAX_LOAD_CONTROLS][MAX_SHED_LEVELS]; Load Control object can take on. It is the same for all the load control objects in this example device. */ static char *Shed_Level_Descriptions[MAX_SHED_LEVELS] = { "dim lights 10%", - "dim lights 20%", "dim lights 30%" }; + "dim lights 20%", + "dim lights 30%" }; -static float Shed_Level_Values[MAX_SHED_LEVELS] = { 90.0, 80.0, 70.0 }; +static float Shed_Level_Values[MAX_SHED_LEVELS] = { 90.0f, 80.0f, 70.0f }; + +/* borrow some properties from the Loop object */ +static BACNET_OBJECT_PROPERTY_REFERENCE + Manipulated_Variable_Reference[MAX_LOAD_CONTROLS]; +static unsigned Priority_For_Writing[MAX_LOAD_CONTROLS]; /* These three arrays are used by the ReadPropertyMultiple handler */ -static const int Load_Control_Properties_Required[] = { PROP_OBJECT_IDENTIFIER, - PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, - PROP_EVENT_STATE, PROP_REQUESTED_SHED_LEVEL, PROP_START_TIME, - PROP_SHED_DURATION, PROP_DUTY_WINDOW, PROP_ENABLE, PROP_EXPECTED_SHED_LEVEL, - PROP_ACTUAL_SHED_LEVEL, PROP_SHED_LEVELS, PROP_SHED_LEVEL_DESCRIPTIONS, - -1 }; +static const int Load_Control_Properties_Required[] = { + PROP_OBJECT_IDENTIFIER, + PROP_OBJECT_NAME, + PROP_OBJECT_TYPE, + PROP_PRESENT_VALUE, + PROP_STATUS_FLAGS, + PROP_EVENT_STATE, + PROP_REQUESTED_SHED_LEVEL, + PROP_START_TIME, + PROP_SHED_DURATION, + PROP_DUTY_WINDOW, + PROP_ENABLE, + PROP_EXPECTED_SHED_LEVEL, + PROP_ACTUAL_SHED_LEVEL, + PROP_SHED_LEVELS, + PROP_SHED_LEVEL_DESCRIPTIONS, + -1 +}; static const int Load_Control_Properties_Optional[] = { PROP_DESCRIPTION, - PROP_FULL_DUTY_BASELINE, -1 }; + PROP_FULL_DUTY_BASELINE, + -1 }; static const int Load_Control_Properties_Proprietary[] = { -1 }; @@ -151,11 +151,10 @@ void Load_Control_Init(void) Requested_Shed_Level[i].value.level = 0; datetime_wildcard_set(&Start_Time[i]); datetime_wildcard_set(&End_Time[i]); - datetime_wildcard_set(&Current_Time); Shed_Duration[i] = 0; Duty_Window[i] = 0; Load_Control_Enable[i] = true; - Full_Duty_Baseline[i] = 1.500; /* kilowatts */ + Full_Duty_Baseline[i] = 1.500f; /* kilowatts */ Expected_Shed_Level[i].type = BACNET_SHED_TYPE_LEVEL; Expected_Shed_Level[i].value.level = 0; Actual_Shed_Level[i].type = BACNET_SHED_TYPE_LEVEL; @@ -165,6 +164,26 @@ void Load_Control_Init(void) for (j = 0; j < MAX_SHED_LEVELS; j++) { Shed_Levels[i][j] = j + 1; } + Priority_For_Writing[i] = 4; + Manipulated_Variable_Reference[i].object_identifier.type = + OBJECT_ANALOG_OUTPUT; + Manipulated_Variable_Reference[i].object_identifier.instance = 1 + i; + Manipulated_Variable_Reference[i].property_identifier = + PROP_PRESENT_VALUE; + switch (Manipulated_Variable_Reference[i].object_identifier.type) { + case OBJECT_ANALOG_OUTPUT: + if (Analog_Output_Valid_Instance( + Manipulated_Variable_Reference[i] + .object_identifier.instance)) { + Analog_Output_Delete(Manipulated_Variable_Reference[i] + .object_identifier.instance); + } + Analog_Output_Create(Manipulated_Variable_Reference[i] + .object_identifier.instance); + break; + default: + break; + } } return; @@ -235,26 +254,21 @@ bool Load_Control_Object_Name( bool status = false; if (object_instance < MAX_LOAD_CONTROLS) { - snprintf(text, sizeof(text), "LOAD CONTROL %lu", (unsigned long)object_instance); + snprintf( + text, sizeof(text), "LOAD CONTROL %lu", + (unsigned long)object_instance); status = characterstring_init_ansi(object_name, text); } return status; } -static void Update_Current_Time(BACNET_DATE_TIME *bdatetime) -{ - if (bdatetime) { - datetime_local(&bdatetime->date, &bdatetime->time, NULL, NULL); - } -} - /* convert the shed level request into an Analog Output Present_Value */ static float Requested_Shed_Level_Value(int object_index) { unsigned shed_level_index = 0; unsigned i = 0; - float requested_level = 0.0; + float requested_level = 0.0f; switch (Requested_Shed_Level[object_index].type) { case BACNET_SHED_TYPE_PERCENT: @@ -266,7 +280,7 @@ static float Requested_Shed_Level_Value(int object_index) requested_level = Full_Duty_Baseline[object_index] - Requested_Shed_Level[object_index].value.amount; requested_level /= Full_Duty_Baseline[object_index]; - requested_level *= 100.0; + requested_level *= 100.0f; break; case BACNET_SHED_TYPE_LEVEL: default: @@ -302,8 +316,8 @@ static void Shed_Level_Copy(BACNET_SHED_LEVEL *dest, BACNET_SHED_LEVEL *src) } } -static void Shed_Level_Default_Set( - BACNET_SHED_LEVEL *dest, BACNET_SHED_LEVEL_TYPE type) +static void +Shed_Level_Default_Set(BACNET_SHED_LEVEL *dest, BACNET_SHED_LEVEL_TYPE type) { if (dest) { dest->type = type; @@ -312,7 +326,7 @@ static void Shed_Level_Default_Set( dest->value.percent = 100; break; case BACNET_SHED_TYPE_AMOUNT: - dest->value.amount = 0.0; + dest->value.amount = 0.0f; break; case BACNET_SHED_TYPE_LEVEL: default: @@ -324,93 +338,134 @@ static void Shed_Level_Default_Set( static bool Able_To_Meet_Shed_Request(int object_index) { - float level = 0.0; - float requested_level = 0.0; + float level = 0.0f; + float requested_level = 0.0f; unsigned priority = 0; bool status = false; int object_instance = 0; + BACNET_OBJECT_TYPE object_type; - /* This demo is going to use the Analog Outputs as their Load */ - object_instance = object_index; - priority = Analog_Output_Present_Value_Priority(object_instance); - /* we are controlling at Priority 4 - can we control the output? */ - if (priority >= 4) { - /* is the level able to be lowered? */ - requested_level = Requested_Shed_Level_Value(object_index); - level = Analog_Output_Present_Value(object_instance); - if (level >= requested_level) { + object_instance = + Manipulated_Variable_Reference[object_index].object_identifier.instance; + object_type = + Manipulated_Variable_Reference[object_index].object_identifier.type; + switch (object_type) { + case OBJECT_ANALOG_OUTPUT: + priority = Analog_Output_Present_Value_Priority(object_instance); + level = Analog_Output_Present_Value(object_instance); status = true; + break; + default: + break; + } + if (status) { + status = false; + /* can we control the output? */ + if (priority >= Priority_For_Writing[object_index]) { + /* is the level able to be lowered? */ + requested_level = Requested_Shed_Level_Value(object_index); + if (level >= requested_level) { + status = true; + } } } return status; } -typedef enum load_control_state { - SHED_INACTIVE, - SHED_REQUEST_PENDING, - SHED_NON_COMPLIANT, - SHED_COMPLIANT, - MAX_LOAD_CONTROL_STATE -} LOAD_CONTROL_STATE; -static LOAD_CONTROL_STATE Load_Control_State[MAX_LOAD_CONTROLS]; -static LOAD_CONTROL_STATE Load_Control_State_Previously[MAX_LOAD_CONTROLS]; +static BACNET_LOAD_CONTROL_STATE Load_Control_State_Active[MAX_LOAD_CONTROLS]; +static BACNET_LOAD_CONTROL_STATE + Load_Control_State_Previously[MAX_LOAD_CONTROLS]; + +/** + * @brief Get the current state of the Load Control object. + * @param object_index [in] The object index number. + * @return The current state of the Load Control object. + */ +BACNET_LOAD_CONTROL_STATE Load_Control_State(int object_index) +{ + BACNET_LOAD_CONTROL_STATE state = SHED_INACTIVE; + + if (object_index < MAX_LOAD_CONTROLS) { + state = Load_Control_State_Active[object_index]; + } + + return state; +} #if PRINT_ENABLED_DEBUG static void Print_Load_Control_State(int object_index) { char *Load_Control_State_Text[MAX_LOAD_CONTROLS] = { "SHED_INACTIVE", - "SHED_REQUEST_PENDING", "SHED_NON_COMPLIANT", "SHED_COMPLIANT" }; + "SHED_REQUEST_PENDING", + "SHED_NON_COMPLIANT", + "SHED_COMPLIANT" }; if (object_index < MAX_LOAD_CONTROLS) { - if (Load_Control_State[object_index] < MAX_LOAD_CONTROL_STATE) { - printf("Load Control[%d]=%s\n", object_index, - Load_Control_State_Text[Load_Control_State[object_index]]); + if (Load_Control_State_Active[object_index] < MAX_LOAD_CONTROL_STATE) { + printf( + "Load Control[%d]=%s\n", object_index, + Load_Control_State_Text + [Load_Control_State_Active[object_index]]); } } } #endif -void Load_Control_State_Machine(int object_index) +void Load_Control_State_Machine(int object_index, BACNET_DATE_TIME *bdatetime) { unsigned i = 0; /* loop counter */ int diff = 0; /* used for datetime comparison */ + float amount; + unsigned percent; + unsigned level; + unsigned priority; + BACNET_OBJECT_ID object_id; + if (object_index >= MAX_LOAD_CONTROLS) { + return; + } /* is the state machine enabled? */ if (!Load_Control_Enable[object_index]) { - Load_Control_State[object_index] = SHED_INACTIVE; + Load_Control_State_Active[object_index] = SHED_INACTIVE; return; } - switch (Load_Control_State[object_index]) { + switch (Load_Control_State_Active[object_index]) { case SHED_REQUEST_PENDING: if (Load_Control_Request_Written[object_index]) { Load_Control_Request_Written[object_index] = false; /* request to cancel using default values? */ switch (Requested_Shed_Level[object_index].type) { case BACNET_SHED_TYPE_PERCENT: - if (Requested_Shed_Level[object_index].value.percent == - DEFAULT_VALUE_PERCENT) { - Load_Control_State[object_index] = SHED_INACTIVE; + percent = + Requested_Shed_Level[object_index].value.percent; + if (percent == DEFAULT_VALUE_PERCENT) { + Load_Control_State_Active[object_index] = + SHED_INACTIVE; } break; case BACNET_SHED_TYPE_AMOUNT: - if (Requested_Shed_Level[object_index].value.amount <= - DEFAULT_VALUE_AMOUNT) { - Load_Control_State[object_index] = SHED_INACTIVE; + amount = + Requested_Shed_Level[object_index].value.amount; + if (islessequal(amount, DEFAULT_VALUE_AMOUNT)) { + Load_Control_State_Active[object_index] = + SHED_INACTIVE; } break; case BACNET_SHED_TYPE_LEVEL: default: - if (Requested_Shed_Level[object_index].value.level == - DEFAULT_VALUE_LEVEL) { - Load_Control_State[object_index] = SHED_INACTIVE; + level = Requested_Shed_Level[object_index].value.level; + if (level == DEFAULT_VALUE_LEVEL) { + Load_Control_State_Active[object_index] = + SHED_INACTIVE; } break; } - if (Load_Control_State[object_index] == SHED_INACTIVE) { + if (Load_Control_State_Active[object_index] == SHED_INACTIVE) { #if PRINT_ENABLED_DEBUG - printf("Load Control[%d]:Requested Shed Level=Default\n", + printf( + "Load Control[%d]:Requested Shed Level=Default\n", object_index); #endif break; @@ -421,7 +476,7 @@ void Load_Control_State_Machine(int object_index) Start_Time_Property_Written[object_index] = false; /* request to cancel using wildcards in start time? */ if (datetime_wildcard(&Start_Time[object_index])) { - Load_Control_State[object_index] = SHED_INACTIVE; + Load_Control_State_Active[object_index] = SHED_INACTIVE; #if PRINT_ENABLED_DEBUG printf( "Load Control[%d]:Start Time=Wildcard\n", object_index); @@ -433,49 +488,71 @@ void Load_Control_State_Machine(int object_index) datetime_copy(&End_Time[object_index], &Start_Time[object_index]); datetime_add_minutes( &End_Time[object_index], Shed_Duration[object_index]); - diff = datetime_compare(&End_Time[object_index], &Current_Time); + diff = datetime_compare(&End_Time[object_index], bdatetime); if (diff < 0) { /* CancelShed */ /* FIXME: stop shedding! i.e. relinquish */ #if PRINT_ENABLED_DEBUG - printf("Load Control[%d]:Current Time" - " is after Start Time + Duration\n", + printf( + "Load Control[%d]:Current Time" + " is after Start Time + Duration\n", object_index); #endif - Load_Control_State[object_index] = SHED_INACTIVE; + Load_Control_State_Active[object_index] = SHED_INACTIVE; break; } - diff = datetime_compare(&Current_Time, &Start_Time[object_index]); + diff = datetime_compare(bdatetime, &Start_Time[object_index]); if (diff < 0) { /* current time prior to start time */ /* ReconfigurePending */ - Shed_Level_Copy(&Expected_Shed_Level[object_index], + Shed_Level_Copy( + &Expected_Shed_Level[object_index], &Requested_Shed_Level[object_index]); - Shed_Level_Default_Set(&Actual_Shed_Level[object_index], + Shed_Level_Default_Set( + &Actual_Shed_Level[object_index], Requested_Shed_Level[object_index].type); } else if (diff > 0) { /* current time after to start time */ -#if PRINT_ENABLED_DEBUG - printf("Load Control[%d]:Current Time" - " is after Start Time\n", + debug_printf( + "Load Control[%d]:Current Time" + " is after Start Time\n", object_index); -#endif /* AbleToMeetShed */ if (Able_To_Meet_Shed_Request(object_index)) { - Shed_Level_Copy(&Expected_Shed_Level[object_index], + Shed_Level_Copy( + &Expected_Shed_Level[object_index], &Requested_Shed_Level[object_index]); - Analog_Output_Present_Value_Set(object_index, - Requested_Shed_Level_Value(object_index), 4); - Shed_Level_Copy(&Actual_Shed_Level[object_index], + object_id.instance = + Manipulated_Variable_Reference[object_index] + .object_identifier.instance; + object_id.type = + Manipulated_Variable_Reference[object_index] + .object_identifier.type; + priority = Priority_For_Writing[object_index]; + switch (object_id.type) { + case OBJECT_ANALOG_OUTPUT: + Analog_Output_Present_Value_Set( + object_id.instance, + Requested_Shed_Level_Value(object_index), + priority); + break; + default: + break; + } + Shed_Level_Copy( + &Actual_Shed_Level[object_index], &Requested_Shed_Level[object_index]); - Load_Control_State[object_index] = SHED_COMPLIANT; + Load_Control_State_Active[object_index] = SHED_COMPLIANT; } else { /* CannotMeetShed */ - Shed_Level_Default_Set(&Expected_Shed_Level[object_index], + Shed_Level_Default_Set( + &Expected_Shed_Level[object_index], Requested_Shed_Level[object_index].type); - Shed_Level_Default_Set(&Actual_Shed_Level[object_index], + Shed_Level_Default_Set( + &Actual_Shed_Level[object_index], Requested_Shed_Level[object_index].type); - Load_Control_State[object_index] = SHED_NON_COMPLIANT; + Load_Control_State_Active[object_index] = + SHED_NON_COMPLIANT; } } break; @@ -483,82 +560,118 @@ void Load_Control_State_Machine(int object_index) datetime_copy(&End_Time[object_index], &Start_Time[object_index]); datetime_add_minutes( &End_Time[object_index], Shed_Duration[object_index]); - diff = datetime_compare(&End_Time[object_index], &Current_Time); + diff = datetime_compare(&End_Time[object_index], bdatetime); if (diff < 0) { /* FinishedUnsuccessfulShed */ #if PRINT_ENABLED_DEBUG - printf("Load Control[%d]:Current Time is after Start Time + " - "Duration\n", + printf( + "Load Control[%d]:Current Time is after Start Time + " + "Duration\n", object_index); #endif - Load_Control_State[object_index] = SHED_INACTIVE; + Load_Control_State_Active[object_index] = SHED_INACTIVE; break; } if (Load_Control_Request_Written[object_index] || Start_Time_Property_Written[object_index]) { /* UnsuccessfulShedReconfigured */ #if PRINT_ENABLED_DEBUG - printf("Load Control[%d]:Control Property written\n", + printf( + "Load Control[%d]:Control Property written\n", object_index); #endif /* The Written flags will cleared in the next state */ - Load_Control_State[object_index] = SHED_REQUEST_PENDING; + Load_Control_State_Active[object_index] = SHED_REQUEST_PENDING; break; } if (Able_To_Meet_Shed_Request(object_index)) { /* CanNowComplyWithShed */ #if PRINT_ENABLED_DEBUG - printf("Load Control[%d]:Able to meet Shed Request\n", + printf( + "Load Control[%d]:Able to meet Shed Request\n", object_index); #endif - Shed_Level_Copy(&Expected_Shed_Level[object_index], + Shed_Level_Copy( + &Expected_Shed_Level[object_index], &Requested_Shed_Level[object_index]); - Analog_Output_Present_Value_Set( - object_index, Requested_Shed_Level_Value(object_index), 4); - Shed_Level_Copy(&Actual_Shed_Level[object_index], + object_id.instance = + Manipulated_Variable_Reference[object_index] + .object_identifier.instance; + object_id.type = Manipulated_Variable_Reference[object_index] + .object_identifier.type; + priority = Priority_For_Writing[object_index]; + switch (object_id.type) { + case OBJECT_ANALOG_OUTPUT: + Analog_Output_Present_Value_Set( + object_id.instance, + Requested_Shed_Level_Value(object_index), priority); + break; + default: + break; + } + Shed_Level_Copy( + &Actual_Shed_Level[object_index], &Requested_Shed_Level[object_index]); - Load_Control_State[object_index] = SHED_COMPLIANT; + Load_Control_State_Active[object_index] = SHED_COMPLIANT; } break; case SHED_COMPLIANT: datetime_copy(&End_Time[object_index], &Start_Time[object_index]); datetime_add_minutes( &End_Time[object_index], Shed_Duration[object_index]); - diff = datetime_compare(&End_Time[object_index], &Current_Time); + diff = datetime_compare(&End_Time[object_index], bdatetime); if (diff < 0) { /* FinishedSuccessfulShed */ #if PRINT_ENABLED_DEBUG - printf("Load Control[%d]:Current Time is after Start Time + " - "Duration\n", + printf( + "Load Control[%d]:Current Time is after Start Time + " + "Duration\n", object_index); #endif datetime_wildcard_set(&Start_Time[i]); - Analog_Output_Present_Value_Relinquish(object_index, 4); - Load_Control_State[object_index] = SHED_INACTIVE; + object_id.instance = + Manipulated_Variable_Reference[object_index] + .object_identifier.instance; + object_id.type = Manipulated_Variable_Reference[object_index] + .object_identifier.type; + priority = Priority_For_Writing[object_index]; + switch (object_id.type) { + case OBJECT_ANALOG_OUTPUT: + Analog_Output_Present_Value_Relinquish( + object_id.instance, priority); + break; + default: + break; + } + Load_Control_State_Active[object_index] = SHED_INACTIVE; break; } if (Load_Control_Request_Written[object_index] || Start_Time_Property_Written[object_index]) { /* UnsuccessfulShedReconfigured */ #if PRINT_ENABLED_DEBUG - printf("Load Control[%d]:Control Property written\n", + printf( + "Load Control[%d]:Control Property written\n", object_index); #endif /* The Written flags will cleared in the next state */ - Load_Control_State[object_index] = SHED_REQUEST_PENDING; + Load_Control_State_Active[object_index] = SHED_REQUEST_PENDING; break; } if (!Able_To_Meet_Shed_Request(object_index)) { /* CanNoLongerComplyWithShed */ #if PRINT_ENABLED_DEBUG - printf("Load Control[%d]:Not able to meet Shed Request\n", + printf( + "Load Control[%d]:Not able to meet Shed Request\n", object_index); #endif - Shed_Level_Default_Set(&Expected_Shed_Level[object_index], + Shed_Level_Default_Set( + &Expected_Shed_Level[object_index], Requested_Shed_Level[object_index].type); - Shed_Level_Default_Set(&Actual_Shed_Level[object_index], + Shed_Level_Default_Set( + &Actual_Shed_Level[object_index], Requested_Shed_Level[object_index].type); - Load_Control_State[object_index] = SHED_NON_COMPLIANT; + Load_Control_State_Active[object_index] = SHED_NON_COMPLIANT; } break; case SHED_INACTIVE: @@ -568,11 +681,13 @@ void Load_Control_State_Machine(int object_index) printf("Load Control[%d]:Start Time written\n", object_index); #endif /* The Written flag will cleared in the next state */ - Shed_Level_Copy(&Expected_Shed_Level[object_index], + Shed_Level_Copy( + &Expected_Shed_Level[object_index], &Requested_Shed_Level[object_index]); - Shed_Level_Default_Set(&Actual_Shed_Level[object_index], + Shed_Level_Default_Set( + &Actual_Shed_Level[object_index], Requested_Shed_Level[object_index].type); - Load_Control_State[object_index] = SHED_REQUEST_PENDING; + Load_Control_State_Active[object_index] = SHED_REQUEST_PENDING; } break; } @@ -585,26 +700,128 @@ void Load_Control_State_Machine_Handler(void) { unsigned i = 0; static bool initialized = false; + BACNET_DATE_TIME bdatetime = { 0 }; if (!initialized) { initialized = true; for (i = 0; i < MAX_LOAD_CONTROLS; i++) { - Load_Control_State[i] = SHED_INACTIVE; + Load_Control_State_Active[i] = SHED_INACTIVE; Load_Control_State_Previously[i] = SHED_INACTIVE; } } - Update_Current_Time(&Current_Time); + datetime_local(&bdatetime.date, &bdatetime.time, NULL, NULL); for (i = 0; i < MAX_LOAD_CONTROLS; i++) { - Load_Control_State_Machine(i); - if (Load_Control_State[i] != Load_Control_State_Previously[i]) { + Load_Control_State_Machine(i, &bdatetime); + if (Load_Control_State_Active[i] != Load_Control_State_Previously[i]) { #if PRINT_ENABLED_DEBUG Print_Load_Control_State(i); #endif - Load_Control_State_Previously[i] = Load_Control_State[i]; + Load_Control_State_Previously[i] = Load_Control_State_Active[i]; } } } +/** + * @brief Get the priority for writing to the Manipulated Variable. + * @param object_instance [in] The object instance number. + */ +unsigned Load_Control_Priority_For_Writing(uint32_t object_instance) +{ + unsigned priority = 0; + unsigned object_index = 0; + + object_index = Load_Control_Instance_To_Index(object_instance); + if (object_index < MAX_LOAD_CONTROLS) { + priority = Priority_For_Writing[object_index]; + } + + return priority; +} + +/** + * @brief Set the priority for writing to the Manipulated Variable. + * @param object_instance [in] The object instance number. + * @param priority [in] The priority for writing. + * @return True if successful, else False. + */ +bool Load_Control_Priority_For_Writing_Set( + uint32_t object_instance, unsigned priority) +{ + unsigned object_index = 0; + bool status = false; + + object_index = Load_Control_Instance_To_Index(object_instance); + if (object_index < MAX_LOAD_CONTROLS) { + Priority_For_Writing[object_index] = priority; + status = true; + } + + return status; +} + +/** + * @brief Get the Manipulated Variable Reference for the Load Control object. + * @param object_instance [in] The object instance number. + * @param object_property_reference [out] The object property reference. + * @return True if successful, else False. + */ +bool Load_Control_Manipulated_Variable_Reference( + uint32_t object_instance, + BACNET_OBJECT_PROPERTY_REFERENCE *object_property_reference) +{ + unsigned object_index = 0; + bool status = false; + + object_index = Load_Control_Instance_To_Index(object_instance); + if (object_index < MAX_LOAD_CONTROLS) { + if (object_property_reference) { + object_property_reference->object_identifier.instance = + Manipulated_Variable_Reference[object_index] + .object_identifier.instance; + object_property_reference->object_identifier.type = + Manipulated_Variable_Reference[object_index] + .object_identifier.type; + object_property_reference->property_identifier = + Manipulated_Variable_Reference[object_index] + .property_identifier; + status = true; + } + } + + return status; +} + +/** + * @brief Set the Manipulated Variable Reference for the Load Control object. + * @param object_instance [in] The object instance number. + * @param object_id [in] The object identifier. + * @return True if successful, else False. + */ +bool Load_Control_Manipulated_Variable_Reference_Set( + uint32_t object_instance, + BACNET_OBJECT_PROPERTY_REFERENCE *object_property_reference) +{ + unsigned object_index = 0; + bool status = false; + + object_index = Load_Control_Instance_To_Index(object_instance); + if (object_index < MAX_LOAD_CONTROLS) { + if (object_property_reference) { + Manipulated_Variable_Reference[object_index] + .object_identifier.instance = + object_property_reference->object_identifier.instance; + Manipulated_Variable_Reference[object_index] + .object_identifier.type = + object_property_reference->object_identifier.type; + Manipulated_Variable_Reference[object_index].property_identifier = + object_property_reference->property_identifier; + status = true; + } + } + + return status; +} + /* return apdu len, or BACNET_STATUS_ERROR on error */ int Load_Control_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) { @@ -667,16 +884,19 @@ int Load_Control_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) case PROP_REQUESTED_SHED_LEVEL: switch (Requested_Shed_Level[object_index].type) { case BACNET_SHED_TYPE_PERCENT: - apdu_len = encode_context_unsigned(&apdu[0], 0, + apdu_len = encode_context_unsigned( + &apdu[0], 0, Requested_Shed_Level[object_index].value.percent); break; case BACNET_SHED_TYPE_AMOUNT: - apdu_len = encode_context_real(&apdu[0], 2, + apdu_len = encode_context_real( + &apdu[0], 2, Requested_Shed_Level[object_index].value.amount); break; case BACNET_SHED_TYPE_LEVEL: default: - apdu_len = encode_context_unsigned(&apdu[0], 1, + apdu_len = encode_context_unsigned( + &apdu[0], 1, Requested_Shed_Level[object_index].value.level); break; } @@ -708,16 +928,19 @@ int Load_Control_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) case PROP_EXPECTED_SHED_LEVEL: switch (Expected_Shed_Level[object_index].type) { case BACNET_SHED_TYPE_PERCENT: - apdu_len = encode_context_unsigned(&apdu[0], 0, + apdu_len = encode_context_unsigned( + &apdu[0], 0, Expected_Shed_Level[object_index].value.percent); break; case BACNET_SHED_TYPE_AMOUNT: - apdu_len = encode_context_real(&apdu[0], 2, + apdu_len = encode_context_real( + &apdu[0], 2, Expected_Shed_Level[object_index].value.amount); break; case BACNET_SHED_TYPE_LEVEL: default: - apdu_len = encode_context_unsigned(&apdu[0], 1, + apdu_len = encode_context_unsigned( + &apdu[0], 1, Expected_Shed_Level[object_index].value.level); break; } @@ -725,16 +948,19 @@ int Load_Control_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) case PROP_ACTUAL_SHED_LEVEL: switch (Actual_Shed_Level[object_index].type) { case BACNET_SHED_TYPE_PERCENT: - apdu_len = encode_context_unsigned(&apdu[0], 0, + apdu_len = encode_context_unsigned( + &apdu[0], 0, Actual_Shed_Level[object_index].value.percent); break; case BACNET_SHED_TYPE_AMOUNT: - apdu_len = encode_context_real(&apdu[0], 2, + apdu_len = encode_context_real( + &apdu[0], 2, Actual_Shed_Level[object_index].value.amount); break; case BACNET_SHED_TYPE_LEVEL: default: - apdu_len = encode_context_unsigned(&apdu[0], 1, + apdu_len = encode_context_unsigned( + &apdu[0], 1, Actual_Shed_Level[object_index].value.level); break; } @@ -765,7 +991,8 @@ int Load_Control_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) } } else { if (rpdata->array_index <= MAX_SHED_LEVELS) { - apdu_len = encode_application_unsigned(&apdu[0], + apdu_len = encode_application_unsigned( + &apdu[0], Shed_Levels[object_index][rpdata->array_index - 1]); } else { rpdata->error_class = ERROR_CLASS_PROPERTY; @@ -802,7 +1029,8 @@ int Load_Control_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) } } else { if (rpdata->array_index <= MAX_SHED_LEVELS) { - characterstring_init_ansi(&char_string, + characterstring_init_ansi( + &char_string, Shed_Level_Descriptions[rpdata->array_index - 1]); apdu_len = encode_application_character_string( &apdu[0], &char_string); @@ -832,6 +1060,115 @@ int Load_Control_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) return apdu_len; } +/** + * @brief For a given object instance-number, writes to the property value + * @param object_instance - object-instance number of the object + * @param value - property value to be written + * @param priority - priority-array index value 1..16 + * @param error_class - the BACnet error class + * @param error_code - BACnet Error code + * + * @return true if values are within range and present-value is set. + */ +static bool Load_Control_Requested_Shed_Level_Write( + uint32_t object_instance, + BACNET_SHED_LEVEL *value, + uint8_t priority, + BACNET_ERROR_CLASS *error_class, + BACNET_ERROR_CODE *error_code) +{ + bool status = false; + unsigned int object_index = 0; + + (void)priority; + object_index = Load_Control_Instance_To_Index(object_instance); + if (object_index < MAX_LOAD_CONTROLS) { + switch (value->type) { + case BACNET_SHED_TYPE_PERCENT: + if (value->value.percent <= 100) { + Requested_Shed_Level[object_index].type = value->type; + Requested_Shed_Level[object_index].value.percent = + value->value.percent; + Load_Control_Request_Written[object_index] = true; + status = true; + } else { + *error_class = ERROR_CLASS_PROPERTY; + *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + } + break; + case BACNET_SHED_TYPE_AMOUNT: + if (value->value.amount >= 0.0f) { + Requested_Shed_Level[object_index].type = value->type; + Requested_Shed_Level[object_index].value.amount = + value->value.amount; + Load_Control_Request_Written[object_index] = true; + status = true; + } else { + *error_class = ERROR_CLASS_PROPERTY; + *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + } + break; + case BACNET_SHED_TYPE_LEVEL: + if (value->value.level <= MAX_SHED_LEVELS) { + Requested_Shed_Level[object_index].type = value->type; + Requested_Shed_Level[object_index].value.level = + value->value.level; + Load_Control_Request_Written[object_index] = true; + status = true; + } else { + *error_class = ERROR_CLASS_PROPERTY; + *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + } + break; + default: + *error_class = ERROR_CLASS_PROPERTY; + *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + break; + } + } else { + *error_class = ERROR_CLASS_OBJECT; + *error_code = ERROR_CODE_UNKNOWN_OBJECT; + } + + return status; +} + +/** + * @brief For a given object instance-number, writes to the property value + * @param object_instance - object-instance number of the object + * @param value - property value to be written + * @param priority - priority-array index value 1..16 + * @param error_class - the BACnet error class + * @param error_code - BACnet Error code + * + * @return true if values are within range and present-value is set. + */ +static bool Load_Control_Start_Time_Write( + uint32_t object_instance, + BACNET_DATE_TIME *value, + uint8_t priority, + BACNET_ERROR_CLASS *error_class, + BACNET_ERROR_CODE *error_code) +{ + bool status = false; + unsigned int object_index = 0; + + (void)priority; + object_index = Load_Control_Instance_To_Index(object_instance); + if (object_index < MAX_LOAD_CONTROLS) { + /* Write time and date and set written flag */ + datetime_copy_date(&Start_Time[object_index].date, &value->date); + datetime_copy_time(&Start_Time[object_index].time, &value->time); + Start_Time_Property_Written[object_index] = true; + status = true; + } else { + *error_class = ERROR_CLASS_OBJECT; + *error_code = ERROR_CODE_UNKNOWN_OBJECT; + } + + return status; +} + /* returns true if successful */ bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) { @@ -842,13 +1179,15 @@ bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) /* build here in case of error in time half of datetime */ BACNET_DATE start_date; - PRINTF("Load_Control_Write_Property(wp_data=%p)\n", wp_data); + debug_printf("Load_Control_Write_Property(wp_data=%p)\n", wp_data); if (wp_data == NULL) { - PRINTF("Load_Control_Write_Property() failure detected point A\n"); + debug_printf( + "Load_Control_Write_Property() failure detected point A\n"); return false; } if (wp_data->application_data_len < 0) { - PRINTF("Load_Control_Write_Property() failure detected point A.2\n"); + debug_printf( + "Load_Control_Write_Property() failure detected point A.2\n"); /* error while decoding - a smaller larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; @@ -856,11 +1195,13 @@ bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) } /* decode the some of the request */ - len = bacapp_decode_application_data( - wp_data->application_data, wp_data->application_data_len, &value); + len = bacapp_decode_known_property( + wp_data->application_data, wp_data->application_data_len, &value, + wp_data->object_type, wp_data->object_property); /* FIXME: len < application_data_len: more data? */ if (len < 0) { - PRINTF("Load_Control_Write_Property() failure detected point B\n"); + debug_printf( + "Load_Control_Write_Property() failure detected point B\n"); /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; @@ -869,7 +1210,8 @@ bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) /* only array properties can have array options */ if ((wp_data->object_property != PROP_SHED_LEVELS) && (wp_data->array_index != BACNET_ARRAY_ALL)) { - PRINTF("Load_Control_Write_Property() failure detected point C\n"); + debug_printf( + "Load_Control_Write_Property() failure detected point C\n"); wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; @@ -877,77 +1219,23 @@ bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) object_index = Load_Control_Instance_To_Index(wp_data->object_instance); switch (wp_data->object_property) { case PROP_REQUESTED_SHED_LEVEL: - len = bacapp_decode_context_data(wp_data->application_data, - wp_data->application_data_len, &value, - PROP_REQUESTED_SHED_LEVEL); - if (len == BACNET_STATUS_ERROR) { - PRINTF( - "Load_Control_Write_Property() failure detected point D\n"); - /* error! */ - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; - } else if (value.context_tag == 0) { - /* percent - Unsigned */ - Requested_Shed_Level[object_index].type = - BACNET_SHED_TYPE_PERCENT; - Requested_Shed_Level[object_index].value.percent = - value.type.Unsigned_Int; - status = true; - } else if (value.context_tag == 1) { - /* level - Unsigned */ - Requested_Shed_Level[object_index].type = - BACNET_SHED_TYPE_LEVEL; - Requested_Shed_Level[object_index].value.level = - value.type.Unsigned_Int; - status = true; - } else if (value.context_tag == 2) { - /* amount - REAL */ - Requested_Shed_Level[object_index].type = - BACNET_SHED_TYPE_AMOUNT; - Requested_Shed_Level[object_index].value.amount = - value.type.Real; - status = true; - } else { - PRINTF( - "Load_Control_Write_Property() failure detected point E\n"); - /* error! */ - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; - } + status = write_property_type_valid( + wp_data, &value, BACNET_APPLICATION_TAG_SHED_LEVEL); if (status) { - Load_Control_Request_Written[object_index] = true; + status = Load_Control_Requested_Shed_Level_Write( + wp_data->object_instance, &value.type.Shed_Level, + wp_data->priority, &wp_data->error_class, + &wp_data->error_code); } break; - case PROP_START_TIME: status = write_property_type_valid( - wp_data, &value, BACNET_APPLICATION_TAG_DATE); - if (!status) { - PRINTF( - "Load_Control_Write_Property() failure detected point F\n"); - /* don't continue if we don't have a valid date */ - break; - } - /* Hold the date until we are sure the time is also there */ - start_date = value.type.Date; - len = - bacapp_decode_application_data(wp_data->application_data + len, - wp_data->application_data_len - len, &value); - if (len) { - status = write_property_type_valid( - wp_data, &value, BACNET_APPLICATION_TAG_TIME); - if (status) { - /* Write time and date and set written flag */ - Start_Time[object_index].date = start_date; - Start_Time[object_index].time = value.type.Time; - Start_Time_Property_Written[object_index] = true; - } - } else { - PRINTF( - "Load_Control_Write_Property() failure detected point G\n"); - status = false; - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + wp_data, &value, BACNET_APPLICATION_TAG_DATETIME); + if (status) { + status = Load_Control_Start_Time_Write( + wp_data->object_instance, &value.type.Date_Time, + wp_data->priority, &wp_data->error_class, + &wp_data->error_code); } break; @@ -958,7 +1246,7 @@ bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) Shed_Duration[object_index] = value.type.Unsigned_Int; Load_Control_Request_Written[object_index] = true; } else { - PRINTF( + debug_printf( "Load_Control_Write_Property() failure detected point H\n"); } break; @@ -1004,12 +1292,13 @@ bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) } break; default: - PRINTF("Load_Control_Write_Property() failure detected point Z\n"); + debug_printf( + "Load_Control_Write_Property() failure detected point Z\n"); wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; } - PRINTF("Load_Control_Write_Property() returning status=%d\n", status); + debug_printf("Load_Control_Write_Property() returning status=%d\n", status); return status; } diff --git a/src/bacnet/basic/object/lc.h b/src/bacnet/basic/object/lc.h index 150f73da..aa88a925 100644 --- a/src/bacnet/basic/object/lc.h +++ b/src/bacnet/basic/object/lc.h @@ -16,6 +16,14 @@ #include "bacnet/rp.h" #include "bacnet/wp.h" +typedef enum bacnet_load_control_state { + SHED_INACTIVE, + SHED_REQUEST_PENDING, + SHED_NON_COMPLIANT, + SHED_COMPLIANT, + MAX_LOAD_CONTROL_STATE +} BACNET_LOAD_CONTROL_STATE; + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -50,9 +58,21 @@ extern "C" { BACNET_STACK_EXPORT void Load_Control_Init( void); + BACNET_STACK_EXPORT - void Load_Control_State_Machine( - int object_index); + unsigned Load_Control_Priority_For_Writing( + uint32_t object_instance); + BACNET_STACK_EXPORT + bool Load_Control_Priority_For_Writing_Set( + uint32_t object_instance, unsigned priority); + BACNET_STACK_EXPORT + bool Load_Control_Manipulated_Variable_Reference( + uint32_t object_instance, + BACNET_OBJECT_PROPERTY_REFERENCE * object_property_reference); + BACNET_STACK_EXPORT + bool Load_Control_Manipulated_Variable_Reference_Set( + uint32_t object_instance, + BACNET_OBJECT_PROPERTY_REFERENCE * object_property_reference); BACNET_STACK_EXPORT int Load_Control_Read_Property( @@ -62,6 +82,18 @@ extern "C" { bool Load_Control_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data); + /* functions used for unit testing */ + BACNET_STACK_EXPORT + void Load_Control_State_Machine( + int object_index, + BACNET_DATE_TIME *bdatetime); + BACNET_STACK_EXPORT + BACNET_LOAD_CONTROL_STATE Load_Control_State( + int object_index); + BACNET_STACK_EXPORT + BACNET_OBJECT_ID Load_Control_Object_ID( + int object_index); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/bacnet/config.h b/src/bacnet/config.h index e2aa6011..54e5cef5 100644 --- a/src/bacnet/config.h +++ b/src/bacnet/config.h @@ -162,6 +162,7 @@ defined(BACAPP_FDT_ENTRY) || \ defined(BACAPP_ACTION_COMMAND) || \ defined(BACAPP_SCALE) || \ + defined(BACAPP_SHED_LEVEL) || \ defined(BACAPP_TYPES_EXTRA)) #define BACAPP_ALL #endif @@ -206,6 +207,7 @@ #define BACAPP_FDT_ENTRY #define BACAPP_ACTION_COMMAND #define BACAPP_SCALE +#define BACAPP_SHED_LEVEL #endif #if defined(BACAPP_DOUBLE) || \ @@ -225,7 +227,8 @@ defined(BACAPP_BDT_ENTRY) || \ defined(BACAPP_FDT_ENTRY) || \ defined(BACAPP_ACTION_COMMAND) || \ - defined(BACAPP_SCALE) + defined(BACAPP_SCALE) || \ + defined(BACAPP_SHED_LEVEL) #define BACAPP_COMPLEX_TYPES #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 17efc950..dc478eb4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -133,7 +133,7 @@ list(APPEND testdirs bacnet/basic/object/csv bacnet/basic/object/device bacnet/basic/object/iv - #bacnet/basic/object/lc #Tests skipped, redesign to use only API + bacnet/basic/object/lc bacnet/basic/object/lo bacnet/basic/object/lsp bacnet/basic/object/lsz diff --git a/test/bacnet/basic/object/ai/CMakeLists.txt b/test/bacnet/basic/object/ai/CMakeLists.txt index d178cc02..f5ede5a3 100644 --- a/test/bacnet/basic/object/ai/CMakeLists.txt +++ b/test/bacnet/basic/object/ai/CMakeLists.txt @@ -28,7 +28,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -67,7 +67,7 @@ add_executable(${PROJECT_NAME} # Test and test library files ./src/main.c ./stubs.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/ao/CMakeLists.txt b/test/bacnet/basic/object/ao/CMakeLists.txt index dde0ed10..61c7ba53 100644 --- a/test/bacnet/basic/object/ao/CMakeLists.txt +++ b/test/bacnet/basic/object/ao/CMakeLists.txt @@ -26,7 +26,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -63,7 +63,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/sys/keylist.c # Test and test library files ./src/main.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/av/CMakeLists.txt b/test/bacnet/basic/object/av/CMakeLists.txt index e1ae7ecf..07ed7ec7 100644 --- a/test/bacnet/basic/object/av/CMakeLists.txt +++ b/test/bacnet/basic/object/av/CMakeLists.txt @@ -28,7 +28,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -67,7 +67,7 @@ add_executable(${PROJECT_NAME} # Test and test library files ./src/main.c ./stubs.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/bacfile/CMakeLists.txt b/test/bacnet/basic/object/bacfile/CMakeLists.txt index f15a0e22..c4d13057 100644 --- a/test/bacnet/basic/object/bacfile/CMakeLists.txt +++ b/test/bacnet/basic/object/bacfile/CMakeLists.txt @@ -29,6 +29,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} ${TST_DIR}/ztest/include + ${TST_DIR}/bacnet/basic/object/test ) add_executable(${PROJECT_NAME} @@ -65,9 +66,9 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/special_event.c # Test and test library files ./src/main.c - ../mock/apdu_mock.c - ../mock/device_mock.c - ../mock/tsm_mock.c + ${TST_DIR}/bacnet/basic/object/test/apdu_mock.c + ${TST_DIR}/bacnet/basic/object/test/device_mock.c + ${TST_DIR}/bacnet/basic/object/test/tsm_mock.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/bi/CMakeLists.txt b/test/bacnet/basic/object/bi/CMakeLists.txt index eefc1846..9ae77acf 100644 --- a/test/bacnet/basic/object/bi/CMakeLists.txt +++ b/test/bacnet/basic/object/bi/CMakeLists.txt @@ -29,7 +29,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -68,7 +68,7 @@ add_executable(${PROJECT_NAME} # Test and test library files ./src/main.c ./stubs.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/bitstring_value/CMakeLists.txt b/test/bacnet/basic/object/bitstring_value/CMakeLists.txt index bf31c6cd..f1df6b6e 100644 --- a/test/bacnet/basic/object/bitstring_value/CMakeLists.txt +++ b/test/bacnet/basic/object/bitstring_value/CMakeLists.txt @@ -27,7 +27,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -64,7 +64,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/special_event.c # Test and test library files ./src/main.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/blo/CMakeLists.txt b/test/bacnet/basic/object/blo/CMakeLists.txt index 79aed77f..8884ddd7 100644 --- a/test/bacnet/basic/object/blo/CMakeLists.txt +++ b/test/bacnet/basic/object/blo/CMakeLists.txt @@ -62,7 +62,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/special_event.c # Test and test library files ./src/main.c - ../mock/device_mock.c + ${TST_DIR}/bacnet/basic/object/test/device_mock.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/bo/CMakeLists.txt b/test/bacnet/basic/object/bo/CMakeLists.txt index fa73d9d4..088d67c6 100644 --- a/test/bacnet/basic/object/bo/CMakeLists.txt +++ b/test/bacnet/basic/object/bo/CMakeLists.txt @@ -27,7 +27,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -65,7 +65,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/sys/keylist.c # Test and test library files ./src/main.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/bv/CMakeLists.txt b/test/bacnet/basic/object/bv/CMakeLists.txt index b65848a3..6687210a 100644 --- a/test/bacnet/basic/object/bv/CMakeLists.txt +++ b/test/bacnet/basic/object/bv/CMakeLists.txt @@ -29,7 +29,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -67,7 +67,7 @@ add_executable(${PROJECT_NAME} # Test and test library files ./src/main.c ./stubs.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/calendar/CMakeLists.txt b/test/bacnet/basic/object/calendar/CMakeLists.txt index c47bdd18..15e7f749 100644 --- a/test/bacnet/basic/object/calendar/CMakeLists.txt +++ b/test/bacnet/basic/object/calendar/CMakeLists.txt @@ -64,7 +64,7 @@ add_executable(${PROJECT_NAME} # Test and test library files ./src/main.c ./stubs.c - ../mock/device_mock.c + ${TST_DIR}/bacnet/basic/object/test/device_mock.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/channel/CMakeLists.txt b/test/bacnet/basic/object/channel/CMakeLists.txt index dcbad153..c78db271 100644 --- a/test/bacnet/basic/object/channel/CMakeLists.txt +++ b/test/bacnet/basic/object/channel/CMakeLists.txt @@ -60,7 +60,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/special_event.c # Test and test library files ./src/main.c - ../mock/device_mock.c + ${TST_DIR}/bacnet/basic/object/test/device_mock.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/color_object/CMakeLists.txt b/test/bacnet/basic/object/color_object/CMakeLists.txt index 995a1037..3e6ff1f7 100644 --- a/test/bacnet/basic/object/color_object/CMakeLists.txt +++ b/test/bacnet/basic/object/color_object/CMakeLists.txt @@ -63,7 +63,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/special_event.c # Test and test library files ./src/main.c - ../mock/device_mock.c + ${TST_DIR}/bacnet/basic/object/test/device_mock.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/color_temperature/CMakeLists.txt b/test/bacnet/basic/object/color_temperature/CMakeLists.txt index a1d3dcb8..61c64993 100644 --- a/test/bacnet/basic/object/color_temperature/CMakeLists.txt +++ b/test/bacnet/basic/object/color_temperature/CMakeLists.txt @@ -63,7 +63,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/special_event.c # Test and test library files ./src/main.c - ../mock/device_mock.c + ${TST_DIR}/bacnet/basic/object/test/device_mock.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/command/CMakeLists.txt b/test/bacnet/basic/object/command/CMakeLists.txt index f34c05e0..b7eda636 100644 --- a/test/bacnet/basic/object/command/CMakeLists.txt +++ b/test/bacnet/basic/object/command/CMakeLists.txt @@ -27,7 +27,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -61,7 +61,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/special_event.c # Test and test library files ./src/main.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/credential_data_input/CMakeLists.txt b/test/bacnet/basic/object/credential_data_input/CMakeLists.txt index 76041f29..c5c565f5 100644 --- a/test/bacnet/basic/object/credential_data_input/CMakeLists.txt +++ b/test/bacnet/basic/object/credential_data_input/CMakeLists.txt @@ -27,7 +27,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -64,7 +64,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/special_event.c # Test and test library files ./src/main.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/lc/CMakeLists.txt b/test/bacnet/basic/object/lc/CMakeLists.txt index 8f5b1250..747d220d 100644 --- a/test/bacnet/basic/object/lc/CMakeLists.txt +++ b/test/bacnet/basic/object/lc/CMakeLists.txt @@ -23,11 +23,15 @@ set(ZTST_DIR "${TST_DIR}/ztest/src") add_compile_definitions( BIG_ENDIAN=0 CONFIG_ZTEST=1 + BACAPP_MINIMAL=1 + BACAPP_DATETIME=1 + BACAPP_SHED_LEVEL=1 ) include_directories( ${SRC_DIR} ${TST_DIR}/ztest/include + ${TST_DIR}/bacnet/basic/object/test ) add_executable(${PROJECT_NAME} @@ -47,11 +51,16 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/bactext.c ${SRC_DIR}/bacnet/basic/object/ao.c ${SRC_DIR}/bacnet/basic/sys/bigend.c - ${SRC_DIR}/bacnet/datetime.c + ${SRC_DIR}/bacnet/basic/sys/debug.c + ${SRC_DIR}/bacnet/basic/sys/keylist.c ${SRC_DIR}/bacnet/basic/sys/days.c + ${SRC_DIR}/bacnet/cov.c + ${SRC_DIR}/bacnet/datetime.c ${SRC_DIR}/bacnet/indtext.c ${SRC_DIR}/bacnet/hostnport.c ${SRC_DIR}/bacnet/lighting.c + ${SRC_DIR}/bacnet/proplist.c + ${SRC_DIR}/bacnet/rp.c ${SRC_DIR}/bacnet/timestamp.c ${SRC_DIR}/bacnet/wp.c ${SRC_DIR}/bacnet/weeklyschedule.c @@ -59,9 +68,10 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/dailyschedule.c ${SRC_DIR}/bacnet/calendar_entry.c ${SRC_DIR}/bacnet/special_event.c - ./stubs.c # Test and test library files ./src/main.c + ${TST_DIR}/bacnet/basic/object/test/datetime_local.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/lc/src/main.c b/test/bacnet/basic/object/lc/src/main.c index cdf1622a..d35c81a5 100644 --- a/test/bacnet/basic/object/lc/src/main.c +++ b/test/bacnet/basic/object/lc/src/main.c @@ -13,6 +13,7 @@ #include #include #include +#include /* TODO: Refactor basic/object/lc.c to avoid duplication of the following: */ @@ -55,7 +56,7 @@ static void Load_Control_WriteProperty_Request_Shed_Level(int instance, unsigned level) { bool status = false; - BACNET_APPLICATION_DATA_VALUE value; + BACNET_APPLICATION_DATA_VALUE value = { 0 }; BACNET_WRITE_PROPERTY_DATA wp_data; wp_data.object_type = OBJECT_LOAD_CONTROL; @@ -63,12 +64,11 @@ Load_Control_WriteProperty_Request_Shed_Level(int instance, unsigned level) wp_data.array_index = BACNET_ARRAY_ALL; wp_data.priority = BACNET_NO_PRIORITY; wp_data.object_property = PROP_REQUESTED_SHED_LEVEL; - value.context_specific = true; - value.context_tag = 1; - value.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT; - value.type.Unsigned_Int = level; - wp_data.application_data_len = - bacapp_encode_data(&wp_data.application_data[0], &value); + value.type.Shed_Level.type = BACNET_SHED_TYPE_LEVEL; + value.type.Shed_Level.value.level = level; + wp_data.application_data_len = bacapp_encode_known_property( + &wp_data.application_data[0], &value, wp_data.object_type, + wp_data.object_property); zassert_true(wp_data.application_data_len > 0, NULL); status = Load_Control_Write_Property(&wp_data); zassert_true(status, NULL); @@ -91,7 +91,7 @@ static void Load_Control_WriteProperty_Enable(int instance, bool enable) value.tag = BACNET_APPLICATION_TAG_BOOLEAN; value.type.Boolean = enable; wp_data.application_data_len = - bacapp_encode_data(&wp_data.application_data[0], &value); + bacapp_encode_application_data(&wp_data.application_data[0], &value); zassert_true(wp_data.application_data_len > 0, NULL); status = Load_Control_Write_Property(&wp_data); zassert_true(status, NULL); @@ -114,7 +114,7 @@ Load_Control_WriteProperty_Shed_Duration(int instance, unsigned duration) value.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT; value.type.Unsigned_Int = duration; wp_data.application_data_len = - bacapp_encode_data(&wp_data.application_data[0], &value); + bacapp_encode_application_data(&wp_data.application_data[0], &value); zassert_true(wp_data.application_data_len > 0, NULL); status = Load_Control_Write_Property(&wp_data); zassert_true(status, NULL); @@ -137,7 +137,7 @@ Load_Control_WriteProperty_Duty_Window(int instance, unsigned duration) value.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT; value.type.Unsigned_Int = duration; wp_data.application_data_len = - bacapp_encode_data(&wp_data.application_data[0], &value); + bacapp_encode_application_data(&wp_data.application_data[0], &value); zassert_true(wp_data.application_data_len > 0, NULL); status = Load_Control_Write_Property(&wp_data); zassert_true(status, NULL); @@ -155,18 +155,12 @@ static void Load_Control_WriteProperty_Start_Time_Wildcards(int instance) wp_data.array_index = BACNET_ARRAY_ALL; wp_data.priority = BACNET_NO_PRIORITY; wp_data.object_property = PROP_START_TIME; - value.context_specific = false; - value.context_tag = 0; - value.tag = BACNET_APPLICATION_TAG_DATE; - datetime_date_wildcard_set(&value.type.Date); - wp_data.application_data_len = - bacapp_encode_data(&wp_data.application_data[0], &value); - zassert_true(wp_data.application_data_len > 0, NULL); - len = wp_data.application_data_len; - value.tag = BACNET_APPLICATION_TAG_TIME; - datetime_time_wildcard_set(&value.type.Time); - wp_data.application_data_len = - bacapp_encode_data(&wp_data.application_data[len], &value); + value.tag = BACNET_APPLICATION_TAG_DATETIME; + datetime_date_wildcard_set(&value.type.Date_Time.date); + datetime_time_wildcard_set(&value.type.Date_Time.time); + wp_data.application_data_len = bacapp_encode_known_property( + &wp_data.application_data[0], &value, wp_data.object_type, + wp_data.object_property); zassert_true(wp_data.application_data_len > 0, NULL); wp_data.application_data_len += len; status = Load_Control_Write_Property(&wp_data); @@ -193,18 +187,13 @@ static void Load_Control_WriteProperty_Start_Time( wp_data.array_index = BACNET_ARRAY_ALL; wp_data.priority = BACNET_NO_PRIORITY; wp_data.object_property = PROP_START_TIME; - value.context_specific = false; - value.context_tag = 0; - value.tag = BACNET_APPLICATION_TAG_DATE; - datetime_set_date(&value.type.Date, year, month, day); - wp_data.application_data_len = - bacapp_encode_data(&wp_data.application_data[0], &value); - zassert_true(wp_data.application_data_len > 0, NULL); - len = wp_data.application_data_len; - value.tag = BACNET_APPLICATION_TAG_TIME; - datetime_set_time(&value.type.Time, hour, minute, seconds, hundredths); - wp_data.application_data_len = - bacapp_encode_data(&wp_data.application_data[len], &value); + value.tag = BACNET_APPLICATION_TAG_DATETIME; + datetime_set_date(&value.type.Date_Time.date, year, month, day); + datetime_set_time( + &value.type.Date_Time.time, hour, minute, seconds, hundredths); + wp_data.application_data_len = bacapp_encode_known_property( + &wp_data.application_data[0], &value, wp_data.object_type, + wp_data.object_property); zassert_true(wp_data.application_data_len > 0, NULL); wp_data.application_data_len += len; status = Load_Control_Write_Property(&wp_data); @@ -217,42 +206,45 @@ ZTEST(lc_tests, testLoadControlStateMachine) static void testLoadControlStateMachine(void) #endif { - // TODO: unsigned i = 0, j = 0; - uint8_t level = 0; + unsigned i = 0, j = 0; + float level = 0; + unsigned count = 0; + BACNET_DATE_TIME bdatetime = { 0 }; + uint32_t object_instance = 0; + BACNET_OBJECT_PROPERTY_REFERENCE object_property_reference; + bool status; + Analog_Output_Init(); Load_Control_Init(); - - // TODO: /* validate the triggers for each state change */ - // TODO: for (j = 0; j < 20; j++) { - // TODO: Load_Control_State_Machine(0); - // TODO: for (i = 0; i < MAX_LOAD_CONTROLS; i++) { - // TODO: zassert_equal(Load_Control_State[i], SHED_INACTIVE, - // NULL); - // TODO: } - // TODO: } - + object_instance = Load_Control_Index_To_Instance(0); + /* validate the triggers for each state change */ + for (j = 0; j < 20; j++) { + Load_Control_State_Machine(0, &bdatetime); + count = Load_Control_Count(); + for (i = 0; i < count; i++) { + zassert_equal(Load_Control_State(i), SHED_INACTIVE, NULL); + } + } /* SHED_REQUEST_PENDING */ /* CancelShed - Start time has wildcards */ Load_Control_WriteProperty_Enable(0, true); Load_Control_WriteProperty_Shed_Duration(0, 60); Load_Control_WriteProperty_Start_Time_Wildcards(0); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_INACTIVE, NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_INACTIVE, NULL); /* CancelShed - Requested_Shed_Level equal to default value */ Load_Control_Init(); Load_Control_WriteProperty_Request_Shed_Level(0, 0); Load_Control_WriteProperty_Start_Time(0, 2007, 2, 27, 15, 0, 0, 0); Load_Control_WriteProperty_Shed_Duration(0, 5); - // TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 15, 0, 0, 0); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_INACTIVE, NULL); + datetime_set_values(&bdatetime, 2007, 2, 27, 15, 0, 0, 0); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_INACTIVE, NULL); /* CancelShed - Non-default values, but Start time is passed */ Load_Control_Init(); @@ -260,12 +252,11 @@ static void testLoadControlStateMachine(void) Load_Control_WriteProperty_Request_Shed_Level(0, 1); Load_Control_WriteProperty_Shed_Duration(0, 5); Load_Control_WriteProperty_Start_Time(0, 2007, 2, 27, 15, 0, 0, 0); - // TODO: datetime_set_values(&Current_Time, 2007, 2, 28, 15, 0, 0, 0); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_INACTIVE, NULL); + datetime_set_values(&bdatetime, 2007, 2, 28, 15, 0, 0, 0); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_INACTIVE, NULL); /* ReconfigurePending - new write received while pending */ Load_Control_Init(); @@ -273,35 +264,27 @@ static void testLoadControlStateMachine(void) Load_Control_WriteProperty_Request_Shed_Level(0, 1); Load_Control_WriteProperty_Shed_Duration(0, 5); Load_Control_WriteProperty_Start_Time(0, 2007, 2, 27, 15, 0, 0, 0); - // TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 5, 0, 0, 0); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); + datetime_set_values(&bdatetime, 2007, 2, 27, 5, 0, 0, 0); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); Load_Control_WriteProperty_Request_Shed_Level(0, 2); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); Load_Control_WriteProperty_Shed_Duration(0, 6); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); Load_Control_WriteProperty_Duty_Window(0, 60); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); Load_Control_WriteProperty_Start_Time(0, 2007, 2, 27, 15, 0, 0, 1); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); /* CannotMeetShed -> FinishedUnsuccessfulShed */ Load_Control_Init(); @@ -309,24 +292,35 @@ static void testLoadControlStateMachine(void) Load_Control_WriteProperty_Request_Shed_Level(0, 1); Load_Control_WriteProperty_Shed_Duration(0, 120); Load_Control_WriteProperty_Start_Time(0, 2007, 2, 27, 15, 0, 0, 0); - // TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 5, 0, 0, 0); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); + datetime_set_values(&bdatetime, 2007, 2, 27, 5, 0, 0, 0); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); /* set to lowest value so we cannot meet the shed level */ - // TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 16, 0, 0, 0); - Analog_Output_Present_Value_Set(0, 0, 16); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_NON_COMPLIANT, NULL); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_NON_COMPLIANT, NULL); + datetime_set_values(&bdatetime, 2007, 2, 27, 16, 0, 0, 0); + + Load_Control_Manipulated_Variable_Reference( + object_instance, &object_property_reference); + if ((object_property_reference.object_identifier.type == + OBJECT_ANALOG_OUTPUT) && + (object_property_reference.property_identifier == PROP_PRESENT_VALUE)) { + status = Analog_Output_Present_Value_Set( + object_property_reference.object_identifier.instance, 0.0f, + BACNET_MAX_PRIORITY); + zassert_true(status, NULL); + } else { + zassert_true(false, NULL); + } + + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_NON_COMPLIANT, NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_NON_COMPLIANT, NULL); /* FinishedUnsuccessfulShed */ - // TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 23, 0, 0, 0); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_INACTIVE, NULL); + datetime_set_values(&bdatetime, 2007, 2, 27, 23, 0, 0, 0); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_INACTIVE, NULL); /* CannotMeetShed -> UnsuccessfulShedReconfigured */ Load_Control_Init(); @@ -334,45 +328,78 @@ static void testLoadControlStateMachine(void) Load_Control_WriteProperty_Request_Shed_Level(0, 1); Load_Control_WriteProperty_Shed_Duration(0, 120); Load_Control_WriteProperty_Start_Time(0, 2007, 2, 27, 15, 0, 0, 0); - // TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 5, 0, 0, 0); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); + datetime_set_values(&bdatetime, 2007, 2, 27, 5, 0, 0, 0); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); /* set to lowest value so we cannot meet the shed level */ - // TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 16, 0, 0, 0); - Analog_Output_Present_Value_Set(0, 0, 16); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_NON_COMPLIANT, NULL); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_NON_COMPLIANT, NULL); + datetime_set_values(&bdatetime, 2007, 2, 27, 16, 0, 0, 0); + Load_Control_Manipulated_Variable_Reference( + object_instance, &object_property_reference); + if ((object_property_reference.object_identifier.type == + OBJECT_ANALOG_OUTPUT) && + (object_property_reference.property_identifier == PROP_PRESENT_VALUE)) { + status = Analog_Output_Present_Value_Set( + object_property_reference.object_identifier.instance, 0.0f, + BACNET_MAX_PRIORITY); + zassert_true(status, NULL); + } else { + zassert_true(false, NULL); + } + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_NON_COMPLIANT, NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_NON_COMPLIANT, NULL); /* FinishedUnsuccessfulShed */ Load_Control_WriteProperty_Start_Time(0, 2007, 2, 27, 16, 0, 0, 0); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_REQUEST_PENDING, - // NULL); - // TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 16, 0, 1, 0); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_NON_COMPLIANT, NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_REQUEST_PENDING, NULL); + datetime_set_values(&bdatetime, 2007, 2, 27, 16, 0, 1, 0); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_NON_COMPLIANT, NULL); /* CanNowComplyWithShed */ - Analog_Output_Present_Value_Set(0, 100, 16); - // TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 16, 0, 2, 0); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_COMPLIANT, NULL); - level = Analog_Output_Present_Value(0); - // TODO: Fails: zassert_equal(level, 90, NULL); + Load_Control_Manipulated_Variable_Reference( + object_instance, &object_property_reference); + if ((object_property_reference.object_identifier.type == + OBJECT_ANALOG_OUTPUT) && + (object_property_reference.property_identifier == PROP_PRESENT_VALUE)) { + status = Analog_Output_Present_Value_Set( + object_property_reference.object_identifier.instance, 100.0f, + BACNET_MAX_PRIORITY); + zassert_true(status, NULL); + } else { + zassert_true(false, NULL); + } + datetime_set_values(&bdatetime, 2007, 2, 27, 16, 0, 2, 0); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_COMPLIANT, NULL); + Load_Control_Manipulated_Variable_Reference( + object_instance, &object_property_reference); + if ((object_property_reference.object_identifier.type == + OBJECT_ANALOG_OUTPUT) && + (object_property_reference.property_identifier == PROP_PRESENT_VALUE)) { + level = Analog_Output_Present_Value( + object_property_reference.object_identifier.instance); + } else { + zassert_true(false, NULL); + } + zassert_false(islessgreater(90.0f, level), "AO Present Value = %f", level); /* FinishedSuccessfulShed */ - // TODO: datetime_set_values(&Current_Time, 2007, 2, 27, 23, 0, 0, 0); - Load_Control_State_Machine(0); - // TODO: zassert_equal(Load_Control_State[0], SHED_INACTIVE, NULL); - level = Analog_Output_Present_Value(0); - // TODO: Fails: zassert_equal(level, 100, NULL); - (void)level; // TODO: remove when level will be checked + datetime_set_values(&bdatetime, 2007, 2, 27, 23, 0, 0, 0); + Load_Control_State_Machine(0, &bdatetime); + zassert_equal(Load_Control_State(0), SHED_INACTIVE, NULL); + if ((object_property_reference.object_identifier.type == + OBJECT_ANALOG_OUTPUT) && + (object_property_reference.property_identifier == PROP_PRESENT_VALUE)) { + level = Analog_Output_Present_Value( + object_property_reference.object_identifier.instance); + } else { + zassert_true(false, NULL); + } + zassert_false(islessgreater(100.0f, level), "AO Present Value = %f", level); } #ifndef MAX_LOAD_CONTROLS @@ -421,56 +448,21 @@ ZTEST(lc_tests, test_Load_Control_Read_Write_Property) static void test_Load_Control_Read_Write_Property(void) #endif { - uint8_t apdu[MAX_APDU] = { 0 }; - int len = 0; - int test_len = 0; - BACNET_READ_PROPERTY_DATA rpdata; - /* for decode value data */ - BACNET_APPLICATION_DATA_VALUE value; - const int *pRequired = NULL; - const int *pOptional = NULL; - const int *pProprietary = NULL; + bool status = false; unsigned count = 0; - uint32_t object_instance = 0; - - zassert_equal(Load_Control_Read_Property(NULL), 0, NULL); - zassert_false(Load_Control_Write_Property(NULL), NULL); + uint32_t object_instance = BACNET_MAX_INSTANCE, test_object_instance = 0; + const int skip_fail_property_list[] = { -1 }; object_instance = Load_Control_Index_To_Instance(0); Load_Control_Init(); count = Load_Control_Count(); zassert_true(count > 0, NULL); - rpdata.application_data = &apdu[0]; - rpdata.application_data_len = sizeof(apdu); - rpdata.object_type = OBJECT_LOAD_CONTROL; - rpdata.object_instance = object_instance; - Load_Control_Property_Lists(&pRequired, &pOptional, &pProprietary); - while ((*pRequired) != -1) { - rpdata.object_property = *pRequired; - rpdata.array_index = BACNET_ARRAY_ALL; - len = Load_Control_Read_Property(&rpdata); - zassert_not_equal(len, BACNET_STATUS_ERROR, NULL); - if (len > 0) { - test_len = bacapp_decode_application_data( - rpdata.application_data, (uint8_t)rpdata.application_data_len, - &value); - zassert_true(test_len >= 0, NULL); - } - pRequired++; - } - while ((*pOptional) != -1) { - rpdata.object_property = *pOptional; - rpdata.array_index = BACNET_ARRAY_ALL; - len = Load_Control_Read_Property(&rpdata); - zassert_not_equal(len, BACNET_STATUS_ERROR, NULL); - if (len > 0) { - test_len = bacapp_decode_application_data( - rpdata.application_data, (uint8_t)rpdata.application_data_len, - &value); - zassert_true(test_len >= 0, NULL); - } - pOptional++; - } + test_object_instance = Load_Control_Index_To_Instance(0); + zassert_equal(object_instance, test_object_instance, NULL); + bacnet_object_properties_read_write_test( + OBJECT_LOAD_CONTROL, object_instance, Load_Control_Property_Lists, + Load_Control_Read_Property, Load_Control_Write_Property, + skip_fail_property_list); } static bool init_wp_data_and_value( @@ -529,136 +521,6 @@ static void test_ShedInactive_gets_RcvShedRequests(void) zassert_false(Load_Control_Write_Property(&wp_data), NULL); zassert_equal(wp_data.error_class, ERROR_CLASS_PROPERTY, NULL); zassert_equal(wp_data.error_code, ERROR_CODE_VALUE_OUT_OF_RANGE, NULL); - - /* Verify calls to dependencies are properly made */ - // object_property == PROP_REQUESTED_SHED_LEVEL calls - // bacapp_decode_context_data() object_property == PROP_START_TIME calls - // bacapp_decode_application_data() object_property == PROP_SHED_DURATION - // calls nothing object_property == PROP_DUTY_WINDOW calls nothing - // object_property == PROP_SHED_LEVELS calls nothing - // object_property == PROP_ENABLE calls nothing - // default returns error -} - -#if defined(CONFIG_ZTEST_NEW_API) -ZTEST(lc_tests, test_ShedReqPending_gets_ReconfigPending) -#else -static void test_ShedReqPending_gets_ReconfigPending(void) -#endif -{ -#ifndef UNIT_TESTING - ztest_test_skip(); -#endif -} - -#if defined(CONFIG_ZTEST_NEW_API) -ZTEST(lc_tests, test_ShedReqPending_gets_CancelShed) -#else -static void test_ShedReqPending_gets_CancelShed(void) -#endif -{ -#ifndef UNIT_TESTING - ztest_test_skip(); -#endif -} - -#if defined(CONFIG_ZTEST_NEW_API) -ZTEST(lc_tests, test_ShedReqPending_gets_CannotMeetShed) -#else -static void test_ShedReqPending_gets_CannotMeetShed(void) -#endif -{ -#ifndef UNIT_TESTING - ztest_test_skip(); -#endif -} - -#if defined(CONFIG_ZTEST_NEW_API) -ZTEST(lc_tests, test_ShedReqPending_gets_PrepareToShed) -#else -static void test_ShedReqPending_gets_PrepareToShed(void) -#endif -{ -#ifndef UNIT_TESTING - ztest_test_skip(); -#endif -} - -#if defined(CONFIG_ZTEST_NEW_API) -ZTEST(lc_tests, test_ShedReqPending_gets_AbleToMeetShed) -#else -static void test_ShedReqPending_gets_AbleToMeetShed(void) -#endif -{ -#ifndef UNIT_TESTING - ztest_test_skip(); -#endif -} - -#if defined(CONFIG_ZTEST_NEW_API) -ZTEST(lc_tests, test_ShedNonCommpliant_gets_UnsuccessfulShedReconfig) -#else -static void test_ShedNonCommpliant_gets_UnsuccessfulShedReconfig(void) -#endif -{ -#ifndef UNIT_TESTING - ztest_test_skip(); -#endif -} - -#if defined(CONFIG_ZTEST_NEW_API) -ZTEST(lc_tests, test_ShedNonCommpliant_gets_FinishedUnsuccessfulShed) -#else -static void test_ShedNonCommpliant_gets_FinishedUnsuccessfulShed(void) -#endif -{ -#ifndef UNIT_TESTING - ztest_test_skip(); -#endif -} - -#if defined(CONFIG_ZTEST_NEW_API) -ZTEST(lc_tests, test_ShedNonCommpliant_gets_CanNowComplyWithShed) -#else -static void test_ShedNonCommpliant_gets_CanNowComplyWithShed(void) -#endif -{ -#ifndef UNIT_TESTING - ztest_test_skip(); -#endif -} - -#if defined(CONFIG_ZTEST_NEW_API) -ZTEST(lc_tests, test_ShedCommpliant_gets_FinishedSuccessfulShed) -#else -static void test_ShedCommpliant_gets_FinishedSuccessfulShed(void) -#endif -{ -#ifndef UNIT_TESTING - ztest_test_skip(); -#endif -} - -#if defined(CONFIG_ZTEST_NEW_API) -ZTEST(lc_tests, test_ShedCommpliant_gets_SuccessfulShedReconfig) -#else -static void test_ShedCommpliant_gets_SuccessfulShedReconfig(void) -#endif -{ -#ifndef UNIT_TESTING - ztest_test_skip(); -#endif -} - -#if defined(CONFIG_ZTEST_NEW_API) -ZTEST(lc_tests, test_ShedCommpliant_gets_CanNoLongerComplyWithShed) -#else -static void test_ShedCommpliant_gets_CanNoLongerComplyWithShed(void) -#endif -{ -#ifndef UNIT_TESTING - ztest_test_skip(); -#endif } /** @@ -675,18 +537,7 @@ void test_main(void) ztest_unit_test(test_Load_Control_Count), ztest_unit_test(test_Load_Control_Read_Write_Property), ztest_unit_test(testLoadControlStateMachine), - ztest_unit_test(test_ShedInactive_gets_RcvShedRequests), - ztest_unit_test(test_ShedReqPending_gets_ReconfigPending), - ztest_unit_test(test_ShedReqPending_gets_CancelShed), - ztest_unit_test(test_ShedReqPending_gets_CannotMeetShed), - ztest_unit_test(test_ShedReqPending_gets_PrepareToShed), - ztest_unit_test(test_ShedReqPending_gets_AbleToMeetShed), - ztest_unit_test(test_ShedNonCommpliant_gets_UnsuccessfulShedReconfig), - ztest_unit_test(test_ShedNonCommpliant_gets_FinishedUnsuccessfulShed), - ztest_unit_test(test_ShedNonCommpliant_gets_CanNowComplyWithShed), - ztest_unit_test(test_ShedCommpliant_gets_FinishedSuccessfulShed), - ztest_unit_test(test_ShedCommpliant_gets_SuccessfulShedReconfig), - ztest_unit_test(test_ShedCommpliant_gets_CanNoLongerComplyWithShed)); + ztest_unit_test(test_ShedInactive_gets_RcvShedRequests)); ztest_run_test_suite(lc_tests); } diff --git a/test/bacnet/basic/object/lc/stubs.c b/test/bacnet/basic/object/lc/stubs.c deleted file mode 100644 index 154332f7..00000000 --- a/test/bacnet/basic/object/lc/stubs.c +++ /dev/null @@ -1,44 +0,0 @@ -/************************************************************************** - * - * Copyright (C) 2006 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. - * - *********************************************************************/ - -/* Binary Input Objects customize for your use */ - -#include -#include -#include "bacnet/bacapp.h" -#include "bacnet/datetime.h" - -void datetime_init(void) -{ -} - -bool datetime_local( - BACNET_DATE *bdate, - BACNET_TIME *btime, - int16_t *utc_offset_minutes, - bool *dst_active) -{ - return true; -} diff --git a/test/bacnet/basic/object/lo/CMakeLists.txt b/test/bacnet/basic/object/lo/CMakeLists.txt index 96ee2c02..005109d4 100644 --- a/test/bacnet/basic/object/lo/CMakeLists.txt +++ b/test/bacnet/basic/object/lo/CMakeLists.txt @@ -63,7 +63,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/special_event.c # Test and test library files ./src/main.c - ../mock/device_mock.c + ${TST_DIR}/bacnet/basic/object/test/device_mock.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/lsz/CMakeLists.txt b/test/bacnet/basic/object/lsz/CMakeLists.txt index 12f12878..924d4104 100644 --- a/test/bacnet/basic/object/lsz/CMakeLists.txt +++ b/test/bacnet/basic/object/lsz/CMakeLists.txt @@ -26,7 +26,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -62,7 +62,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/special_event.c # Test and test library files ./src/main.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/ms-input/CMakeLists.txt b/test/bacnet/basic/object/ms-input/CMakeLists.txt index 15fe56d6..a86cf37c 100644 --- a/test/bacnet/basic/object/ms-input/CMakeLists.txt +++ b/test/bacnet/basic/object/ms-input/CMakeLists.txt @@ -27,7 +27,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -64,7 +64,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/sys/keylist.c # Test and test library files ./src/main.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/mso/CMakeLists.txt b/test/bacnet/basic/object/mso/CMakeLists.txt index bcbeb41b..6e196a2a 100644 --- a/test/bacnet/basic/object/mso/CMakeLists.txt +++ b/test/bacnet/basic/object/mso/CMakeLists.txt @@ -27,7 +27,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -65,7 +65,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/sys/keylist.c # Test and test library files ./src/main.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/msv/CMakeLists.txt b/test/bacnet/basic/object/msv/CMakeLists.txt index 9dd8eda6..437063f2 100644 --- a/test/bacnet/basic/object/msv/CMakeLists.txt +++ b/test/bacnet/basic/object/msv/CMakeLists.txt @@ -27,7 +27,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -64,7 +64,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/sys/keylist.c # Test and test library files ./src/main.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/netport/CMakeLists.txt b/test/bacnet/basic/object/netport/CMakeLists.txt index be8406bf..1f8f2033 100644 --- a/test/bacnet/basic/object/netport/CMakeLists.txt +++ b/test/bacnet/basic/object/netport/CMakeLists.txt @@ -27,7 +27,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -63,7 +63,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/special_event.c # Test and test library files ./src/main.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/schedule/CMakeLists.txt b/test/bacnet/basic/object/schedule/CMakeLists.txt index 3e9eb476..23157ce1 100644 --- a/test/bacnet/basic/object/schedule/CMakeLists.txt +++ b/test/bacnet/basic/object/schedule/CMakeLists.txt @@ -27,7 +27,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -61,7 +61,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/special_event.c # Test and test library files ./src/main.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/structured_view/CMakeLists.txt b/test/bacnet/basic/object/structured_view/CMakeLists.txt index faccb928..0497f47b 100644 --- a/test/bacnet/basic/object/structured_view/CMakeLists.txt +++ b/test/bacnet/basic/object/structured_view/CMakeLists.txt @@ -28,7 +28,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -66,7 +66,7 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/basic/sys/keylist.c # Test and test library files ./src/main.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/mock/apdu_mock.c b/test/bacnet/basic/object/test/apdu_mock.c similarity index 100% rename from test/bacnet/basic/object/mock/apdu_mock.c rename to test/bacnet/basic/object/test/apdu_mock.c diff --git a/test/bacnet/basic/object/time_value/stubs.c b/test/bacnet/basic/object/test/datetime_local.c similarity index 50% rename from test/bacnet/basic/object/time_value/stubs.c rename to test/bacnet/basic/object/test/datetime_local.c index feef7194..c1f6dac8 100644 --- a/test/bacnet/basic/object/time_value/stubs.c +++ b/test/bacnet/basic/object/test/datetime_local.c @@ -10,19 +10,35 @@ #include #include "bacnet/datetime.h" +static BACNET_DATE BACnet_Date; +static BACNET_TIME BACnet_Time; + bool datetime_local( BACNET_DATE *bdate, BACNET_TIME *btime, int16_t *utc_offset_minutes, bool *dst_active) { - bdate->year = 2023; - bdate->month = 6; - bdate->day = 26; - bdate->wday = 1; - - (void)btime; + if (bdate) { + datetime_copy_date(bdate, &BACnet_Date); + } + if (btime) { + datetime_copy_time(btime, &BACnet_Time); + } (void)utc_offset_minutes; (void)dst_active; + return true; } + +void datetime_timesync( + BACNET_DATE *bdate, BACNET_TIME *btime, bool utc) +{ + if (bdate) { + datetime_copy_date(&BACnet_Date, bdate); + } + if (btime) { + datetime_copy_time(&BACnet_Time, btime); + } + (void)utc; +} diff --git a/test/bacnet/basic/object/mock/device_mock.c b/test/bacnet/basic/object/test/device_mock.c similarity index 100% rename from test/bacnet/basic/object/mock/device_mock.c rename to test/bacnet/basic/object/test/device_mock.c diff --git a/test/bacnet/basic/object/property_test.c b/test/bacnet/basic/object/test/property_test.c similarity index 100% rename from test/bacnet/basic/object/property_test.c rename to test/bacnet/basic/object/test/property_test.c diff --git a/test/bacnet/basic/object/property_test.h b/test/bacnet/basic/object/test/property_test.h similarity index 100% rename from test/bacnet/basic/object/property_test.h rename to test/bacnet/basic/object/test/property_test.h diff --git a/test/bacnet/basic/object/mock/tsm_mock.c b/test/bacnet/basic/object/test/tsm_mock.c similarity index 100% rename from test/bacnet/basic/object/mock/tsm_mock.c rename to test/bacnet/basic/object/test/tsm_mock.c diff --git a/test/bacnet/basic/object/time_value/CMakeLists.txt b/test/bacnet/basic/object/time_value/CMakeLists.txt index ec8df76c..281fe0f3 100644 --- a/test/bacnet/basic/object/time_value/CMakeLists.txt +++ b/test/bacnet/basic/object/time_value/CMakeLists.txt @@ -27,7 +27,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -64,9 +64,9 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/special_event.c # Test and test library files ./src/main.c - ./stubs.c - ../mock/device_mock.c - ../property_test.c + ${TST_DIR}/bacnet/basic/object/test/datetime_local.c + ${TST_DIR}/bacnet/basic/object/test/device_mock.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/test/bacnet/basic/object/trendlog/CMakeLists.txt b/test/bacnet/basic/object/trendlog/CMakeLists.txt index 20951e78..e5c8725c 100644 --- a/test/bacnet/basic/object/trendlog/CMakeLists.txt +++ b/test/bacnet/basic/object/trendlog/CMakeLists.txt @@ -27,7 +27,7 @@ add_compile_definitions( include_directories( ${SRC_DIR} - ${TST_DIR}/bacnet/basic/object + ${TST_DIR}/bacnet/basic/object/test ${TST_DIR}/ztest/include ) @@ -61,8 +61,8 @@ add_executable(${PROJECT_NAME} ${SRC_DIR}/bacnet/special_event.c # Test and test library files ./src/main.c - ../mock/device_mock.c - ${TST_DIR}/bacnet/basic/object/property_test.c + ${TST_DIR}/bacnet/basic/object/test/device_mock.c + ${TST_DIR}/bacnet/basic/object/test/property_test.c ${ZTST_DIR}/ztest_mock.c ${ZTST_DIR}/ztest.c ) diff --git a/zephyr/tests/bacnet/basic/object/ai/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/ai/CMakeLists.txt index b7a45ca4..7e416a56 100644 --- a/zephyr/tests/bacnet/basic/object/ai/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/ai/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) -set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC}) if(BOARD STREQUAL unit_testing) diff --git a/zephyr/tests/bacnet/basic/object/ao/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/ao/CMakeLists.txt index 2d913fd0..7cc6acbe 100644 --- a/zephyr/tests/bacnet/basic/object/ao/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/ao/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) -set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC}) if(BOARD STREQUAL unit_testing) diff --git a/zephyr/tests/bacnet/basic/object/av/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/av/CMakeLists.txt index 505c83e1..e21616fd 100644 --- a/zephyr/tests/bacnet/basic/object/av/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/av/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) -set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC}) if(BOARD STREQUAL unit_testing) diff --git a/zephyr/tests/bacnet/basic/object/bi/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/bi/CMakeLists.txt index f34790c1..1a7612e4 100644 --- a/zephyr/tests/bacnet/basic/object/bi/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/bi/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) -set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC}) if(BOARD STREQUAL unit_testing) diff --git a/zephyr/tests/bacnet/basic/object/bo/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/bo/CMakeLists.txt index ebcb03bc..c28b096f 100644 --- a/zephyr/tests/bacnet/basic/object/bo/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/bo/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) -set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC}) if(BOARD STREQUAL unit_testing) diff --git a/zephyr/tests/bacnet/basic/object/bv/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/bv/CMakeLists.txt index 9d175aeb..fc81bac5 100644 --- a/zephyr/tests/bacnet/basic/object/bv/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/bv/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) -set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC}) if(BOARD STREQUAL unit_testing) diff --git a/zephyr/tests/bacnet/basic/object/calendar/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/calendar/CMakeLists.txt index 874025ab..51e9f033 100644 --- a/zephyr/tests/bacnet/basic/object/calendar/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/calendar/CMakeLists.txt @@ -19,6 +19,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) if(BOARD STREQUAL unit_testing) file(RELATIVE_PATH BACNET_INCLUDE $ENV{ZEPHYR_BASE} ${BACNET_BASE}/src) @@ -27,7 +28,7 @@ if(BOARD STREQUAL unit_testing) ${BACNET_SRC_PATH}.c ${BACNET_TEST_PATH}/src/main.c ${BACNET_TEST_PATH}/stubs.c - ${BACNET_TEST_PATH}/../mock/device_mock.c + ${TEST_OBJECT_SRC}/device_mock.c ) get_filename_component(BACNET_OBJECT_SRC ${BACNET_SRC_PATH} PATH) diff --git a/zephyr/tests/bacnet/basic/object/color_object/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/color_object/CMakeLists.txt index 890ff0ac..fb5b2d12 100644 --- a/zephyr/tests/bacnet/basic/object/color_object/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/color_object/CMakeLists.txt @@ -19,6 +19,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) if(BOARD STREQUAL unit_testing) file(RELATIVE_PATH BACNET_INCLUDE $ENV{ZEPHYR_BASE} ${BACNET_BASE}/src) @@ -26,7 +27,7 @@ if(BOARD STREQUAL unit_testing) list(APPEND SOURCES ${BACNET_SRC_PATH}.c ${BACNET_TEST_PATH}/src/main.c - ${BACNET_TEST_PATH}/../mock/device_mock.c + ${TEST_OBJECT_SRC}/device_mock.c ) get_filename_component(BACNET_OBJECT_SRC ${BACNET_SRC_PATH} PATH) diff --git a/zephyr/tests/bacnet/basic/object/color_temperature/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/color_temperature/CMakeLists.txt index c1931235..65978370 100644 --- a/zephyr/tests/bacnet/basic/object/color_temperature/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/color_temperature/CMakeLists.txt @@ -19,6 +19,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) if(BOARD STREQUAL unit_testing) file(RELATIVE_PATH BACNET_INCLUDE $ENV{ZEPHYR_BASE} ${BACNET_BASE}/src) @@ -26,7 +27,7 @@ if(BOARD STREQUAL unit_testing) list(APPEND SOURCES ${BACNET_SRC_PATH}.c ${BACNET_TEST_PATH}/src/main.c - ${BACNET_TEST_PATH}/../mock/device_mock.c + ${TEST_OBJECT_SRC}/device_mock.c ) get_filename_component(BACNET_OBJECT_SRC ${BACNET_SRC_PATH} PATH) diff --git a/zephyr/tests/bacnet/basic/object/command/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/command/CMakeLists.txt index 57772894..c921e71c 100644 --- a/zephyr/tests/bacnet/basic/object/command/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/command/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) -set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC}) if(BOARD STREQUAL unit_testing) diff --git a/zephyr/tests/bacnet/basic/object/credential_data_input/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/credential_data_input/CMakeLists.txt index ef3bdfde..dc6b29a2 100644 --- a/zephyr/tests/bacnet/basic/object/credential_data_input/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/credential_data_input/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) -set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC}) if(BOARD STREQUAL unit_testing) diff --git a/zephyr/tests/bacnet/basic/object/lo/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/lo/CMakeLists.txt index 78114f86..3b5e4a68 100644 --- a/zephyr/tests/bacnet/basic/object/lo/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/lo/CMakeLists.txt @@ -19,6 +19,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) if(BOARD STREQUAL unit_testing) file(RELATIVE_PATH BACNET_INCLUDE $ENV{ZEPHYR_BASE} ${BACNET_BASE}/src) @@ -26,7 +27,7 @@ if(BOARD STREQUAL unit_testing) list(APPEND SOURCES ${BACNET_SRC_PATH}.c ${BACNET_TEST_PATH}/src/main.c - ${BACNET_TEST_PATH}/../mock/device_mock.c + ${TEST_OBJECT_SRC}/device_mock.c ) get_filename_component(BACNET_OBJECT_SRC ${BACNET_SRC_PATH} PATH) diff --git a/zephyr/tests/bacnet/basic/object/ms-input/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/ms-input/CMakeLists.txt index 9d175aeb..fc81bac5 100644 --- a/zephyr/tests/bacnet/basic/object/ms-input/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/ms-input/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) -set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC}) if(BOARD STREQUAL unit_testing) diff --git a/zephyr/tests/bacnet/basic/object/mso/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/mso/CMakeLists.txt index 6775b6e3..63026bdf 100644 --- a/zephyr/tests/bacnet/basic/object/mso/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/mso/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) -set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC}) if(BOARD STREQUAL unit_testing) diff --git a/zephyr/tests/bacnet/basic/object/msv/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/msv/CMakeLists.txt index f455c050..66a59c42 100644 --- a/zephyr/tests/bacnet/basic/object/msv/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/msv/CMakeLists.txt @@ -19,7 +19,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) -set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC}) if(BOARD STREQUAL unit_testing) diff --git a/zephyr/tests/bacnet/basic/object/netport/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/netport/CMakeLists.txt index 73b597c3..cb440ad7 100644 --- a/zephyr/tests/bacnet/basic/object/netport/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/netport/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) -set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC}) if(BOARD STREQUAL unit_testing) diff --git a/zephyr/tests/bacnet/basic/object/schedule/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/schedule/CMakeLists.txt index 6e5c1800..47df76eb 100644 --- a/zephyr/tests/bacnet/basic/object/schedule/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/schedule/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) -set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC}) if(BOARD STREQUAL unit_testing) diff --git a/zephyr/tests/bacnet/basic/object/time_value/CMakeLists.txt b/zephyr/tests/bacnet/basic/object/time_value/CMakeLists.txt index bc7c7364..fac52756 100644 --- a/zephyr/tests/bacnet/basic/object/time_value/CMakeLists.txt +++ b/zephyr/tests/bacnet/basic/object/time_value/CMakeLists.txt @@ -20,7 +20,7 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME) # Update include path for this module list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src) -set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object) +set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object/test) list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC}) if(BOARD STREQUAL unit_testing) @@ -30,9 +30,9 @@ if(BOARD STREQUAL unit_testing) list(APPEND SOURCES ${BACNET_SRC_PATH}.c ${BACNET_TEST_PATH}/src/main.c - ${BACNET_TEST_PATH}/stubs.c + ${TEST_OBJECT_SRC}/datetime_local.c ${TEST_OBJECT_SRC}/property_test.c - ${BACNET_TEST_PATH}/../mock/device_mock.c + ${TEST_OBJECT_SRC}/device_mock.c ) get_filename_component(BACNET_OBJECT_SRC ${BACNET_SRC_PATH} PATH)