diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8ecd4797..398424ea 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,9 @@ The git repositories are hosted at the following sites:
### Added
+* Added API and optional properties to basic load control object example
+ Refactored BACnetShedLevel encoding, decoding, and printing into separate
+ file. Added BACnetShedLevel validation testing. (#1187)
* Added API for Analog_Input_Notification_Class, Analog_Input_Event_Enable,
and Analog_Input_Notify_Type. (#1184)
* Added API and optional properties to basic lighting output object example
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cb5c0df3..6805a084 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -672,6 +672,8 @@ add_library(${PROJECT_NAME}
src/bacnet/rp.h
src/bacnet/rpm.c
src/bacnet/rpm.h
+ src/bacnet/shed_level.c
+ src/bacnet/shed_level.h
src/bacnet/timer_value.c
src/bacnet/timer_value.h
src/bacnet/timestamp.c
diff --git a/ports/at91sam7s/CMakeLists.txt b/ports/at91sam7s/CMakeLists.txt
index 3d423229..64411217 100644
--- a/ports/at91sam7s/CMakeLists.txt
+++ b/ports/at91sam7s/CMakeLists.txt
@@ -168,6 +168,7 @@ set(BACNET_PROJECT_SOURCE
${LIBRARY_BACNET_CORE}/reject.c
${LIBRARY_BACNET_CORE}/rp.c
${LIBRARY_BACNET_CORE}/rpm.c
+ ${LIBRARY_BACNET_CORE}/shed_level.c
${LIBRARY_BACNET_CORE}/timer_value.c
${LIBRARY_BACNET_CORE}/timestamp.c
${LIBRARY_BACNET_CORE}/weeklyschedule.c
diff --git a/ports/at91sam7s/Makefile b/ports/at91sam7s/Makefile
index 1d377cb2..1298eda2 100644
--- a/ports/at91sam7s/Makefile
+++ b/ports/at91sam7s/Makefile
@@ -130,6 +130,7 @@ CORESRC = $(BACNET_CORE)/abort.c \
$(BACNET_CORE)/reject.c \
$(BACNET_CORE)/rp.c \
$(BACNET_CORE)/rpm.c \
+ $(BACNET_CORE)/shed_level.c \
$(BACNET_CORE)/timer_value.c \
$(BACNET_CORE)/timestamp.c \
$(BACNET_CORE)/weeklyschedule.c \
diff --git a/ports/at91sam7s/bacnet.ewp b/ports/at91sam7s/bacnet.ewp
index cdaba4af..e9325b4a 100644
--- a/ports/at91sam7s/bacnet.ewp
+++ b/ports/at91sam7s/bacnet.ewp
@@ -1188,6 +1188,9 @@
$PROJ_DIR$\..\..\src\bacnet\rpm.c
+
+ $PROJ_DIR$\..\..\src\bacnet\shed_level.c
+
$PROJ_DIR$\..\..\src\bacnet\timer_value.c
diff --git a/ports/stm32f10x/CMakeLists.txt b/ports/stm32f10x/CMakeLists.txt
index f406f2ff..3d3f298d 100644
--- a/ports/stm32f10x/CMakeLists.txt
+++ b/ports/stm32f10x/CMakeLists.txt
@@ -194,6 +194,7 @@ set(BACNET_PROJECT_SOURCE
${LIBRARY_BACNET_CORE}/reject.c
${LIBRARY_BACNET_CORE}/rp.c
${LIBRARY_BACNET_CORE}/rpm.c
+ ${LIBRARY_BACNET_CORE}/shed_level.c
${LIBRARY_BACNET_CORE}/timer_value.c
${LIBRARY_BACNET_CORE}/timestamp.c
${LIBRARY_BACNET_CORE}/weeklyschedule.c
diff --git a/ports/stm32f10x/Makefile b/ports/stm32f10x/Makefile
index 9c0f0b29..23fdcf93 100644
--- a/ports/stm32f10x/Makefile
+++ b/ports/stm32f10x/Makefile
@@ -82,6 +82,7 @@ BACNET_SRC = \
$(BACNET_CORE)/rp.c \
$(BACNET_CORE)/rpm.c \
$(BACNET_CORE)/special_event.c \
+ $(BACNET_CORE)/shed_level.c \
$(BACNET_CORE)/timer_value.c \
$(BACNET_CORE)/timestamp.c \
$(BACNET_CORE)/weeklyschedule.c \
diff --git a/ports/stm32f10x/bacnet.ewp b/ports/stm32f10x/bacnet.ewp
index 3b61ed78..9e034580 100644
--- a/ports/stm32f10x/bacnet.ewp
+++ b/ports/stm32f10x/bacnet.ewp
@@ -1118,6 +1118,9 @@
$PROJ_DIR$\..\..\src\bacnet\rpm.c
+
+ $PROJ_DIR$\..\..\src\bacnet\shed_level.c
+
$PROJ_DIR$\..\..\src\bacnet\timer_value.c
diff --git a/ports/stm32f4xx/CMakeLists.txt b/ports/stm32f4xx/CMakeLists.txt
index be71c80a..0138aac9 100644
--- a/ports/stm32f4xx/CMakeLists.txt
+++ b/ports/stm32f4xx/CMakeLists.txt
@@ -227,6 +227,7 @@ set(BACNET_PROJECT_SOURCE
${LIBRARY_BACNET_CORE}/reject.c
${LIBRARY_BACNET_CORE}/rp.c
${LIBRARY_BACNET_CORE}/rpm.c
+ ${LIBRARY_BACNET_CORE}/shed_level.c
${LIBRARY_BACNET_CORE}/timer_value.c
${LIBRARY_BACNET_CORE}/timestamp.c
${LIBRARY_BACNET_CORE}/timesync.c
diff --git a/ports/stm32f4xx/Makefile b/ports/stm32f4xx/Makefile
index 86feced7..6207eea5 100644
--- a/ports/stm32f4xx/Makefile
+++ b/ports/stm32f4xx/Makefile
@@ -104,6 +104,7 @@ BACNET_SRC = \
$(BACNET_CORE)/rp.c \
$(BACNET_CORE)/rpm.c \
$(BACNET_CORE)/special_event.c \
+ $(BACNET_CORE)/shed_level.c \
$(BACNET_CORE)/timer_value.c \
$(BACNET_CORE)/timestamp.c \
$(BACNET_CORE)/timesync.c \
diff --git a/ports/stm32f4xx/bacnet.ewp b/ports/stm32f4xx/bacnet.ewp
index c232a716..a5cd9bed 100644
--- a/ports/stm32f4xx/bacnet.ewp
+++ b/ports/stm32f4xx/bacnet.ewp
@@ -1127,6 +1127,9 @@
$PROJ_DIR$\..\..\src\bacnet\rpm.c
+
+ $PROJ_DIR$\..\..\src\bacnet\shed_level.c
+
$PROJ_DIR$\..\..\src\bacnet\timer_value.c
diff --git a/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj b/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj
index f6a3d187..a8ac02cd 100644
--- a/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj
+++ b/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj
@@ -215,6 +215,7 @@
+
diff --git a/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj.filters b/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj.filters
index 22c6b5ac..0bcf0c80 100644
--- a/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj.filters
+++ b/ports/win32/Microsoft Visual Studio 2019/BACnet_Stack_Library/BACnet_Stack_Library.vcxproj.filters
@@ -129,6 +129,9 @@
Source Files
+
+ Source Files
+
Source Files
diff --git a/ports/win32/Microsoft Visual Studio/bacnet-stack/bacnet-stack.vcxproj b/ports/win32/Microsoft Visual Studio/bacnet-stack/bacnet-stack.vcxproj
index 63ccd5bf..9b70ba21 100644
--- a/ports/win32/Microsoft Visual Studio/bacnet-stack/bacnet-stack.vcxproj
+++ b/ports/win32/Microsoft Visual Studio/bacnet-stack/bacnet-stack.vcxproj
@@ -210,6 +210,7 @@
+
diff --git a/ports/win32/Microsoft Visual Studio/bacnet-stack/bacnet-stack.vcxproj.filters b/ports/win32/Microsoft Visual Studio/bacnet-stack/bacnet-stack.vcxproj.filters
index b4ef6fe8..f4cce308 100644
--- a/ports/win32/Microsoft Visual Studio/bacnet-stack/bacnet-stack.vcxproj.filters
+++ b/ports/win32/Microsoft Visual Studio/bacnet-stack/bacnet-stack.vcxproj.filters
@@ -201,6 +201,9 @@
Source Files\src\bacnet
+
+ Source Files\src\bacnet
+
Source Files\src\bacnet
diff --git a/src/bacnet/bacapp.c b/src/bacnet/bacapp.c
index e1a5dd24..19a6984c 100644
--- a/src/bacnet/bacapp.c
+++ b/src/bacnet/bacapp.c
@@ -151,149 +151,6 @@ bacnet_scale_same(const BACNET_SCALE *value1, const 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, const 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(
- const 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(
- const BACNET_SHED_LEVEL *value1, const 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
@@ -2062,40 +1919,6 @@ 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
- */
-static int bacapp_snprintf_shed_level(
- char *str, size_t str_len, const 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", (double)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
@@ -3440,7 +3263,7 @@ static int bacapp_snprintf_host_n_port(
str, str_len, "%u.%u.%u.%u:%u", (unsigned)octet_str[0],
(unsigned)octet_str[1], (unsigned)octet_str[2],
(unsigned)octet_str[3], (unsigned)value->port);
- ret_val += slen;
+ ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
} else if (value->host_name) {
const BACNET_CHARACTER_STRING *name;
name = &value->host.name;
@@ -3458,7 +3281,7 @@ static int bacapp_snprintf_host_n_port(
char_str++;
}
slen = bacapp_snprintf(str, str_len, "\"");
- ret_val += slen;
+ ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
}
slen = bacapp_snprintf(str, str_len, "}");
ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
@@ -3801,7 +3624,8 @@ int bacapp_snprintf_value(
BACNET_PROPERTY_ID property = PROP_ALL;
BACNET_OBJECT_TYPE object_type = MAX_BACNET_OBJECT_TYPE;
int ret_val = 0;
-#if defined(BACAPP_BDT_ENTRY) || defined(BACAPP_FDT_ENTRY)
+#if defined(BACAPP_BDT_ENTRY) || defined(BACAPP_FDT_ENTRY) || \
+ defined(BACAPP_SHED_LEVEL)
int slen = 0;
#endif
@@ -4039,8 +3863,13 @@ int bacapp_snprintf_value(
#endif
#if defined(BACAPP_SHED_LEVEL)
case BACNET_APPLICATION_TAG_SHED_LEVEL:
- ret_val = bacapp_snprintf_shed_level(
+ slen = bacapp_snprintf(str, str_len, "{");
+ ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
+ slen = bacapp_snprintf_shed_level(
str, str_len, &value->type.Shed_Level);
+ ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
+ slen = bacapp_snprintf(str, str_len, "}");
+ ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
break;
#endif
#if defined(BACAPP_ACCESS_RULE)
@@ -4335,58 +4164,6 @@ static bool bacnet_scale_from_ascii(BACNET_SCALE *value, const char *argv)
}
#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
- */
-static 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
-
#if defined(BACAPP_DEVICE_OBJECT_PROPERTY_REFERENCE)
/**
* @brief Parse a string into a BACnetDeviceObjectPropertyReference value
diff --git a/src/bacnet/bacapp.h b/src/bacnet/bacapp.h
index 9a9e9825..7971739c 100644
--- a/src/bacnet/bacapp.h
+++ b/src/bacnet/bacapp.h
@@ -31,6 +31,7 @@
#include "bacnet/calendar_entry.h"
#include "bacnet/special_event.h"
#include "bacnet/channel_value.h"
+#include "bacnet/shed_level.h"
#include "bacnet/timer_value.h"
#include "bacnet/secure_connect.h"
@@ -53,16 +54,6 @@ 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 */
diff --git a/src/bacnet/basic/object/lc.c b/src/bacnet/basic/object/lc.c
index 9a385534..a386688b 100644
--- a/src/bacnet/basic/object/lc.c
+++ b/src/bacnet/basic/object/lc.c
@@ -16,6 +16,7 @@
#include "bacnet/bacdcode.h"
#include "bacnet/bactext.h"
#include "bacnet/datetime.h"
+#include "bacnet/shed_level.h"
#include "bacnet/basic/object/lc.h"
#include "bacnet/basic/object/ao.h"
#include "bacnet/wp.h"
@@ -33,9 +34,6 @@
#define LOAD_CONTROL_TASK_INTERVAL_MS 1000UL
struct object_data {
- void *Context;
- const char *Object_Name;
- const char *Description;
/* indicates the current load shedding state of the object */
BACNET_SHED_STATE Present_Value;
/* tracking for the Load Control finite state machine */
@@ -91,6 +89,9 @@ struct object_data {
load_control_manipulated_object_read_callback Manipulated_Object_Read;
/* state machine task time tracking per object */
uint32_t Task_Milliseconds;
+ void *Context;
+ const char *Object_Name;
+ const char *Description;
};
/* Key List for storing the object data sorted by instance number */
static OS_Keylist Object_List;
@@ -1667,6 +1668,329 @@ bool Load_Control_Shed_Level_Array(
return true;
}
+/**
+ * @brief For a given object instance-number, gets the requested shed level
+ * property
+ * @param object_instance - object-instance number of the object
+ * @param value - holds the value to be retrieved
+ * @return the requested shed level of this object instance.
+ */
+bool Load_Control_Requested_Shed_Level(
+ uint32_t object_instance, BACNET_SHED_LEVEL *value)
+{
+ bool status = false;
+ struct object_data *pObject;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ status = bacnet_shed_level_copy(value, &pObject->Requested_Shed_Level);
+ }
+
+ return status;
+}
+
+/**
+ * @brief For a given object instance-number, sets the requested shed level
+ * property
+ * @param object_instance - object-instance number of the object
+ * @param value - holds the value to be set
+ * @return true if requested shed level was set
+ */
+bool Load_Control_Requested_Shed_Level_Set(
+ uint32_t object_instance, BACNET_SHED_LEVEL *value)
+{
+ bool status = false;
+ struct object_data *pObject;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ status = bacnet_shed_level_copy(&pObject->Requested_Shed_Level, value);
+ }
+
+ return status;
+}
+
+/**
+ * @brief For a given object instance-number, gets the expected shed level
+ * property
+ * @param object_instance - object-instance number of the object
+ * @param value - holds the value to be retrieved
+ * @return the expected shed level of this object instance.
+ */
+bool Load_Control_Expected_Shed_Level(
+ uint32_t object_instance, BACNET_SHED_LEVEL *value)
+{
+ bool status = false;
+ struct object_data *pObject;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ status = bacnet_shed_level_copy(value, &pObject->Expected_Shed_Level);
+ }
+
+ return status;
+}
+
+/**
+ * @brief For a given object instance-number, sets the expected shed level
+ * property
+ * @param object_instance - object-instance number of the object
+ * @param value - holds the value to be set
+ * @return true if expected shed level was set
+ */
+bool Load_Control_Expected_Shed_Level_Set(
+ uint32_t object_instance, BACNET_SHED_LEVEL *value)
+{
+ bool status = false;
+ struct object_data *pObject;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ status = bacnet_shed_level_copy(&pObject->Expected_Shed_Level, value);
+ }
+
+ return status;
+}
+
+/**
+ * @brief For a given object instance-number, gets the expected shed level
+ * property
+ * @param object_instance - object-instance number of the object
+ * @param value - holds the value to be retrieved
+ * @return the expected shed level of this object instance.
+ */
+bool Load_Control_Actual_Shed_Level(
+ uint32_t object_instance, BACNET_SHED_LEVEL *value)
+{
+ bool status = false;
+ struct object_data *pObject;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ status = bacnet_shed_level_copy(value, &pObject->Expected_Shed_Level);
+ }
+
+ return status;
+}
+
+/**
+ * @brief For a given object instance-number, sets the expected shed level
+ * property
+ * @param object_instance - object-instance number of the object
+ * @param value - holds the value to be set
+ * @return true if expected shed level was set
+ */
+bool Load_Control_Actual_Shed_Level_Set(
+ uint32_t object_instance, BACNET_SHED_LEVEL *value)
+{
+ bool status = false;
+ struct object_data *pObject;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ status = bacnet_shed_level_copy(&pObject->Expected_Shed_Level, value);
+ }
+
+ return status;
+}
+
+/**
+ * @brief For a given object instance-number, gets the start-time property
+ * @param object_instance - object-instance number of the object
+ * @param value - holds the value to be retrieved
+ * @return the start-time property value of this object instance.
+ */
+bool Load_Control_Start_Time(uint32_t object_instance, BACNET_DATE_TIME *value)
+{
+ bool status = false;
+ struct object_data *pObject;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ datetime_copy_date(&value->date, &pObject->Start_Time.date);
+ datetime_copy_time(&value->time, &pObject->Start_Time.time);
+ status = true;
+ }
+
+ return status;
+}
+
+/**
+ * @brief For a given object instance-number, sets the start-time property
+ * @param object_instance - object-instance number of the object
+ * @param value - holds the value to be set
+ * @return true if property value was set
+ */
+bool Load_Control_Start_Time_Set(
+ uint32_t object_instance, BACNET_DATE_TIME *value)
+{
+ bool status = false;
+ struct object_data *pObject;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ datetime_copy_date(&pObject->Start_Time.date, &value->date);
+ datetime_copy_time(&pObject->Start_Time.time, &value->time);
+ status = true;
+ }
+
+ return status;
+}
+
+/**
+ * @brief For a given object instance-number, gets the shed-duration property
+ * @param object_instance - object-instance number of the object
+ * @return the shed-duration property value of this object instance.
+ */
+uint32_t Load_Control_Shed_Duration(uint32_t object_instance)
+{
+ struct object_data *pObject;
+ uint32_t value = 0;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ value = pObject->Shed_Duration;
+ }
+
+ return value;
+}
+
+/**
+ * @brief For a given object instance-number, sets the shed-duration property
+ * @param object_instance - object-instance number of the object
+ * @param value - holds the value to be set
+ * @return true if property value was set
+ */
+bool Load_Control_Shed_Duration_Set(uint32_t object_instance, uint32_t value)
+{
+ struct object_data *pObject;
+ bool status = false;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ pObject->Shed_Duration = value;
+ status = true;
+ }
+
+ return status;
+}
+
+/**
+ * @brief For a given object instance-number, gets the duty-window property
+ * @param object_instance - object-instance number of the object
+ * @return the duty-window property value of this object instance.
+ */
+uint32_t Load_Control_Duty_Window(uint32_t object_instance)
+{
+ struct object_data *pObject;
+ uint32_t value = 0;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ value = pObject->Duty_Window;
+ }
+
+ return value;
+}
+
+/**
+ * @brief For a given object instance-number, sets the duty-window property
+ * @param object_instance - object-instance number of the object
+ * @param value - holds the value to be set
+ * @return true if property value was set
+ */
+bool Load_Control_Duty_Window_Set(uint32_t object_instance, uint32_t value)
+{
+ struct object_data *pObject;
+ bool status = false;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ pObject->Duty_Window = value;
+ status = true;
+ }
+
+ return status;
+}
+
+/**
+ * @brief For a given object instance-number, gets the full-duty-baseline
+ * property value
+ * @param object_instance - object-instance number of the object
+ * @return the full-duty-baseline property value of this object instance.
+ */
+float Load_Control_Full_Duty_Baseline(uint32_t object_instance)
+{
+ struct object_data *pObject;
+ float value = 0.0f;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ value = pObject->Full_Duty_Baseline;
+ }
+
+ return value;
+}
+
+/**
+ * @brief For a given object instance-number, sets the full-duty-baseline
+ * property value
+ * @param object_instance - object-instance number of the object
+ * @param value - holds the value to be set
+ * @return true if property value was set
+ */
+bool Load_Control_Full_Duty_Baseline_Set(uint32_t object_instance, float value)
+{
+ struct object_data *pObject;
+ bool status = false;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ pObject->Full_Duty_Baseline = value;
+ status = true;
+ }
+
+ return status;
+}
+
+/**
+ * @brief For a given object instance-number, gets the enable property value
+ * @param object_instance - object-instance number of the object
+ * @return the enable property value of this object instance.
+ */
+bool Load_Control_Enable(uint32_t object_instance)
+{
+ struct object_data *pObject;
+ bool value = false;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ value = pObject->Load_Control_Enable;
+ }
+
+ return value;
+}
+
+/**
+ * @brief For a given object instance-number, sets the enable property
+ * @param object_instance - object-instance number of the object
+ * @param value - holds the value to be set
+ * @return true if property value was set
+ */
+bool Load_Control_Enable_Set(uint32_t object_instance, bool value)
+{
+ struct object_data *pObject;
+ bool status = false;
+
+ pObject = Keylist_Data(Object_List, object_instance);
+ if (pObject) {
+ pObject->Load_Control_Enable = value;
+ status = true;
+ }
+
+ return status;
+}
+
/**
* @brief Set the context used with a specific object instance
* @param object_instance [in] BACnet object instance number
diff --git a/src/bacnet/basic/object/lc.h b/src/bacnet/basic/object/lc.h
index 2fb4e553..442f4d02 100644
--- a/src/bacnet/basic/object/lc.h
+++ b/src/bacnet/basic/object/lc.h
@@ -13,6 +13,7 @@
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/bacerror.h"
+#include "bacnet/shed_level.h"
#include "bacnet/rp.h"
#include "bacnet/wp.h"
@@ -112,6 +113,53 @@ bool Load_Control_Shed_Level_Array(
uint32_t array_entry,
struct shed_level_data *value);
+BACNET_STACK_EXPORT
+bool Load_Control_Requested_Shed_Level(
+ uint32_t object_instance, BACNET_SHED_LEVEL *value);
+BACNET_STACK_EXPORT
+bool Load_Control_Requested_Shed_Level_Set(
+ uint32_t object_instance, BACNET_SHED_LEVEL *value);
+
+BACNET_STACK_EXPORT
+bool Load_Control_Expected_Shed_Level(
+ uint32_t object_instance, BACNET_SHED_LEVEL *value);
+BACNET_STACK_EXPORT
+bool Load_Control_Expected_Shed_Level_Set(
+ uint32_t object_instance, BACNET_SHED_LEVEL *value);
+
+BACNET_STACK_EXPORT
+bool Load_Control_Actual_Shed_Level(
+ uint32_t object_instance, BACNET_SHED_LEVEL *value);
+BACNET_STACK_EXPORT
+bool Load_Control_Actual_Shed_Level_Set(
+ uint32_t object_instance, BACNET_SHED_LEVEL *value);
+
+BACNET_STACK_EXPORT
+bool Load_Control_Start_Time(uint32_t object_instance, BACNET_DATE_TIME *value);
+BACNET_STACK_EXPORT
+bool Load_Control_Start_Time_Set(
+ uint32_t object_instance, BACNET_DATE_TIME *value);
+
+BACNET_STACK_EXPORT
+uint32_t Load_Control_Shed_Duration(uint32_t object_instance);
+BACNET_STACK_EXPORT
+bool Load_Control_Shed_Duration_Set(uint32_t object_instance, uint32_t value);
+
+BACNET_STACK_EXPORT
+uint32_t Load_Control_Duty_Window(uint32_t object_instance);
+BACNET_STACK_EXPORT
+bool Load_Control_Duty_Window_Set(uint32_t object_instance, uint32_t value);
+
+BACNET_STACK_EXPORT
+float Load_Control_Full_Duty_Baseline(uint32_t object_instance);
+BACNET_STACK_EXPORT
+bool Load_Control_Full_Duty_Baseline_Set(uint32_t object_instance, float value);
+
+BACNET_STACK_EXPORT
+bool Load_Control_Enable(uint32_t object_instance);
+BACNET_STACK_EXPORT
+bool Load_Control_Enable_Set(uint32_t object_instance, bool value);
+
BACNET_STACK_EXPORT
void *Load_Control_Context_Get(uint32_t object_instance);
BACNET_STACK_EXPORT
diff --git a/src/bacnet/shed_level.c b/src/bacnet/shed_level.c
new file mode 100644
index 00000000..b3821c18
--- /dev/null
+++ b/src/bacnet/shed_level.c
@@ -0,0 +1,259 @@
+/**
+ * @file
+ * @brief BACnetShedLevel complex data type encode and decode
+ * @author Steve Karg
+ * @date December 2025
+ * @copyright SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
+ */
+#include
+#include
+#include "bacnet/bacdcode.h"
+#include "bacnet/shed_level.h"
+
+/**
+ * @brief Encode a BACnetShedLevel value.
+ *
+ * BACnetShedLevel ::= CHOICE {
+ * percent[0] Unsigned,
+ * level[1] Unsigned,
+ * amount[2] Real
+ * }
+ *
+ * @param apdu - buffer to encode to
+ * @param value - value to encode
+ * @return number of bytes encoded
+ */
+int bacnet_shed_level_encode(uint8_t *apdu, const 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_LEVEL:
+ apdu_len = encode_context_unsigned(apdu, 1, value->value.level);
+ break;
+ case BACNET_SHED_TYPE_AMOUNT:
+ apdu_len = encode_context_real(apdu, 2, value->value.amount);
+ break;
+ default:
+ break;
+ }
+
+ return apdu_len;
+}
+
+/**
+ * @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, or NULL for size only
+ * @return number of bytes decoded, or BACNET_STATUS_ERROR on error
+ */
+int bacnet_shed_level_decode(
+ const 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) {
+ if (value) {
+ 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) {
+ if (value) {
+ 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) {
+ if (value) {
+ value->type = BACNET_SHED_TYPE_AMOUNT;
+ value->value.amount = real_value;
+ }
+ }
+ break;
+ default:
+ return BACNET_STATUS_ERROR;
+ }
+
+ return apdu_len;
+}
+
+/**
+ * @brief Compare the BACnetShedLevel complex data
+ * @param value1 - BACNET_SHED_LEVEL structure
+ * @param value2 - BACNET_SHED_LEVEL structure
+ * @return true if the same
+ */
+bool bacnet_shed_level_same(
+ const BACNET_SHED_LEVEL *value1, const 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_LEVEL:
+ if (value1->value.level != value2->value.level) {
+ status = false;
+ }
+ break;
+ case BACNET_SHED_TYPE_AMOUNT:
+ if (islessgreater(
+ value1->value.amount, value2->value.amount)) {
+ status = false;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief Compare the BACnetShedLevel complex data
+ * @param value1 - BACNET_SHED_LEVEL structure
+ * @param value2 - BACNET_SHED_LEVEL structure
+ * @return true if the same
+ */
+bool bacnet_shed_level_copy(
+ BACNET_SHED_LEVEL *dest, const BACNET_SHED_LEVEL *src)
+{
+ if (!dest || !src) {
+ return false;
+ }
+
+ memcpy(dest, src, sizeof(BACNET_SHED_LEVEL));
+
+ return true;
+}
+
+/**
+ * @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, const BACNET_SHED_LEVEL *value)
+{
+ int length = 0;
+
+ switch (value->type) {
+ case BACNET_SHED_TYPE_PERCENT:
+ length = bacnet_snprintf(
+ str, str_len, length, "%u%%", (unsigned)value->value.percent);
+ break;
+ case BACNET_SHED_TYPE_LEVEL:
+ length = bacnet_snprintf(
+ str, str_len, length, "%u", (unsigned)value->value.level);
+ break;
+ case BACNET_SHED_TYPE_AMOUNT:
+ length = bacnet_snprintf(
+ str, str_len, length, "%f", (double)value->value.amount);
+ break;
+ default:
+ break;
+ }
+
+ return length;
+}
+
+/**
+ * @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;
+}
diff --git a/src/bacnet/shed_level.h b/src/bacnet/shed_level.h
new file mode 100644
index 00000000..3446bad3
--- /dev/null
+++ b/src/bacnet/shed_level.h
@@ -0,0 +1,58 @@
+/**
+ * @file
+ * @brief API for BACnetShedLevel complex data type encode and decode
+ * @author Steve Karg
+ * @date December 2025
+ * @copyright SPDX-License-Identifier: MIT
+ */
+#ifndef BACNET_SHED_LEVEL_H
+#define BACNET_SHED_LEVEL_H
+
+#include
+#include
+/* BACnet Stack defines - first */
+#include "bacnet/bacdef.h"
+#include "bacnet/bacint.h"
+
+/* The shed levels for the LEVEL choice of BACnetShedLevel. */
+typedef struct BACnetShedLevel {
+ BACNET_SHED_LEVEL_TYPE type;
+ union {
+ BACNET_UNSIGNED_INTEGER level;
+ BACNET_UNSIGNED_INTEGER percent;
+ float amount;
+ } value;
+} BACNET_SHED_LEVEL;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/** Decode Special Event */
+BACNET_STACK_EXPORT
+int bacnet_shed_level_decode(
+ const uint8_t *apdu, size_t apdu_size, BACNET_SHED_LEVEL *value);
+
+/** Encode Special Event */
+BACNET_STACK_EXPORT
+int bacnet_shed_level_encode(uint8_t *apdu, const BACNET_SHED_LEVEL *value);
+
+BACNET_STACK_EXPORT
+bool bacnet_shed_level_same(
+ const BACNET_SHED_LEVEL *value1, const BACNET_SHED_LEVEL *value2);
+
+BACNET_STACK_EXPORT
+bool bacnet_shed_level_copy(
+ BACNET_SHED_LEVEL *dest, const BACNET_SHED_LEVEL *src);
+
+BACNET_STACK_EXPORT
+int bacapp_snprintf_shed_level(
+ char *str, size_t str_len, const BACNET_SHED_LEVEL *value);
+
+BACNET_STACK_EXPORT
+bool bacnet_shed_level_from_ascii(BACNET_SHED_LEVEL *value, const char *argv);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index f249af27..b252aaac 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -124,6 +124,7 @@ list(APPEND testdirs
bacnet/rpm
bacnet/secure_connect
bacnet/specialevent
+ bacnet/shed_level
bacnet/timer_value
bacnet/timestamp
bacnet/timesync
diff --git a/test/bacnet/access_rule/CMakeLists.txt b/test/bacnet/access_rule/CMakeLists.txt
index 8ad3aee3..3600f5f1 100644
--- a/test/bacnet/access_rule/CMakeLists.txt
+++ b/test/bacnet/access_rule/CMakeLists.txt
@@ -56,6 +56,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/weeklyschedule.c
diff --git a/test/bacnet/authentication_factor_format/CMakeLists.txt b/test/bacnet/authentication_factor_format/CMakeLists.txt
index aec16a4c..e2c1bc9b 100644
--- a/test/bacnet/authentication_factor_format/CMakeLists.txt
+++ b/test/bacnet/authentication_factor_format/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/weeklyschedule.c
diff --git a/test/bacnet/bacapp/CMakeLists.txt b/test/bacnet/bacapp/CMakeLists.txt
index 29e28d36..6b6d1437 100644
--- a/test/bacnet/bacapp/CMakeLists.txt
+++ b/test/bacnet/bacapp/CMakeLists.txt
@@ -52,6 +52,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/indtext.c
diff --git a/test/bacnet/bacaudit/CMakeLists.txt b/test/bacnet/bacaudit/CMakeLists.txt
index 8743ada5..99727c50 100644
--- a/test/bacnet/bacaudit/CMakeLists.txt
+++ b/test/bacnet/bacaudit/CMakeLists.txt
@@ -54,6 +54,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/timesync.c
diff --git a/test/bacnet/bacdest/CMakeLists.txt b/test/bacnet/bacdest/CMakeLists.txt
index 53d101cc..fb32468f 100644
--- a/test/bacnet/bacdest/CMakeLists.txt
+++ b/test/bacnet/bacdest/CMakeLists.txt
@@ -54,6 +54,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/timesync.c
diff --git a/test/bacnet/bacdevobjpropref/CMakeLists.txt b/test/bacnet/bacdevobjpropref/CMakeLists.txt
index 067db5fc..beae9ebb 100644
--- a/test/bacnet/bacdevobjpropref/CMakeLists.txt
+++ b/test/bacnet/bacdevobjpropref/CMakeLists.txt
@@ -56,6 +56,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/weeklyschedule.c
diff --git a/test/bacnet/baclog/CMakeLists.txt b/test/bacnet/baclog/CMakeLists.txt
index 95a34e69..a9abc041 100644
--- a/test/bacnet/baclog/CMakeLists.txt
+++ b/test/bacnet/baclog/CMakeLists.txt
@@ -54,6 +54,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/timesync.c
diff --git a/test/bacnet/bactimevalue/CMakeLists.txt b/test/bacnet/bactimevalue/CMakeLists.txt
index efca4a4a..a9350be7 100644
--- a/test/bacnet/bactimevalue/CMakeLists.txt
+++ b/test/bacnet/bactimevalue/CMakeLists.txt
@@ -54,6 +54,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/weeklyschedule.c
diff --git a/test/bacnet/basic/binding/address/CMakeLists.txt b/test/bacnet/basic/binding/address/CMakeLists.txt
index 29ab5212..c03f9f79 100644
--- a/test/bacnet/basic/binding/address/CMakeLists.txt
+++ b/test/bacnet/basic/binding/address/CMakeLists.txt
@@ -52,6 +52,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/weeklyschedule.c
diff --git a/test/bacnet/basic/object/acc/CMakeLists.txt b/test/bacnet/basic/object/acc/CMakeLists.txt
index b7727df3..373a3d07 100644
--- a/test/bacnet/basic/object/acc/CMakeLists.txt
+++ b/test/bacnet/basic/object/acc/CMakeLists.txt
@@ -52,6 +52,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/basic/sys/days.c
diff --git a/test/bacnet/basic/object/access_credential/CMakeLists.txt b/test/bacnet/basic/object/access_credential/CMakeLists.txt
index 2437734a..0bf2ba54 100644
--- a/test/bacnet/basic/object/access_credential/CMakeLists.txt
+++ b/test/bacnet/basic/object/access_credential/CMakeLists.txt
@@ -56,6 +56,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/access_door/CMakeLists.txt b/test/bacnet/basic/object/access_door/CMakeLists.txt
index cc14d495..920aba7f 100644
--- a/test/bacnet/basic/object/access_door/CMakeLists.txt
+++ b/test/bacnet/basic/object/access_door/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/access_point/CMakeLists.txt b/test/bacnet/basic/object/access_point/CMakeLists.txt
index 03b7997b..912046db 100644
--- a/test/bacnet/basic/object/access_point/CMakeLists.txt
+++ b/test/bacnet/basic/object/access_point/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/weeklyschedule.c
diff --git a/test/bacnet/basic/object/access_rights/CMakeLists.txt b/test/bacnet/basic/object/access_rights/CMakeLists.txt
index 91a69541..a8aab038 100644
--- a/test/bacnet/basic/object/access_rights/CMakeLists.txt
+++ b/test/bacnet/basic/object/access_rights/CMakeLists.txt
@@ -55,6 +55,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/property.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/access_user/CMakeLists.txt b/test/bacnet/basic/object/access_user/CMakeLists.txt
index f96f8f34..00908cbe 100644
--- a/test/bacnet/basic/object/access_user/CMakeLists.txt
+++ b/test/bacnet/basic/object/access_user/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/access_zone/CMakeLists.txt b/test/bacnet/basic/object/access_zone/CMakeLists.txt
index f461df0a..4521284e 100644
--- a/test/bacnet/basic/object/access_zone/CMakeLists.txt
+++ b/test/bacnet/basic/object/access_zone/CMakeLists.txt
@@ -57,6 +57,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/ai/CMakeLists.txt b/test/bacnet/basic/object/ai/CMakeLists.txt
index 129e255a..ed61ba0f 100644
--- a/test/bacnet/basic/object/ai/CMakeLists.txt
+++ b/test/bacnet/basic/object/ai/CMakeLists.txt
@@ -54,6 +54,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/memcopy.c
diff --git a/test/bacnet/basic/object/ao/CMakeLists.txt b/test/bacnet/basic/object/ao/CMakeLists.txt
index 87925927..41d13793 100644
--- a/test/bacnet/basic/object/ao/CMakeLists.txt
+++ b/test/bacnet/basic/object/ao/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
${SRC_DIR}/bacnet/memcopy.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/auditlog/CMakeLists.txt b/test/bacnet/basic/object/auditlog/CMakeLists.txt
index 7f75fb81..63e9ffb8 100644
--- a/test/bacnet/basic/object/auditlog/CMakeLists.txt
+++ b/test/bacnet/basic/object/auditlog/CMakeLists.txt
@@ -57,6 +57,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/av/CMakeLists.txt b/test/bacnet/basic/object/av/CMakeLists.txt
index cc58356d..20369de6 100644
--- a/test/bacnet/basic/object/av/CMakeLists.txt
+++ b/test/bacnet/basic/object/av/CMakeLists.txt
@@ -54,6 +54,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/memcopy.c
diff --git a/test/bacnet/basic/object/bacfile/CMakeLists.txt b/test/bacnet/basic/object/bacfile/CMakeLists.txt
index fdec5547..33c6acf7 100644
--- a/test/bacnet/basic/object/bacfile/CMakeLists.txt
+++ b/test/bacnet/basic/object/bacfile/CMakeLists.txt
@@ -60,6 +60,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
${SRC_DIR}/bacnet/memcopy.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/bi/CMakeLists.txt b/test/bacnet/basic/object/bi/CMakeLists.txt
index 037a5081..55eefcf4 100644
--- a/test/bacnet/basic/object/bi/CMakeLists.txt
+++ b/test/bacnet/basic/object/bi/CMakeLists.txt
@@ -55,6 +55,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/memcopy.c
diff --git a/test/bacnet/basic/object/bitstring_value/CMakeLists.txt b/test/bacnet/basic/object/bitstring_value/CMakeLists.txt
index 809fa625..3575e392 100644
--- a/test/bacnet/basic/object/bitstring_value/CMakeLists.txt
+++ b/test/bacnet/basic/object/bitstring_value/CMakeLists.txt
@@ -57,6 +57,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
${SRC_DIR}/bacnet/property.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/blo/CMakeLists.txt b/test/bacnet/basic/object/blo/CMakeLists.txt
index 3f7f929e..fcdc4080 100644
--- a/test/bacnet/basic/object/blo/CMakeLists.txt
+++ b/test/bacnet/basic/object/blo/CMakeLists.txt
@@ -58,6 +58,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/bo/CMakeLists.txt b/test/bacnet/basic/object/bo/CMakeLists.txt
index 4188b4dc..f167d626 100644
--- a/test/bacnet/basic/object/bo/CMakeLists.txt
+++ b/test/bacnet/basic/object/bo/CMakeLists.txt
@@ -54,6 +54,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
${SRC_DIR}/bacnet/memcopy.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/bv/CMakeLists.txt b/test/bacnet/basic/object/bv/CMakeLists.txt
index 92a7cce6..cac09c40 100644
--- a/test/bacnet/basic/object/bv/CMakeLists.txt
+++ b/test/bacnet/basic/object/bv/CMakeLists.txt
@@ -55,6 +55,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/calendar/CMakeLists.txt b/test/bacnet/basic/object/calendar/CMakeLists.txt
index 721d41b6..e68a12ad 100644
--- a/test/bacnet/basic/object/calendar/CMakeLists.txt
+++ b/test/bacnet/basic/object/calendar/CMakeLists.txt
@@ -55,6 +55,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/memcopy.c
diff --git a/test/bacnet/basic/object/channel/CMakeLists.txt b/test/bacnet/basic/object/channel/CMakeLists.txt
index 6e85a752..76d587e4 100644
--- a/test/bacnet/basic/object/channel/CMakeLists.txt
+++ b/test/bacnet/basic/object/channel/CMakeLists.txt
@@ -59,6 +59,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/property.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/color_object/CMakeLists.txt b/test/bacnet/basic/object/color_object/CMakeLists.txt
index 4ce7139d..bc84057a 100644
--- a/test/bacnet/basic/object/color_object/CMakeLists.txt
+++ b/test/bacnet/basic/object/color_object/CMakeLists.txt
@@ -58,6 +58,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/memcopy.c
diff --git a/test/bacnet/basic/object/color_temperature/CMakeLists.txt b/test/bacnet/basic/object/color_temperature/CMakeLists.txt
index 34417b3b..a513e3ca 100644
--- a/test/bacnet/basic/object/color_temperature/CMakeLists.txt
+++ b/test/bacnet/basic/object/color_temperature/CMakeLists.txt
@@ -58,6 +58,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/memcopy.c
diff --git a/test/bacnet/basic/object/command/CMakeLists.txt b/test/bacnet/basic/object/command/CMakeLists.txt
index a3f08c70..ef50592a 100644
--- a/test/bacnet/basic/object/command/CMakeLists.txt
+++ b/test/bacnet/basic/object/command/CMakeLists.txt
@@ -54,6 +54,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/credential_data_input/CMakeLists.txt b/test/bacnet/basic/object/credential_data_input/CMakeLists.txt
index 81992a87..d98c1c07 100644
--- a/test/bacnet/basic/object/credential_data_input/CMakeLists.txt
+++ b/test/bacnet/basic/object/credential_data_input/CMakeLists.txt
@@ -57,6 +57,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/csv/CMakeLists.txt b/test/bacnet/basic/object/csv/CMakeLists.txt
index addebe52..484d7b06 100644
--- a/test/bacnet/basic/object/csv/CMakeLists.txt
+++ b/test/bacnet/basic/object/csv/CMakeLists.txt
@@ -54,6 +54,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/device/CMakeLists.txt b/test/bacnet/basic/object/device/CMakeLists.txt
index c79271d4..057421bf 100644
--- a/test/bacnet/basic/object/device/CMakeLists.txt
+++ b/test/bacnet/basic/object/device/CMakeLists.txt
@@ -102,6 +102,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/proplist.c
${SRC_DIR}/bacnet/property.c
${SRC_DIR}/bacnet/reject.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/iv/CMakeLists.txt b/test/bacnet/basic/object/iv/CMakeLists.txt
index 95ec1ee1..dff23034 100644
--- a/test/bacnet/basic/object/iv/CMakeLists.txt
+++ b/test/bacnet/basic/object/iv/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/lc/CMakeLists.txt b/test/bacnet/basic/object/lc/CMakeLists.txt
index cfc98c34..b8682962 100644
--- a/test/bacnet/basic/object/lc/CMakeLists.txt
+++ b/test/bacnet/basic/object/lc/CMakeLists.txt
@@ -63,6 +63,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
${SRC_DIR}/bacnet/rp.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/lo/CMakeLists.txt b/test/bacnet/basic/object/lo/CMakeLists.txt
index 7f1285f6..0b2a391c 100644
--- a/test/bacnet/basic/object/lo/CMakeLists.txt
+++ b/test/bacnet/basic/object/lo/CMakeLists.txt
@@ -61,6 +61,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/loop/CMakeLists.txt b/test/bacnet/basic/object/loop/CMakeLists.txt
index 060527d3..6d37e7bf 100644
--- a/test/bacnet/basic/object/loop/CMakeLists.txt
+++ b/test/bacnet/basic/object/loop/CMakeLists.txt
@@ -58,6 +58,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/property.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/lsp/CMakeLists.txt b/test/bacnet/basic/object/lsp/CMakeLists.txt
index a8cbebbe..f17d0ed7 100644
--- a/test/bacnet/basic/object/lsp/CMakeLists.txt
+++ b/test/bacnet/basic/object/lsp/CMakeLists.txt
@@ -54,6 +54,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/lsz/CMakeLists.txt b/test/bacnet/basic/object/lsz/CMakeLists.txt
index 13a1eb3e..33b035a6 100644
--- a/test/bacnet/basic/object/lsz/CMakeLists.txt
+++ b/test/bacnet/basic/object/lsz/CMakeLists.txt
@@ -55,6 +55,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/ms-input/CMakeLists.txt b/test/bacnet/basic/object/ms-input/CMakeLists.txt
index d2a78957..a254843d 100644
--- a/test/bacnet/basic/object/ms-input/CMakeLists.txt
+++ b/test/bacnet/basic/object/ms-input/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/mso/CMakeLists.txt b/test/bacnet/basic/object/mso/CMakeLists.txt
index 6f62197c..5f4a4306 100644
--- a/test/bacnet/basic/object/mso/CMakeLists.txt
+++ b/test/bacnet/basic/object/mso/CMakeLists.txt
@@ -54,6 +54,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
${SRC_DIR}/bacnet/memcopy.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/msv/CMakeLists.txt b/test/bacnet/basic/object/msv/CMakeLists.txt
index dc3d865d..ffbb4679 100644
--- a/test/bacnet/basic/object/msv/CMakeLists.txt
+++ b/test/bacnet/basic/object/msv/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/nc/CMakeLists.txt b/test/bacnet/basic/object/nc/CMakeLists.txt
index 73a6c6a7..13eb272d 100644
--- a/test/bacnet/basic/object/nc/CMakeLists.txt
+++ b/test/bacnet/basic/object/nc/CMakeLists.txt
@@ -59,6 +59,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/list_element.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/netport/CMakeLists.txt b/test/bacnet/basic/object/netport/CMakeLists.txt
index 984387ec..b6019f57 100644
--- a/test/bacnet/basic/object/netport/CMakeLists.txt
+++ b/test/bacnet/basic/object/netport/CMakeLists.txt
@@ -71,6 +71,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
${SRC_DIR}/bacnet/property.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/osv/CMakeLists.txt b/test/bacnet/basic/object/osv/CMakeLists.txt
index 803237c2..46dba899 100644
--- a/test/bacnet/basic/object/osv/CMakeLists.txt
+++ b/test/bacnet/basic/object/osv/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/piv/CMakeLists.txt b/test/bacnet/basic/object/piv/CMakeLists.txt
index 1bc61ecc..c07ef266 100644
--- a/test/bacnet/basic/object/piv/CMakeLists.txt
+++ b/test/bacnet/basic/object/piv/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/program/CMakeLists.txt b/test/bacnet/basic/object/program/CMakeLists.txt
index 8f848e43..2c708abb 100644
--- a/test/bacnet/basic/object/program/CMakeLists.txt
+++ b/test/bacnet/basic/object/program/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
${SRC_DIR}/bacnet/memcopy.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/schedule/CMakeLists.txt b/test/bacnet/basic/object/schedule/CMakeLists.txt
index 5e4103f5..8577590f 100644
--- a/test/bacnet/basic/object/schedule/CMakeLists.txt
+++ b/test/bacnet/basic/object/schedule/CMakeLists.txt
@@ -56,6 +56,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/structured_view/CMakeLists.txt b/test/bacnet/basic/object/structured_view/CMakeLists.txt
index 9e14de55..657e0827 100644
--- a/test/bacnet/basic/object/structured_view/CMakeLists.txt
+++ b/test/bacnet/basic/object/structured_view/CMakeLists.txt
@@ -55,6 +55,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
${SRC_DIR}/bacnet/property.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/time_value/CMakeLists.txt b/test/bacnet/basic/object/time_value/CMakeLists.txt
index ef7f4501..17560da0 100644
--- a/test/bacnet/basic/object/time_value/CMakeLists.txt
+++ b/test/bacnet/basic/object/time_value/CMakeLists.txt
@@ -56,6 +56,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/memcopy.c
diff --git a/test/bacnet/basic/object/timer/CMakeLists.txt b/test/bacnet/basic/object/timer/CMakeLists.txt
index 4ca4b802..40086c69 100644
--- a/test/bacnet/basic/object/timer/CMakeLists.txt
+++ b/test/bacnet/basic/object/timer/CMakeLists.txt
@@ -58,6 +58,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/property.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/object/trendlog/CMakeLists.txt b/test/bacnet/basic/object/trendlog/CMakeLists.txt
index 7923c1aa..5b2bc422 100644
--- a/test/bacnet/basic/object/trendlog/CMakeLists.txt
+++ b/test/bacnet/basic/object/trendlog/CMakeLists.txt
@@ -55,6 +55,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/basic/server/bacnet_device/CMakeLists.txt b/test/bacnet/basic/server/bacnet_device/CMakeLists.txt
index 9c9acbc5..ce9a3e12 100644
--- a/test/bacnet/basic/server/bacnet_device/CMakeLists.txt
+++ b/test/bacnet/basic/server/bacnet_device/CMakeLists.txt
@@ -107,6 +107,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/proplist.c
${SRC_DIR}/bacnet/property.c
${SRC_DIR}/bacnet/reject.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
diff --git a/test/bacnet/cov/CMakeLists.txt b/test/bacnet/cov/CMakeLists.txt
index 25aaabba..f57c75db 100644
--- a/test/bacnet/cov/CMakeLists.txt
+++ b/test/bacnet/cov/CMakeLists.txt
@@ -52,6 +52,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/memcopy.c
diff --git a/test/bacnet/create_object/CMakeLists.txt b/test/bacnet/create_object/CMakeLists.txt
index b890c20a..2c21fbe0 100644
--- a/test/bacnet/create_object/CMakeLists.txt
+++ b/test/bacnet/create_object/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/memcopy.c
diff --git a/test/bacnet/datalink/bsc-datalink/CMakeLists.txt b/test/bacnet/datalink/bsc-datalink/CMakeLists.txt
index d5dd1f00..e5d4aaca 100644
--- a/test/bacnet/datalink/bsc-datalink/CMakeLists.txt
+++ b/test/bacnet/datalink/bsc-datalink/CMakeLists.txt
@@ -196,6 +196,7 @@ target_sources(${PROJECT_NAME} PRIVATE
${SRC_DIR}/bacnet/special_event.c
${SRC_DIR}/bacnet/channel_value.c
${SRC_DIR}/bacnet/secure_connect.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/weeklyschedule.c
diff --git a/test/bacnet/datalink/bsc-node/CMakeLists.txt b/test/bacnet/datalink/bsc-node/CMakeLists.txt
index d86a8785..5558a9eb 100644
--- a/test/bacnet/datalink/bsc-node/CMakeLists.txt
+++ b/test/bacnet/datalink/bsc-node/CMakeLists.txt
@@ -186,6 +186,7 @@ target_sources(${PROJECT_NAME} PRIVATE
${SRC_DIR}/bacnet/special_event.c
${SRC_DIR}/bacnet/channel_value.c
${SRC_DIR}/bacnet/secure_connect.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/weeklyschedule.c
diff --git a/test/bacnet/datalink/bsc-socket/CMakeLists.txt b/test/bacnet/datalink/bsc-socket/CMakeLists.txt
index fa8c5a17..5fb40e46 100644
--- a/test/bacnet/datalink/bsc-socket/CMakeLists.txt
+++ b/test/bacnet/datalink/bsc-socket/CMakeLists.txt
@@ -184,6 +184,7 @@ target_sources(${PROJECT_NAME} PRIVATE
${SRC_DIR}/bacnet/special_event.c
${SRC_DIR}/bacnet/channel_value.c
${SRC_DIR}/bacnet/secure_connect.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/weeklyschedule.c
diff --git a/test/bacnet/datalink/hub-sc/CMakeLists.txt b/test/bacnet/datalink/hub-sc/CMakeLists.txt
index 54b46bad..7079e705 100644
--- a/test/bacnet/datalink/hub-sc/CMakeLists.txt
+++ b/test/bacnet/datalink/hub-sc/CMakeLists.txt
@@ -189,6 +189,7 @@ target_sources(${PROJECT_NAME} PRIVATE
${SRC_DIR}/bacnet/special_event.c
${SRC_DIR}/bacnet/channel_value.c
${SRC_DIR}/bacnet/secure_connect.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/weeklyschedule.c
diff --git a/test/bacnet/delete_object/CMakeLists.txt b/test/bacnet/delete_object/CMakeLists.txt
index 96868948..a36925dc 100644
--- a/test/bacnet/delete_object/CMakeLists.txt
+++ b/test/bacnet/delete_object/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/memcopy.c
diff --git a/test/bacnet/event/CMakeLists.txt b/test/bacnet/event/CMakeLists.txt
index ef457681..6568c750 100644
--- a/test/bacnet/event/CMakeLists.txt
+++ b/test/bacnet/event/CMakeLists.txt
@@ -67,6 +67,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/bactimevalue.c
${SRC_DIR}/bacnet/dailyschedule.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/hostnport.c
diff --git a/test/bacnet/getalarm/CMakeLists.txt b/test/bacnet/getalarm/CMakeLists.txt
index eea6560c..1ed623c2 100644
--- a/test/bacnet/getalarm/CMakeLists.txt
+++ b/test/bacnet/getalarm/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/weeklyschedule.c
diff --git a/test/bacnet/getevent/CMakeLists.txt b/test/bacnet/getevent/CMakeLists.txt
index 2b26be9c..a4c53767 100644
--- a/test/bacnet/getevent/CMakeLists.txt
+++ b/test/bacnet/getevent/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/weeklyschedule.c
diff --git a/test/bacnet/hostnport/CMakeLists.txt b/test/bacnet/hostnport/CMakeLists.txt
index 05c67ee7..51a7258f 100644
--- a/test/bacnet/hostnport/CMakeLists.txt
+++ b/test/bacnet/hostnport/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/memcopy.c
diff --git a/test/bacnet/list_element/CMakeLists.txt b/test/bacnet/list_element/CMakeLists.txt
index f3a1342e..3df93378 100644
--- a/test/bacnet/list_element/CMakeLists.txt
+++ b/test/bacnet/list_element/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/memcopy.c
diff --git a/test/bacnet/lso/CMakeLists.txt b/test/bacnet/lso/CMakeLists.txt
index ba900945..3c38a34d 100644
--- a/test/bacnet/lso/CMakeLists.txt
+++ b/test/bacnet/lso/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/memcopy.c
diff --git a/test/bacnet/ptransfer/CMakeLists.txt b/test/bacnet/ptransfer/CMakeLists.txt
index dc591bd4..da25a946 100644
--- a/test/bacnet/ptransfer/CMakeLists.txt
+++ b/test/bacnet/ptransfer/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/weeklyschedule.c
diff --git a/test/bacnet/rpm/CMakeLists.txt b/test/bacnet/rpm/CMakeLists.txt
index bf81c833..f7452c5d 100644
--- a/test/bacnet/rpm/CMakeLists.txt
+++ b/test/bacnet/rpm/CMakeLists.txt
@@ -54,6 +54,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/memcopy.c
diff --git a/test/bacnet/secure_connect/CMakeLists.txt b/test/bacnet/secure_connect/CMakeLists.txt
index b9af1d0f..4bb9ef78 100644
--- a/test/bacnet/secure_connect/CMakeLists.txt
+++ b/test/bacnet/secure_connect/CMakeLists.txt
@@ -54,6 +54,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/special_event.c
${SRC_DIR}/bacnet/channel_value.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/weeklyschedule.c
diff --git a/test/bacnet/shed_level/CMakeLists.txt b/test/bacnet/shed_level/CMakeLists.txt
new file mode 100644
index 00000000..0a5ad743
--- /dev/null
+++ b/test/bacnet/shed_level/CMakeLists.txt
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: MIT
+
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
+
+get_filename_component(basename ${CMAKE_CURRENT_SOURCE_DIR} NAME)
+project(test_${basename}
+ VERSION 1.0.0
+ LANGUAGES C)
+
+
+string(REGEX REPLACE
+ "/test/bacnet/[a-zA-Z_/-]*$"
+ "/src"
+ SRC_DIR
+ ${CMAKE_CURRENT_SOURCE_DIR})
+string(REGEX REPLACE
+ "/test/bacnet/[a-zA-Z_/-]*$"
+ "/test"
+ TST_DIR
+ ${CMAKE_CURRENT_SOURCE_DIR})
+set(ZTST_DIR "${TST_DIR}/ztest/src")
+
+add_compile_definitions(
+ BIG_ENDIAN=0
+ CONFIG_ZTEST=1
+ BACAPP_ALL
+ )
+
+include_directories(
+ ${SRC_DIR}
+ ${TST_DIR}/ztest/include
+ )
+
+add_executable(${PROJECT_NAME}
+ # File(s) under test
+ ${SRC_DIR}/bacnet/shed_level.c
+ # Support files and stubs (pathname alphabetical)
+ ${SRC_DIR}/bacnet/bacdcode.c
+ ${SRC_DIR}/bacnet/bacint.c
+ ${SRC_DIR}/bacnet/bacreal.c
+ ${SRC_DIR}/bacnet/bacstr.c
+ ${SRC_DIR}/bacnet/bactext.c
+ ${SRC_DIR}/bacnet/basic/sys/bigend.c
+ ${SRC_DIR}/bacnet/basic/sys/days.c
+ ${SRC_DIR}/bacnet/datetime.c
+ ${SRC_DIR}/bacnet/hostnport.c
+ ${SRC_DIR}/bacnet/indtext.c
+ ${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/timer_value.c
+ # Test and test library files
+ ./src/main.c
+ ${ZTST_DIR}/ztest_mock.c
+ ${ZTST_DIR}/ztest.c
+ )
diff --git a/test/bacnet/shed_level/src/main.c b/test/bacnet/shed_level/src/main.c
new file mode 100644
index 00000000..4bbf2cb2
--- /dev/null
+++ b/test/bacnet/shed_level/src/main.c
@@ -0,0 +1,111 @@
+/**
+ * @file
+ * @brief Unit test for BACnetShedLevel.
+ * @author Steve Karg
+ * @date October 2024
+ * @copyright SPDX-License-Identifier: MIT
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "bacnet/bactext.h"
+#include "bacnet/bacstr.h"
+#include "bacnet/shed_level.h"
+
+/**
+ * @addtogroup bacnet_tests
+ * @{
+ */
+
+/** @brief Test the BACnetShedLevel complex data encode/decode */
+#if defined(CONFIG_ZTEST_NEW_API)
+ZTEST(BACnetShedLevel_Tests, test_BACnetShedLevel)
+#else
+static void test_BACnetShedLevel(void)
+#endif
+{
+ uint8_t apdu[MAX_APDU];
+ int apdu_len, test_len, null_len;
+ bool status;
+ BACNET_SHED_LEVEL *value;
+ BACNET_SHED_LEVEL case_value[] = {
+ { .type = BACNET_SHED_TYPE_PERCENT, .value.percent = 75 },
+ { .type = BACNET_SHED_TYPE_LEVEL, .value.level = 12345 },
+ { .type = BACNET_SHED_TYPE_AMOUNT, .value.amount = 3.141592654f },
+ };
+ size_t i;
+ BACNET_SHED_LEVEL test_value = { 0 };
+ char buffer[64];
+
+ for (i = 0; i < ARRAY_SIZE(case_value); i++) {
+ value = &case_value[i];
+ null_len = bacnet_shed_level_encode(apdu, NULL);
+ zassert_equal(
+ null_len, 0, "value->type: %s null_len=%d",
+ bactext_shed_level_type_name(value->type), null_len);
+ null_len = bacnet_shed_level_encode(NULL, value);
+ apdu_len = bacnet_shed_level_encode(apdu, value);
+ zassert_equal(
+ apdu_len, null_len, "value->type: %s len=%d null_len=%d",
+ bactext_shed_level_type_name(value->type), apdu_len, null_len);
+ null_len = bacnet_shed_level_decode(NULL, apdu_len, &test_value);
+ zassert_equal(
+ null_len, BACNET_STATUS_ERROR, "value->type: %s null_len=%d",
+ bactext_shed_level_type_name(value->type), null_len);
+ null_len = bacnet_shed_level_decode(apdu, apdu_len, NULL);
+ zassert_equal(
+ null_len, apdu_len, "value->type: %s null_len=%d apdu_len=%d",
+ bactext_shed_level_type_name(value->type), null_len, apdu_len);
+ test_len = bacnet_shed_level_decode(apdu, apdu_len, &test_value);
+ zassert_not_equal(
+ test_len, BACNET_STATUS_ERROR, "value->type: %s test_len=%d",
+ bactext_shed_level_type_name(value->type), test_len);
+ zassert_equal(
+ test_len, apdu_len, "value->type: %s test_len=%d apdu_len=%d",
+ bactext_shed_level_type_name(value->type), test_len, apdu_len);
+ zassert_equal(
+ value->type, test_value.type, "value->type: %s test_type=%s",
+ bactext_shed_level_type_name(value->type),
+ bactext_shed_level_type_name(test_value.type));
+ status = bacnet_shed_level_same(value, &test_value);
+ zassert_true(
+ status, "decode: different: %s",
+ bactext_shed_level_type_name(value->type));
+ status = bacnet_shed_level_copy(&test_value, value);
+ zassert_true(
+ status, "copy: failed: %s",
+ bactext_shed_level_type_name(value->type));
+ status = bacnet_shed_level_same(value, &test_value);
+ zassert_true(
+ status, "copy: different: %s",
+ bactext_shed_level_type_name(value->type));
+ test_len = bacapp_snprintf_shed_level(buffer, sizeof(buffer), value);
+ zassert_true(
+ test_len > 0, "snprintf: failed: %s",
+ bactext_shed_level_type_name(value->type));
+ test_len = bacapp_snprintf_shed_level(buffer, 0, value);
+ zassert_true(
+ test_len > 0, "snprintf length only: failed: %s",
+ bactext_shed_level_type_name(value->type));
+ }
+}
+
+/**
+ * @}
+ */
+
+#if defined(CONFIG_ZTEST_NEW_API)
+ZTEST_SUITE(BACnetShedLevel_Tests, NULL, NULL, NULL, NULL, NULL);
+#else
+void test_main(void)
+{
+ ztest_test_suite(
+ BACnetShedLevel_Tests, ztest_unit_test(test_BACnetShedLevel));
+
+ ztest_run_test_suite(BACnetShedLevel_Tests);
+}
+#endif
diff --git a/test/bacnet/specialevent/CMakeLists.txt b/test/bacnet/specialevent/CMakeLists.txt
index 6365a499..36531216 100644
--- a/test/bacnet/specialevent/CMakeLists.txt
+++ b/test/bacnet/specialevent/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/bactimevalue.c
diff --git a/test/bacnet/timer_value/CMakeLists.txt b/test/bacnet/timer_value/CMakeLists.txt
index 7d5fdee6..b3a05964 100644
--- a/test/bacnet/timer_value/CMakeLists.txt
+++ b/test/bacnet/timer_value/CMakeLists.txt
@@ -47,6 +47,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
# Test and test library files
./src/main.c
${ZTST_DIR}/ztest_mock.c
diff --git a/test/bacnet/timesync/CMakeLists.txt b/test/bacnet/timesync/CMakeLists.txt
index a2452cf6..190804f6 100644
--- a/test/bacnet/timesync/CMakeLists.txt
+++ b/test/bacnet/timesync/CMakeLists.txt
@@ -54,6 +54,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/weeklyschedule.c
diff --git a/test/bacnet/weeklyschedule/CMakeLists.txt b/test/bacnet/weeklyschedule/CMakeLists.txt
index dfedeb81..2ae5fd55 100644
--- a/test/bacnet/weeklyschedule/CMakeLists.txt
+++ b/test/bacnet/weeklyschedule/CMakeLists.txt
@@ -55,6 +55,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/calendar_entry.c
diff --git a/test/bacnet/wp/CMakeLists.txt b/test/bacnet/wp/CMakeLists.txt
index f811ed87..4a3555d4 100644
--- a/test/bacnet/wp/CMakeLists.txt
+++ b/test/bacnet/wp/CMakeLists.txt
@@ -53,6 +53,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/indtext.c
diff --git a/test/bacnet/wpm/CMakeLists.txt b/test/bacnet/wpm/CMakeLists.txt
index 1708c908..7e1312d5 100644
--- a/test/bacnet/wpm/CMakeLists.txt
+++ b/test/bacnet/wpm/CMakeLists.txt
@@ -54,6 +54,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/indtext.c
diff --git a/test/bacnet/write_group/CMakeLists.txt b/test/bacnet/write_group/CMakeLists.txt
index 2698fd5a..13730161 100644
--- a/test/bacnet/write_group/CMakeLists.txt
+++ b/test/bacnet/write_group/CMakeLists.txt
@@ -52,6 +52,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
+ ${SRC_DIR}/bacnet/shed_level.c
${SRC_DIR}/bacnet/timer_value.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/indtext.c