Fixed channel-value encoding in the channel object when no-coercian is required for lighting-command, color-command, and xy-color. (#1190)
This commit is contained in:
@@ -66,6 +66,8 @@ The git repositories are hosted at the following sites:
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed channel-value encoding in the channel object when no-coercian
|
||||
is required for lighting-command, color-command, and xy-color. (#1190)
|
||||
* Fixed NULL handling in CharacterString sprintf which caused an endless
|
||||
loop. (#1189)
|
||||
* Fixed a regression in the rpm_ack_object_property_process() function
|
||||
|
||||
@@ -657,7 +657,7 @@ bool Channel_Write_Member_Value(
|
||||
}
|
||||
} else {
|
||||
/* no coercion */
|
||||
apdu_len = bacnet_channel_value_encode(
|
||||
apdu_len = bacnet_channel_value_no_coerce_encode(
|
||||
wp_data->application_data, wp_data->application_data_len,
|
||||
value);
|
||||
if (apdu_len > 0) {
|
||||
|
||||
@@ -1164,3 +1164,203 @@ int bacnet_channel_value_coerce_data_encode(
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode a given BACnetChannelValue to use for internal writes
|
||||
* This function encodes the complex data types without context tags
|
||||
* normally used for BACnetChannelValue.
|
||||
* @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, or zero if unable to encode
|
||||
*/
|
||||
int bacnet_channel_value_no_coerce_type_encode(
|
||||
uint8_t *apdu, const BACNET_CHANNEL_VALUE *value)
|
||||
{
|
||||
int apdu_len = 0;
|
||||
|
||||
if (!value) {
|
||||
return 0;
|
||||
}
|
||||
switch (value->tag) {
|
||||
#if defined(CHANNEL_LIGHTING_COMMAND)
|
||||
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
|
||||
apdu_len =
|
||||
lighting_command_encode(apdu, &value->type.Lighting_Command);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_COLOR_COMMAND)
|
||||
case BACNET_APPLICATION_TAG_COLOR_COMMAND:
|
||||
apdu_len = color_command_encode(apdu, &value->type.Color_Command);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_XY_COLOR)
|
||||
case BACNET_APPLICATION_TAG_XY_COLOR:
|
||||
apdu_len = xy_color_encode(apdu, &value->type.XY_Color);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
apdu_len = bacnet_channel_value_type_encode(apdu, value);
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode a given BACnetChannelValue to use for internal writes
|
||||
* This function encodes the complex data types without context tags
|
||||
* normally used for BACnetChannelValue.
|
||||
* @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 zero if unable to encode
|
||||
*/
|
||||
int bacnet_channel_value_no_coerce_encode(
|
||||
uint8_t *apdu, size_t apdu_size, const BACNET_CHANNEL_VALUE *value)
|
||||
{
|
||||
size_t apdu_len = 0; /* total length of the apdu, return value */
|
||||
|
||||
apdu_len = bacnet_channel_value_no_coerce_type_encode(NULL, value);
|
||||
if (apdu_len > apdu_size) {
|
||||
apdu_len = 0;
|
||||
} else {
|
||||
apdu_len = bacnet_channel_value_no_coerce_type_encode(apdu, value);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decode a given BACnetChannelValue to use for internal writes
|
||||
* This function decodes the complex data types without context tags
|
||||
* normally used for BACnetChannelValue.
|
||||
* @param apdu - APDU buffer for decoding
|
||||
* @param apdu_size - Count of valid bytes in the buffer
|
||||
* @param tag - application tag of the data to decode
|
||||
* @param value - BACNET_CHANNEL_VALUE value to store the decoded data
|
||||
* @return number of bytes decoded or BACNET_STATUS_ERROR on error
|
||||
*/
|
||||
int bacnet_channel_value_no_coerce_decode(
|
||||
const uint8_t *apdu,
|
||||
size_t apdu_size,
|
||||
uint8_t tag,
|
||||
BACNET_CHANNEL_VALUE *value)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
if (!apdu) {
|
||||
return BACNET_STATUS_ERROR;
|
||||
}
|
||||
if (!value) {
|
||||
return BACNET_STATUS_ERROR;
|
||||
}
|
||||
switch (tag) {
|
||||
case BACNET_APPLICATION_TAG_NULL:
|
||||
/* nothing else to do */
|
||||
break;
|
||||
#if defined(CHANNEL_BOOLEAN)
|
||||
case BACNET_APPLICATION_TAG_BOOLEAN:
|
||||
len = bacnet_boolean_application_decode(
|
||||
apdu, apdu_size, &value->type.Boolean);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_UNSIGNED)
|
||||
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
|
||||
len = bacnet_unsigned_application_decode(
|
||||
apdu, apdu_size, &value->type.Unsigned_Int);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_SIGNED)
|
||||
case BACNET_APPLICATION_TAG_SIGNED_INT:
|
||||
len = bacnet_signed_application_decode(
|
||||
apdu, apdu_size, &value->type.Signed_Int);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_REAL)
|
||||
case BACNET_APPLICATION_TAG_REAL:
|
||||
len = bacnet_real_application_decode(
|
||||
apdu, apdu_size, &value->type.Real);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_DOUBLE)
|
||||
case BACNET_APPLICATION_TAG_DOUBLE:
|
||||
len = bacnet_double_application_decode(
|
||||
apdu, apdu_size, &value->type.Double);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_OCTET_STRING)
|
||||
case BACNET_APPLICATION_TAG_OCTET_STRING:
|
||||
len = bacnet_octet_string_application_decode(
|
||||
apdu, apdu_size, &value->type.Octet_String);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_CHARACTER_STRING)
|
||||
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
|
||||
len = bacnet_character_string_application_decode(
|
||||
apdu, apdu_size, &value->type.Character_String);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_BIT_STRING)
|
||||
case BACNET_APPLICATION_TAG_BIT_STRING:
|
||||
len = bacnet_bitstring_application_decode(
|
||||
apdu, apdu_size, &value->type.Bit_String);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_ENUMERATED)
|
||||
case BACNET_APPLICATION_TAG_ENUMERATED:
|
||||
len = bacnet_enumerated_application_decode(
|
||||
apdu, apdu_size, &value->type.Enumerated);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_DATE)
|
||||
case BACNET_APPLICATION_TAG_DATE:
|
||||
len = bacnet_date_application_decode(
|
||||
apdu, apdu_size, &value->type.Date);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_TIME)
|
||||
case BACNET_APPLICATION_TAG_TIME:
|
||||
len = bacnet_time_application_decode(
|
||||
apdu, apdu_size, &value->type.Time);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_OBJECT_ID)
|
||||
case BACNET_APPLICATION_TAG_OBJECT_ID:
|
||||
len = bacnet_object_id_application_decode(
|
||||
apdu, apdu_size, &value->type.Object_Id.type,
|
||||
&value->type.Object_Id.instance);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_LIGHTING_COMMAND)
|
||||
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
|
||||
len = lighting_command_decode(
|
||||
apdu, apdu_size, &value->type.Lighting_Command);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_COLOR_COMMAND)
|
||||
case BACNET_APPLICATION_TAG_COLOR_COMMAND:
|
||||
len = color_command_decode(
|
||||
apdu, apdu_size, NULL, &value->type.Color_Command);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CHANNEL_XY_COLOR)
|
||||
case BACNET_APPLICATION_TAG_XY_COLOR:
|
||||
len = xy_color_decode(apdu, apdu_size, &value->type.XY_Color);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
len = BACNET_STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
if ((len == 0) && (tag != BACNET_APPLICATION_TAG_NULL) &&
|
||||
(tag != BACNET_APPLICATION_TAG_BOOLEAN) &&
|
||||
(tag != BACNET_APPLICATION_TAG_OCTET_STRING)) {
|
||||
/* indicate that we were not able to decode the value */
|
||||
len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
if (len != BACNET_STATUS_ERROR) {
|
||||
value->tag = tag;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -165,6 +165,18 @@ int bacnet_channel_value_coerce_data_encode(
|
||||
size_t apdu_size,
|
||||
const BACNET_CHANNEL_VALUE *value,
|
||||
BACNET_APPLICATION_TAG tag);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_channel_value_no_coerce_type_encode(
|
||||
uint8_t *apdu, const BACNET_CHANNEL_VALUE *value);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_channel_value_no_coerce_encode(
|
||||
uint8_t *apdu, size_t apdu_size, const BACNET_CHANNEL_VALUE *value);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_channel_value_no_coerce_decode(
|
||||
const uint8_t *apdu,
|
||||
size_t apdu_size,
|
||||
uint8_t tag,
|
||||
BACNET_CHANNEL_VALUE *value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -402,7 +402,7 @@ static void test_BACnetChannelValue(void)
|
||||
bacnet_channel_value_link_array(case_value, ARRAY_SIZE(case_value));
|
||||
value = &case_value[0];
|
||||
while (value) {
|
||||
/* no coercion path */
|
||||
/* write-group encode/decode path */
|
||||
null_len = bacnet_channel_value_encode(NULL, sizeof(apdu), value);
|
||||
if (value->tag != BACNET_APPLICATION_TAG_NULL) {
|
||||
zassert_not_equal(null_len, 0, NULL);
|
||||
@@ -464,6 +464,33 @@ static void test_BACnetChannelValue(void)
|
||||
zassert_true(
|
||||
status, "decode: different: %s",
|
||||
bactext_application_tag_name(value->tag));
|
||||
/* no-coercion path */
|
||||
null_len =
|
||||
bacnet_channel_value_no_coerce_encode(NULL, sizeof(apdu), value);
|
||||
if (value->tag != BACNET_APPLICATION_TAG_NULL) {
|
||||
zassert_not_equal(null_len, 0, NULL);
|
||||
}
|
||||
apdu_len =
|
||||
bacnet_channel_value_no_coerce_encode(apdu, sizeof(apdu), value);
|
||||
zassert_equal(
|
||||
apdu_len, null_len, "value->tag: %s len=%d null_len=%d",
|
||||
bactext_application_tag_name(value->tag), apdu_len, null_len);
|
||||
test_len = bacnet_channel_value_no_coerce_decode(
|
||||
apdu, apdu_len, test_value.tag, NULL);
|
||||
zassert_equal(test_len, BACNET_STATUS_ERROR, NULL);
|
||||
test_len = bacnet_channel_value_no_coerce_decode(
|
||||
NULL, apdu_len, test_value.tag, &test_value);
|
||||
zassert_equal(test_len, BACNET_STATUS_ERROR, NULL);
|
||||
test_len = bacnet_channel_value_no_coerce_decode(
|
||||
apdu, apdu_len, test_value.tag, &test_value);
|
||||
zassert_not_equal(
|
||||
test_len, BACNET_STATUS_ERROR, "value->tag: %s test_len=%d",
|
||||
bactext_application_tag_name(value->tag), test_len);
|
||||
if (value->tag != BACNET_APPLICATION_TAG_NULL) {
|
||||
zassert_equal(
|
||||
test_len, apdu_len, "value->tag: %s test_len=%d",
|
||||
bactext_application_tag_name(value->tag), test_len);
|
||||
}
|
||||
/* next test case */
|
||||
value = value->next;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user