Fixed writing to the Channel object when no member value coercion was required. (#1176)
* Updated documentation for encode functions to accurately describe return values (0 on error instead of BACNET_STATUS_ERROR) * Expanded property support, removed INPUT object types, added fallback encoding for non-coerced data types, and updated error handling in ReadProperty of present-value to check for 0 instead of BACNET_STATUS_ERROR. * Expanded the validation tests and increased test code coverage.
This commit is contained in:
+6
-1
@@ -21,6 +21,8 @@ The git repositories are hosted at the following sites:
|
||||
|
||||
### Added
|
||||
|
||||
* Added properties to the Channel object write member value coercion
|
||||
minimal properties supported. (#1176)
|
||||
* Added Send_x_Address() API to ReadPropertyMultiple, WritePropertyMultiple,
|
||||
and SubscribeSOV services primarily for interacting with MS/TP slaves (#1174)
|
||||
* Added npdu_set_i_am_router_to_network_handler() API. Fixed sending to
|
||||
@@ -54,9 +56,12 @@ The git repositories are hosted at the following sites:
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed the Channel object to handle all data types that do not need
|
||||
coercion when written. Fixed present-value when no value is able to
|
||||
be encoded. (#1176)
|
||||
* Fixed the Loop object read/write references and manipulated variables
|
||||
update during timer loop by adding callbacks to device read/write property
|
||||
in basic example device object. (##1175)
|
||||
in basic example device object. (#1175)
|
||||
* Fixed library specific strcmp/stricmp functions match standard strcmp. (#1173)
|
||||
* Fixed compiler macro redefined warning when optional datatypes are defined
|
||||
globally. (#1172)
|
||||
|
||||
@@ -581,10 +581,10 @@ bool Channel_Write_Member_Value(
|
||||
int apdu_len = 0;
|
||||
|
||||
if (wp_data && value) {
|
||||
if (((wp_data->object_type == OBJECT_ANALOG_INPUT) ||
|
||||
(wp_data->object_type == OBJECT_ANALOG_OUTPUT) ||
|
||||
if (((wp_data->object_type == OBJECT_ANALOG_OUTPUT) ||
|
||||
(wp_data->object_type == OBJECT_ANALOG_VALUE)) &&
|
||||
(wp_data->object_property == PROP_PRESENT_VALUE) &&
|
||||
((wp_data->object_property == PROP_PRESENT_VALUE) ||
|
||||
(wp_data->object_property == PROP_RELINQUISH_DEFAULT)) &&
|
||||
(wp_data->array_index == BACNET_ARRAY_ALL)) {
|
||||
apdu_len = bacnet_channel_value_coerce_data_encode(
|
||||
wp_data->application_data, wp_data->application_data_len, value,
|
||||
@@ -594,10 +594,10 @@ bool Channel_Write_Member_Value(
|
||||
status = true;
|
||||
}
|
||||
} else if (
|
||||
((wp_data->object_type == OBJECT_BINARY_INPUT) ||
|
||||
(wp_data->object_type == OBJECT_BINARY_OUTPUT) ||
|
||||
((wp_data->object_type == OBJECT_BINARY_OUTPUT) ||
|
||||
(wp_data->object_type == OBJECT_BINARY_VALUE)) &&
|
||||
(wp_data->object_property == PROP_PRESENT_VALUE) &&
|
||||
((wp_data->object_property == PROP_PRESENT_VALUE) ||
|
||||
(wp_data->object_property == PROP_RELINQUISH_DEFAULT)) &&
|
||||
(wp_data->array_index == BACNET_ARRAY_ALL)) {
|
||||
apdu_len = bacnet_channel_value_coerce_data_encode(
|
||||
wp_data->application_data, wp_data->application_data_len, value,
|
||||
@@ -607,10 +607,10 @@ bool Channel_Write_Member_Value(
|
||||
status = true;
|
||||
}
|
||||
} else if (
|
||||
((wp_data->object_type == OBJECT_MULTI_STATE_INPUT) ||
|
||||
(wp_data->object_type == OBJECT_MULTI_STATE_OUTPUT) ||
|
||||
((wp_data->object_type == OBJECT_MULTI_STATE_OUTPUT) ||
|
||||
(wp_data->object_type == OBJECT_MULTI_STATE_VALUE)) &&
|
||||
(wp_data->object_property == PROP_PRESENT_VALUE) &&
|
||||
((wp_data->object_property == PROP_PRESENT_VALUE) ||
|
||||
(wp_data->object_property == PROP_RELINQUISH_DEFAULT)) &&
|
||||
(wp_data->array_index == BACNET_ARRAY_ALL)) {
|
||||
apdu_len = bacnet_channel_value_coerce_data_encode(
|
||||
wp_data->application_data, wp_data->application_data_len, value,
|
||||
@@ -619,49 +619,35 @@ bool Channel_Write_Member_Value(
|
||||
wp_data->application_data_len = apdu_len;
|
||||
status = true;
|
||||
}
|
||||
} else if (wp_data->object_type == OBJECT_LIGHTING_OUTPUT) {
|
||||
if ((wp_data->object_property == PROP_PRESENT_VALUE) &&
|
||||
(wp_data->array_index == BACNET_ARRAY_ALL)) {
|
||||
apdu_len = bacnet_channel_value_coerce_data_encode(
|
||||
wp_data->application_data, wp_data->application_data_len,
|
||||
value, BACNET_APPLICATION_TAG_REAL);
|
||||
if (apdu_len != BACNET_STATUS_ERROR) {
|
||||
wp_data->application_data_len = apdu_len;
|
||||
status = true;
|
||||
}
|
||||
} else if (
|
||||
(wp_data->object_property == PROP_LIGHTING_COMMAND) &&
|
||||
(wp_data->array_index == BACNET_ARRAY_ALL)) {
|
||||
apdu_len = bacnet_channel_value_coerce_data_encode(
|
||||
wp_data->application_data, wp_data->application_data_len,
|
||||
value, BACNET_APPLICATION_TAG_LIGHTING_COMMAND);
|
||||
if (apdu_len != BACNET_STATUS_ERROR) {
|
||||
wp_data->application_data_len = apdu_len;
|
||||
status = true;
|
||||
}
|
||||
} else if (
|
||||
(wp_data->object_type == OBJECT_LIGHTING_OUTPUT) &&
|
||||
((wp_data->object_property == PROP_PRESENT_VALUE) ||
|
||||
(wp_data->object_property == PROP_RELINQUISH_DEFAULT)) &&
|
||||
(wp_data->array_index == BACNET_ARRAY_ALL)) {
|
||||
apdu_len = bacnet_channel_value_coerce_data_encode(
|
||||
wp_data->application_data, wp_data->application_data_len, value,
|
||||
BACNET_APPLICATION_TAG_REAL);
|
||||
if (apdu_len != BACNET_STATUS_ERROR) {
|
||||
wp_data->application_data_len = apdu_len;
|
||||
status = true;
|
||||
}
|
||||
} else if (wp_data->object_type == OBJECT_COLOR) {
|
||||
if ((wp_data->object_property == PROP_PRESENT_VALUE) &&
|
||||
(wp_data->array_index == BACNET_ARRAY_ALL)) {
|
||||
apdu_len = bacnet_channel_value_coerce_data_encode(
|
||||
wp_data->application_data, wp_data->application_data_len,
|
||||
value, BACNET_APPLICATION_TAG_XY_COLOR);
|
||||
if (apdu_len != BACNET_STATUS_ERROR) {
|
||||
wp_data->application_data_len = apdu_len;
|
||||
status = true;
|
||||
}
|
||||
} else if (
|
||||
(wp_data->object_property == PROP_COLOR_COMMAND) &&
|
||||
(wp_data->array_index == BACNET_ARRAY_ALL)) {
|
||||
apdu_len = bacnet_channel_value_coerce_data_encode(
|
||||
wp_data->application_data, wp_data->application_data_len,
|
||||
value, BACNET_APPLICATION_TAG_COLOR_COMMAND);
|
||||
if (apdu_len != BACNET_STATUS_ERROR) {
|
||||
wp_data->application_data_len = apdu_len;
|
||||
status = true;
|
||||
}
|
||||
} else if (
|
||||
(wp_data->object_type == OBJECT_COLOR) &&
|
||||
((wp_data->object_property == PROP_PRESENT_VALUE) ||
|
||||
(wp_data->object_property == PROP_DEFAULT_COLOR)) &&
|
||||
(wp_data->array_index == BACNET_ARRAY_ALL)) {
|
||||
apdu_len = bacnet_channel_value_coerce_data_encode(
|
||||
wp_data->application_data, wp_data->application_data_len, value,
|
||||
BACNET_APPLICATION_TAG_XY_COLOR);
|
||||
if (apdu_len != BACNET_STATUS_ERROR) {
|
||||
wp_data->application_data_len = apdu_len;
|
||||
status = true;
|
||||
}
|
||||
} else if (wp_data->object_type == OBJECT_COLOR_TEMPERATURE) {
|
||||
} else if (
|
||||
(wp_data->object_type == OBJECT_COLOR_TEMPERATURE) &&
|
||||
((wp_data->object_property == PROP_PRESENT_VALUE) ||
|
||||
(wp_data->object_property == PROP_DEFAULT_COLOR_TEMPERATURE)) &&
|
||||
(wp_data->array_index == BACNET_ARRAY_ALL)) {
|
||||
apdu_len = bacnet_channel_value_coerce_data_encode(
|
||||
wp_data->application_data, wp_data->application_data_len, value,
|
||||
BACNET_APPLICATION_TAG_UNSIGNED_INT);
|
||||
@@ -669,6 +655,15 @@ bool Channel_Write_Member_Value(
|
||||
wp_data->application_data_len = apdu_len;
|
||||
status = true;
|
||||
}
|
||||
} else {
|
||||
/* no coercion */
|
||||
apdu_len = bacnet_channel_value_encode(
|
||||
wp_data->application_data, wp_data->application_data_len,
|
||||
value);
|
||||
if (apdu_len > 0) {
|
||||
wp_data->application_data_len = apdu_len;
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -991,7 +986,7 @@ int Channel_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
case PROP_PRESENT_VALUE:
|
||||
cvalue = Channel_Present_Value(rpdata->object_instance);
|
||||
apdu_len = bacnet_channel_value_encode(apdu, apdu_size, cvalue);
|
||||
if (apdu_len == BACNET_STATUS_ERROR) {
|
||||
if (apdu_len == 0) {
|
||||
apdu_len = encode_application_null(apdu);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* @brief Encode a given BACnetChanneValue
|
||||
* @param apdu - APDU buffer for storing the encoded data, or NULL for length
|
||||
* @param value - BACNET_CHANNEL_VALUE value
|
||||
* @return number of bytes in the APDU
|
||||
* @return number of bytes in the APDU, or zero if unable to encode
|
||||
*/
|
||||
int bacnet_channel_value_type_encode(
|
||||
uint8_t *apdu, const BACNET_CHANNEL_VALUE *value)
|
||||
@@ -245,7 +245,7 @@ int bacnet_channel_value_type_decode(
|
||||
* @param apdu - APDU buffer for storing the encoded data, or NULL for length
|
||||
* @param apdu_size - size of the APDU buffer
|
||||
* @param value - BACNET_CHANNEL_VALUE value
|
||||
* @return number of bytes in the APDU, or BACNET_STATUS_ERROR
|
||||
* @return number of bytes in the APDU, or zero if unable to encode
|
||||
*/
|
||||
int bacnet_channel_value_encode(
|
||||
uint8_t *apdu, size_t apdu_size, const BACNET_CHANNEL_VALUE *value)
|
||||
|
||||
@@ -23,6 +23,7 @@ set(ZTST_DIR "${TST_DIR}/ztest/src")
|
||||
add_compile_definitions(
|
||||
BIG_ENDIAN=0
|
||||
CONFIG_ZTEST=1
|
||||
CHANNEL_MEMBERS_MAX=16
|
||||
)
|
||||
|
||||
include_directories(
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
* @addtogroup bacnet_tests
|
||||
* @{
|
||||
*/
|
||||
static BACNET_WRITE_PROPERTY_DATA Write_Property_Internal_Data;
|
||||
static bool Write_Property_Internal(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
memcpy(
|
||||
&Write_Property_Internal_Data, wp_data,
|
||||
sizeof(BACNET_WRITE_PROPERTY_DATA));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test
|
||||
@@ -32,9 +41,12 @@ static void test_Channel_Property_Read_Write(void)
|
||||
const int32_t skip_fail_property_list[] = { -1 };
|
||||
BACNET_CHANNEL_VALUE channel_value = { 0 };
|
||||
BACNET_WRITE_PROPERTY_DATA wp_data = { 0 };
|
||||
BACNET_WRITE_GROUP_DATA wg_data = { 0 };
|
||||
|
||||
BACNET_APPLICATION_DATA_VALUE value = { 0 };
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE member = { 0 };
|
||||
|
||||
Channel_Write_Property_Internal_Callback_Set(Write_Property_Internal);
|
||||
Channel_Init();
|
||||
Channel_Create(instance);
|
||||
status = Channel_Valid_Instance(instance);
|
||||
@@ -52,8 +64,8 @@ static void test_Channel_Property_Read_Write(void)
|
||||
member.deviceIdentifier.instance = 0;
|
||||
member.objectIdentifier.type = OBJECT_ANALOG_OUTPUT;
|
||||
member.objectIdentifier.instance = 1;
|
||||
member.propertyIdentifier = PROP_PRESENT_VALUE;
|
||||
member.arrayIndex = BACNET_ARRAY_ALL;
|
||||
member.propertyIdentifier = PROP_PRESENT_VALUE;
|
||||
index = Channel_Reference_List_Member_Element_Add(instance, &member);
|
||||
zassert_not_equal(index, 0, NULL);
|
||||
status =
|
||||
@@ -61,6 +73,9 @@ static void test_Channel_Property_Read_Write(void)
|
||||
zassert_true(status, NULL);
|
||||
status = Channel_Control_Groups_Element_Set(instance, 1, 1);
|
||||
zassert_true(status, NULL);
|
||||
member.propertyIdentifier = PROP_RELINQUISH_DEFAULT;
|
||||
index = Channel_Reference_List_Member_Element_Add(instance, &member);
|
||||
zassert_not_equal(index, 0, NULL);
|
||||
member.deviceIdentifier.type = OBJECT_DEVICE;
|
||||
member.deviceIdentifier.instance = 0;
|
||||
member.objectIdentifier.type = OBJECT_BINARY_OUTPUT;
|
||||
@@ -69,6 +84,9 @@ static void test_Channel_Property_Read_Write(void)
|
||||
member.arrayIndex = BACNET_ARRAY_ALL;
|
||||
index = Channel_Reference_List_Member_Element_Add(instance, &member);
|
||||
zassert_not_equal(index, 0, NULL);
|
||||
member.propertyIdentifier = PROP_RELINQUISH_DEFAULT;
|
||||
index = Channel_Reference_List_Member_Element_Add(instance, &member);
|
||||
zassert_not_equal(index, 0, NULL);
|
||||
member.deviceIdentifier.type = OBJECT_DEVICE;
|
||||
member.deviceIdentifier.instance = 0;
|
||||
member.objectIdentifier.type = OBJECT_MULTI_STATE_OUTPUT;
|
||||
@@ -77,6 +95,9 @@ static void test_Channel_Property_Read_Write(void)
|
||||
member.arrayIndex = BACNET_ARRAY_ALL;
|
||||
index = Channel_Reference_List_Member_Element_Add(instance, &member);
|
||||
zassert_not_equal(index, 0, NULL);
|
||||
member.propertyIdentifier = PROP_RELINQUISH_DEFAULT;
|
||||
index = Channel_Reference_List_Member_Element_Add(instance, &member);
|
||||
zassert_not_equal(index, 0, NULL);
|
||||
member.deviceIdentifier.type = OBJECT_DEVICE;
|
||||
member.deviceIdentifier.instance = 0;
|
||||
member.objectIdentifier.type = OBJECT_LIGHTING_OUTPUT;
|
||||
@@ -85,6 +106,12 @@ static void test_Channel_Property_Read_Write(void)
|
||||
member.arrayIndex = BACNET_ARRAY_ALL;
|
||||
index = Channel_Reference_List_Member_Element_Add(instance, &member);
|
||||
zassert_not_equal(index, 0, NULL);
|
||||
member.propertyIdentifier = PROP_RELINQUISH_DEFAULT;
|
||||
index = Channel_Reference_List_Member_Element_Add(instance, &member);
|
||||
zassert_not_equal(index, 0, NULL);
|
||||
member.propertyIdentifier = PROP_HIGH_END_TRIM;
|
||||
index = Channel_Reference_List_Member_Element_Add(instance, &member);
|
||||
zassert_not_equal(index, 0, NULL);
|
||||
member.deviceIdentifier.type = OBJECT_DEVICE;
|
||||
member.deviceIdentifier.instance = 0;
|
||||
member.objectIdentifier.type = OBJECT_COLOR;
|
||||
@@ -93,6 +120,9 @@ static void test_Channel_Property_Read_Write(void)
|
||||
member.arrayIndex = BACNET_ARRAY_ALL;
|
||||
index = Channel_Reference_List_Member_Element_Add(instance, &member);
|
||||
zassert_not_equal(index, 0, NULL);
|
||||
member.propertyIdentifier = PROP_DEFAULT_COLOR;
|
||||
index = Channel_Reference_List_Member_Element_Add(instance, &member);
|
||||
zassert_not_equal(index, 0, NULL);
|
||||
member.deviceIdentifier.type = OBJECT_DEVICE;
|
||||
member.deviceIdentifier.instance = 0;
|
||||
member.objectIdentifier.type = OBJECT_COLOR_TEMPERATURE;
|
||||
@@ -101,6 +131,9 @@ static void test_Channel_Property_Read_Write(void)
|
||||
member.arrayIndex = BACNET_ARRAY_ALL;
|
||||
index = Channel_Reference_List_Member_Element_Add(instance, &member);
|
||||
zassert_not_equal(index, 0, NULL);
|
||||
member.propertyIdentifier = PROP_DEFAULT_COLOR_TEMPERATURE;
|
||||
index = Channel_Reference_List_Member_Element_Add(instance, &member);
|
||||
zassert_not_equal(index, 0, NULL);
|
||||
/* perform a general test for RP/WP */
|
||||
bacnet_object_properties_read_write_test(
|
||||
OBJECT_CHANNEL, instance, Channel_Property_Lists, Channel_Read_Property,
|
||||
@@ -129,6 +162,13 @@ static void test_Channel_Property_Read_Write(void)
|
||||
bacapp_encode_application_data(wp_data.application_data, &value);
|
||||
status = Channel_Write_Property(&wp_data);
|
||||
zassert_true(status, NULL);
|
||||
value.type.Channel_Value.tag = BACNET_APPLICATION_TAG_XY_COLOR;
|
||||
value.type.Channel_Value.type.XY_Color.x_coordinate = 0.4590f;
|
||||
value.type.Channel_Value.type.XY_Color.y_coordinate = 0.4101f;
|
||||
wp_data.application_data_len =
|
||||
bacapp_encode_application_data(wp_data.application_data, &value);
|
||||
status = Channel_Write_Property(&wp_data);
|
||||
zassert_true(status, NULL);
|
||||
/* specific WriteProperty value */
|
||||
wp_data.object_property = PROP_OUT_OF_SERVICE;
|
||||
value.tag = BACNET_APPLICATION_TAG_BOOLEAN;
|
||||
@@ -235,6 +275,16 @@ static void test_Channel_Property_Read_Write(void)
|
||||
channel_value.type.Real = 3.14159f;
|
||||
status = Channel_Present_Value_Set(instance, 1, &channel_value);
|
||||
zassert_true(status, NULL);
|
||||
/* context API */
|
||||
Channel_Context_Set(instance, Channel_Context_Get(instance));
|
||||
/* WriteGroup API */
|
||||
wg_data.change_list.channel = 1;
|
||||
wg_data.change_list.overriding_priority = BACNET_MAX_PRIORITY;
|
||||
wg_data.change_list.value.tag = BACNET_APPLICATION_TAG_REAL;
|
||||
wg_data.change_list.value.type.Real = 2.71828f;
|
||||
wg_data.inhibit_delay = 0;
|
||||
wg_data.write_priority = BACNET_MAX_PRIORITY;
|
||||
Channel_Write_Group(&wg_data, 0, &wg_data.change_list);
|
||||
/* cleanup */
|
||||
status = Channel_Delete(instance);
|
||||
zassert_true(status, NULL);
|
||||
|
||||
Reference in New Issue
Block a user