Bugfix/bacapp deprecation fixes (#578)
* Secured bacapp_decode_application_data_safe(), bacapp_decode_application_data_len(), bacapp_decode_context_data(), bacapp_decode_known_property() for timestamp, bacapp_decode_context_data_len(), and bacapp_data_len() functions. * Fixed Command, Credential Data Input, and Schedule objects unit test
This commit is contained in:
+230
-210
@@ -251,14 +251,19 @@ int bacapp_encode_application_data(
|
|||||||
/**
|
/**
|
||||||
* @brief Decode the data and store it into value.
|
* @brief Decode the data and store it into value.
|
||||||
* @param apdu Receive buffer
|
* @param apdu Receive buffer
|
||||||
|
* @param apdu_size Size of the receive buffer
|
||||||
* @param tag_data_type Data type of the given tag
|
* @param tag_data_type Data type of the given tag
|
||||||
* @param len_value_type Count of bytes of given tag
|
* @param len_value_type Count of bytes of given tag
|
||||||
* @param value Pointer to the application value structure,
|
* @param value Pointer to the application value structure,
|
||||||
* used to store the decoded value to.
|
* used to store the decoded value to.
|
||||||
*
|
*
|
||||||
* @return Number of octets consumed.
|
* @return Number of octets consumed (could be zero).
|
||||||
|
* Parameter value->tag set to MAX_BACNET_APPLICATION_TAG when
|
||||||
|
* the number of octets consumed is zero and there is an error
|
||||||
|
* in the decoding, or BACNET_STATUS_ERROR/ABORT/REJECT if malformed.
|
||||||
*/
|
*/
|
||||||
int bacapp_decode_data(uint8_t *apdu,
|
int bacapp_data_decode(uint8_t *apdu,
|
||||||
|
uint32_t apdu_size,
|
||||||
uint8_t tag_data_type,
|
uint8_t tag_data_type,
|
||||||
uint32_t len_value_type,
|
uint32_t len_value_type,
|
||||||
BACNET_APPLICATION_DATA_VALUE *value)
|
BACNET_APPLICATION_DATA_VALUE *value)
|
||||||
@@ -279,162 +284,158 @@ int bacapp_decode_data(uint8_t *apdu,
|
|||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_UNSIGNED)
|
#if defined(BACAPP_UNSIGNED)
|
||||||
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
|
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
|
||||||
len = decode_unsigned(
|
len = bacnet_unsigned_decode(
|
||||||
apdu, len_value_type, &value->type.Unsigned_Int);
|
apdu, apdu_size, len_value_type, &value->type.Unsigned_Int);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_SIGNED)
|
#if defined(BACAPP_SIGNED)
|
||||||
case BACNET_APPLICATION_TAG_SIGNED_INT:
|
case BACNET_APPLICATION_TAG_SIGNED_INT:
|
||||||
len = decode_signed(
|
len = bacnet_signed_decode(
|
||||||
apdu, len_value_type, &value->type.Signed_Int);
|
apdu, apdu_size, len_value_type, &value->type.Signed_Int);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_REAL)
|
#if defined(BACAPP_REAL)
|
||||||
case BACNET_APPLICATION_TAG_REAL:
|
case BACNET_APPLICATION_TAG_REAL:
|
||||||
len =
|
len = bacnet_real_decode(
|
||||||
decode_real_safe(apdu, len_value_type, &(value->type.Real));
|
apdu, apdu_size, len_value_type, &(value->type.Real));
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_DOUBLE)
|
#if defined(BACAPP_DOUBLE)
|
||||||
case BACNET_APPLICATION_TAG_DOUBLE:
|
case BACNET_APPLICATION_TAG_DOUBLE:
|
||||||
len = decode_double_safe(
|
len = bacnet_double_decode(
|
||||||
apdu, len_value_type, &(value->type.Double));
|
apdu, apdu_size, len_value_type, &(value->type.Double));
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_OCTET_STRING)
|
#if defined(BACAPP_OCTET_STRING)
|
||||||
case BACNET_APPLICATION_TAG_OCTET_STRING:
|
case BACNET_APPLICATION_TAG_OCTET_STRING:
|
||||||
len = decode_octet_string(
|
len = bacnet_octet_string_decode(
|
||||||
apdu, len_value_type, &value->type.Octet_String);
|
apdu, apdu_size, len_value_type, &value->type.Octet_String);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_CHARACTER_STRING)
|
#if defined(BACAPP_CHARACTER_STRING)
|
||||||
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
|
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
|
||||||
len = decode_character_string(
|
len = bacnet_character_string_decode(apdu, apdu_size,
|
||||||
apdu, len_value_type, &value->type.Character_String);
|
len_value_type, &value->type.Character_String);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_BIT_STRING)
|
#if defined(BACAPP_BIT_STRING)
|
||||||
case BACNET_APPLICATION_TAG_BIT_STRING:
|
case BACNET_APPLICATION_TAG_BIT_STRING:
|
||||||
len = decode_bitstring(
|
len = bacnet_bitstring_decode(
|
||||||
apdu, len_value_type, &value->type.Bit_String);
|
apdu, apdu_size, len_value_type, &value->type.Bit_String);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_ENUMERATED)
|
#if defined(BACAPP_ENUMERATED)
|
||||||
case BACNET_APPLICATION_TAG_ENUMERATED:
|
case BACNET_APPLICATION_TAG_ENUMERATED:
|
||||||
len = decode_enumerated(
|
len = bacnet_enumerated_decode(
|
||||||
apdu, len_value_type, &value->type.Enumerated);
|
apdu, apdu_size, len_value_type, &value->type.Enumerated);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_DATE)
|
#if defined(BACAPP_DATE)
|
||||||
case BACNET_APPLICATION_TAG_DATE:
|
case BACNET_APPLICATION_TAG_DATE:
|
||||||
len = decode_date_safe(apdu, len_value_type, &value->type.Date);
|
len = bacnet_date_decode(
|
||||||
|
apdu, apdu_size, len_value_type, &value->type.Date);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_TIME)
|
#if defined(BACAPP_TIME)
|
||||||
case BACNET_APPLICATION_TAG_TIME:
|
case BACNET_APPLICATION_TAG_TIME:
|
||||||
len = decode_bacnet_time_safe(
|
len = bacnet_time_decode(
|
||||||
apdu, len_value_type, &value->type.Time);
|
apdu, apdu_size, len_value_type, &value->type.Time);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_OBJECT_ID)
|
#if defined(BACAPP_OBJECT_ID)
|
||||||
case BACNET_APPLICATION_TAG_OBJECT_ID: {
|
case BACNET_APPLICATION_TAG_OBJECT_ID: {
|
||||||
BACNET_OBJECT_TYPE object_type = OBJECT_NONE;
|
len = bacnet_object_id_decode(apdu, apdu_size, len_value_type,
|
||||||
uint32_t instance = 0;
|
&value->type.Object_Id.type,
|
||||||
len = decode_object_id_safe(
|
&value->type.Object_Id.instance);
|
||||||
apdu, len_value_type, &object_type, &instance);
|
|
||||||
value->type.Object_Id.type = object_type;
|
|
||||||
value->type.Object_Id.instance = instance;
|
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_TIMESTAMP)
|
#if defined(BACAPP_TIMESTAMP)
|
||||||
case BACNET_APPLICATION_TAG_TIMESTAMP:
|
case BACNET_APPLICATION_TAG_TIMESTAMP:
|
||||||
len = bacnet_timestamp_decode(
|
len = bacnet_timestamp_decode(
|
||||||
apdu, len_value_type, &value->type.Time_Stamp);
|
apdu, apdu_size, &value->type.Time_Stamp);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_DATETIME)
|
#if defined(BACAPP_DATETIME)
|
||||||
case BACNET_APPLICATION_TAG_DATETIME:
|
case BACNET_APPLICATION_TAG_DATETIME:
|
||||||
len = bacnet_datetime_decode(
|
len = bacnet_datetime_decode(
|
||||||
apdu, len_value_type, &value->type.Date_Time);
|
apdu, apdu_size, &value->type.Date_Time);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_DATERANGE)
|
#if defined(BACAPP_DATERANGE)
|
||||||
case BACNET_APPLICATION_TAG_DATERANGE:
|
case BACNET_APPLICATION_TAG_DATERANGE:
|
||||||
len = bacnet_daterange_decode(
|
len = bacnet_daterange_decode(
|
||||||
apdu, len_value_type, &value->type.Date_Range);
|
apdu, apdu_size, &value->type.Date_Range);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_LIGHTING_COMMAND)
|
#if defined(BACAPP_LIGHTING_COMMAND)
|
||||||
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
|
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
|
||||||
len = lighting_command_decode(
|
len = lighting_command_decode(
|
||||||
apdu, len_value_type, &value->type.Lighting_Command);
|
apdu, apdu_size, &value->type.Lighting_Command);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_XY_COLOR)
|
#if defined(BACAPP_XY_COLOR)
|
||||||
case BACNET_APPLICATION_TAG_XY_COLOR:
|
case BACNET_APPLICATION_TAG_XY_COLOR:
|
||||||
/* BACnetxyColor */
|
/* BACnetxyColor */
|
||||||
len = xy_color_decode(
|
len = xy_color_decode(apdu, apdu_size, &value->type.XY_Color);
|
||||||
apdu, len_value_type, &value->type.XY_Color);
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_COLOR_COMMAND)
|
#if defined(BACAPP_COLOR_COMMAND)
|
||||||
case BACNET_APPLICATION_TAG_COLOR_COMMAND:
|
case BACNET_APPLICATION_TAG_COLOR_COMMAND:
|
||||||
/* BACnetColorCommand */
|
/* BACnetColorCommand */
|
||||||
len = color_command_decode(
|
len = color_command_decode(
|
||||||
apdu, len_value_type, NULL, &value->type.Color_Command);
|
apdu, apdu_size, NULL, &value->type.Color_Command);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_WEEKLY_SCHEDULE)
|
#if defined(BACAPP_WEEKLY_SCHEDULE)
|
||||||
case BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE:
|
case BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE:
|
||||||
len = bacnet_weeklyschedule_decode(
|
len = bacnet_weeklyschedule_decode(
|
||||||
apdu, (int)len_value_type, &value->type.Weekly_Schedule);
|
apdu, apdu_size, &value->type.Weekly_Schedule);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_CALENDAR_ENTRY)
|
#if defined(BACAPP_CALENDAR_ENTRY)
|
||||||
case BACNET_APPLICATION_TAG_CALENDAR_ENTRY:
|
case BACNET_APPLICATION_TAG_CALENDAR_ENTRY:
|
||||||
len = bacnet_calendar_entry_decode(
|
len = bacnet_calendar_entry_decode(
|
||||||
apdu, len_value_type, &value->type.Calendar_Entry);
|
apdu, apdu_size, &value->type.Calendar_Entry);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_SPECIAL_EVENT)
|
#if defined(BACAPP_SPECIAL_EVENT)
|
||||||
case BACNET_APPLICATION_TAG_SPECIAL_EVENT:
|
case BACNET_APPLICATION_TAG_SPECIAL_EVENT:
|
||||||
len = bacnet_special_event_decode(
|
len = bacnet_special_event_decode(
|
||||||
apdu, (int)len_value_type, &value->type.Special_Event);
|
apdu, apdu_size, &value->type.Special_Event);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_HOST_N_PORT)
|
#if defined(BACAPP_HOST_N_PORT)
|
||||||
case BACNET_APPLICATION_TAG_HOST_N_PORT:
|
case BACNET_APPLICATION_TAG_HOST_N_PORT:
|
||||||
len = host_n_port_decode(
|
len = host_n_port_decode(
|
||||||
apdu, len_value_type, NULL, &value->type.Host_Address);
|
apdu, apdu_size, NULL, &value->type.Host_Address);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_DEVICE_OBJECT_PROPERTY_REFERENCE)
|
#if defined(BACAPP_DEVICE_OBJECT_PROPERTY_REFERENCE)
|
||||||
case BACNET_APPLICATION_TAG_DEVICE_OBJECT_PROPERTY_REFERENCE:
|
case BACNET_APPLICATION_TAG_DEVICE_OBJECT_PROPERTY_REFERENCE:
|
||||||
/* BACnetDeviceObjectPropertyReference */
|
/* BACnetDeviceObjectPropertyReference */
|
||||||
len = bacnet_device_object_property_reference_decode(apdu,
|
len = bacnet_device_object_property_reference_decode(apdu,
|
||||||
len_value_type,
|
apdu_size, &value->type.Device_Object_Property_Reference);
|
||||||
&value->type.Device_Object_Property_Reference);
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_DEVICE_OBJECT_REFERENCE)
|
#if defined(BACAPP_DEVICE_OBJECT_REFERENCE)
|
||||||
case BACNET_APPLICATION_TAG_DEVICE_OBJECT_REFERENCE:
|
case BACNET_APPLICATION_TAG_DEVICE_OBJECT_REFERENCE:
|
||||||
/* BACnetDeviceObjectReference */
|
/* BACnetDeviceObjectReference */
|
||||||
len = bacapp_decode_device_obj_ref(
|
len = bacnet_device_object_reference_decode(
|
||||||
apdu, &value->type.Device_Object_Reference);
|
apdu, apdu_size, &value->type.Device_Object_Reference);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_OBJECT_PROPERTY_REFERENCE)
|
#if defined(BACAPP_OBJECT_PROPERTY_REFERENCE)
|
||||||
case BACNET_APPLICATION_TAG_OBJECT_PROPERTY_REFERENCE:
|
case BACNET_APPLICATION_TAG_OBJECT_PROPERTY_REFERENCE:
|
||||||
/* BACnetObjectPropertyReference */
|
/* BACnetObjectPropertyReference */
|
||||||
len = bacapp_decode_obj_property_ref(apdu, len_value_type,
|
len = bacapp_decode_obj_property_ref(
|
||||||
&value->type.Object_Property_Reference);
|
apdu, apdu_size, &value->type.Object_Property_Reference);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(BACAPP_DESTINATION)
|
#if defined(BACAPP_DESTINATION)
|
||||||
case BACNET_APPLICATION_TAG_DESTINATION:
|
case BACNET_APPLICATION_TAG_DESTINATION:
|
||||||
/* BACnetDestination */
|
/* BACnetDestination */
|
||||||
len = bacnet_destination_decode(
|
len = bacnet_destination_decode(
|
||||||
apdu, len_value_type, &value->type.Destination);
|
apdu, apdu_size, &value->type.Destination);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
@@ -450,9 +451,30 @@ int bacapp_decode_data(uint8_t *apdu,
|
|||||||
value->tag = MAX_BACNET_APPLICATION_TAG;
|
value->tag = MAX_BACNET_APPLICATION_TAG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Decode the data and store it into value.
|
||||||
|
* @param apdu Receive buffer
|
||||||
|
* @param tag_data_type Data type of the given tag
|
||||||
|
* @param len_value_type Count of bytes of given tag
|
||||||
|
* @param value Pointer to the application value structure,
|
||||||
|
* used to store the decoded value to.
|
||||||
|
*
|
||||||
|
* @return Number of octets consumed
|
||||||
|
* @deprecated Use bacapp_data_decode() instead.
|
||||||
|
*/
|
||||||
|
int bacapp_decode_data(uint8_t *apdu,
|
||||||
|
uint8_t tag_data_type,
|
||||||
|
uint32_t len_value_type,
|
||||||
|
BACNET_APPLICATION_DATA_VALUE *value)
|
||||||
|
{
|
||||||
|
return bacapp_data_decode(
|
||||||
|
apdu, MAX_APDU, tag_data_type, len_value_type, value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Decode the BACnet Application Data
|
* @brief Decode the BACnet Application Data
|
||||||
*
|
*
|
||||||
@@ -460,46 +482,37 @@ int bacapp_decode_data(uint8_t *apdu,
|
|||||||
* @param apdu_len_max - number of bytes in the buffer
|
* @param apdu_len_max - number of bytes in the buffer
|
||||||
* @param value - decoded value, if decoded
|
* @param value - decoded value, if decoded
|
||||||
*
|
*
|
||||||
* @return the number of apdu bytes consumed, or #BACNET_STATUS_ERROR
|
* @return the number of apdu bytes consumed, 0 on bad args, or
|
||||||
|
* BACNET_STATUS_ERROR
|
||||||
*/
|
*/
|
||||||
int bacapp_decode_application_data(
|
int bacapp_decode_application_data(
|
||||||
uint8_t *apdu, uint32_t apdu_size, BACNET_APPLICATION_DATA_VALUE *value)
|
uint8_t *apdu, uint32_t apdu_size, BACNET_APPLICATION_DATA_VALUE *value)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int tag_len = 0;
|
int apdu_len = 0;
|
||||||
int decode_len = 0;
|
BACNET_TAG tag = { 0 };
|
||||||
uint8_t tag_number = 0;
|
|
||||||
uint32_t len_value_type = 0;
|
|
||||||
|
|
||||||
if (apdu && value && apdu_size && !IS_CONTEXT_SPECIFIC(*apdu)) {
|
if (!value) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
len = bacnet_tag_decode(apdu, apdu_size, &tag);
|
||||||
|
if ((len > 0) && tag.application) {
|
||||||
value->context_specific = false;
|
value->context_specific = false;
|
||||||
tag_len = bacnet_tag_number_and_value_decode(
|
value->tag = tag.number;
|
||||||
&apdu[0], apdu_size, &tag_number, &len_value_type);
|
apdu_len += len;
|
||||||
if (tag_len > 0) {
|
len = bacapp_data_decode(&apdu[apdu_len], apdu_size - apdu_len,
|
||||||
len += tag_len;
|
tag.number, tag.len_value_type, value);
|
||||||
value->tag = tag_number;
|
if ((len >= 0) && (value->tag != MAX_BACNET_APPLICATION_TAG)) {
|
||||||
if ((unsigned)len <= apdu_size) {
|
apdu_len += len;
|
||||||
decode_len =
|
} else {
|
||||||
bacapp_decode_data_len(NULL, tag_number, len_value_type);
|
apdu_len = BACNET_STATUS_ERROR;
|
||||||
if ((unsigned)decode_len <= (apdu_size - len)) {
|
|
||||||
decode_len = bacapp_decode_data(
|
|
||||||
&apdu[len], tag_number, len_value_type, value);
|
|
||||||
if (value->tag != MAX_BACNET_APPLICATION_TAG) {
|
|
||||||
len += decode_len;
|
|
||||||
} else {
|
|
||||||
len = BACNET_STATUS_ERROR;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
len = BACNET_STATUS_ERROR;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
len = BACNET_STATUS_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
value->next = NULL;
|
value->next = NULL;
|
||||||
|
} else if (apdu && (apdu_size > 0)) {
|
||||||
|
apdu_len = BACNET_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -527,8 +540,7 @@ bool bacapp_decode_application_data_safe(uint8_t *new_apdu,
|
|||||||
static uint32_t apdu_len = 0;
|
static uint32_t apdu_len = 0;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int tag_len = 0;
|
int tag_len = 0;
|
||||||
uint8_t tag_number = 0;
|
BACNET_TAG tag = { 0 };
|
||||||
uint32_t len_value_type = 0;
|
|
||||||
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
@@ -537,27 +549,28 @@ bool bacapp_decode_application_data_safe(uint8_t *new_apdu,
|
|||||||
apdu_len_remaining = new_apdu_len;
|
apdu_len_remaining = new_apdu_len;
|
||||||
apdu_len = 0;
|
apdu_len = 0;
|
||||||
}
|
}
|
||||||
|
if (!value) {
|
||||||
if (value && apdu_len_remaining > 0 &&
|
return ret;
|
||||||
!IS_CONTEXT_SPECIFIC(apdu[apdu_len])) {
|
}
|
||||||
value->context_specific = false;
|
tag_len = bacnet_tag_decode(&apdu[apdu_len], apdu_len_remaining, &tag);
|
||||||
tag_len = bacnet_tag_number_and_value_decode(
|
if ((tag_len > 0) && tag.application) {
|
||||||
&apdu[apdu_len], apdu_len_remaining, &tag_number, &len_value_type);
|
|
||||||
/* If tag_len is zero, then the tag information is truncated */
|
/* If tag_len is zero, then the tag information is truncated */
|
||||||
if (tag_len) {
|
value->context_specific = false;
|
||||||
apdu_len += tag_len;
|
apdu_len += tag_len;
|
||||||
apdu_len_remaining -= tag_len;
|
apdu_len_remaining -= tag_len;
|
||||||
/* The tag is boolean then len_value_type is interpreted as value,
|
/* The tag is boolean then len_value_type is interpreted as value,
|
||||||
not length, so don't bother checking with apdu_len_remaining */
|
not length, so don't bother checking with apdu_len_remaining */
|
||||||
if (tag_number == BACNET_APPLICATION_TAG_BOOLEAN ||
|
if (tag.number == BACNET_APPLICATION_TAG_BOOLEAN ||
|
||||||
len_value_type <= apdu_len_remaining) {
|
(tag.len_value_type <= apdu_len_remaining)) {
|
||||||
value->tag = tag_number;
|
value->tag = tag.number;
|
||||||
len = bacapp_decode_data(
|
len = bacapp_data_decode(&apdu[apdu_len], apdu_len_remaining,
|
||||||
&apdu[apdu_len], tag_number, len_value_type, value);
|
tag.number, tag.len_value_type, value);
|
||||||
|
if (value->tag != MAX_BACNET_APPLICATION_TAG) {
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
apdu_len_remaining -= len;
|
apdu_len_remaining -= len;
|
||||||
|
|
||||||
ret = true;
|
ret = true;
|
||||||
|
} else {
|
||||||
|
ret = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value->next = NULL;
|
value->next = NULL;
|
||||||
@@ -610,29 +623,23 @@ int bacapp_decode_data_len(
|
|||||||
/**
|
/**
|
||||||
* @brief Determine the BACnet Application Data number of APDU bytes consumed
|
* @brief Determine the BACnet Application Data number of APDU bytes consumed
|
||||||
* @param apdu - buffer of data to be decoded
|
* @param apdu - buffer of data to be decoded
|
||||||
* @param apdu_len_max - number of bytes in the buffer
|
* @param apdu_size - number of bytes in the buffer
|
||||||
* @return number of bytes decoded, or zero if errors occur
|
* @return number of bytes decoded, or zero if errors occur
|
||||||
*/
|
*/
|
||||||
int bacapp_decode_application_data_len(uint8_t *apdu, unsigned apdu_len_max)
|
int bacapp_decode_application_data_len(uint8_t *apdu, unsigned apdu_size)
|
||||||
{
|
{
|
||||||
|
int apdu_len = 0;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int tag_len = 0;
|
BACNET_TAG tag = { 0 };
|
||||||
int decode_len = 0;
|
|
||||||
uint8_t tag_number = 0;
|
|
||||||
uint32_t len_value_type = 0;
|
|
||||||
|
|
||||||
if (apdu && !IS_CONTEXT_SPECIFIC(*apdu)) {
|
len = bacnet_tag_decode(apdu, apdu_size, &tag);
|
||||||
tag_len = bacnet_tag_number_and_value_decode(
|
if ((len > 0) && (tag.application)) {
|
||||||
&apdu[0], apdu_len_max, &tag_number, &len_value_type);
|
apdu_len += len;
|
||||||
if (tag_len > 0) {
|
len = bacapp_decode_data_len(NULL, tag.number, tag.len_value_type);
|
||||||
len += tag_len;
|
apdu_len += len;
|
||||||
decode_len =
|
|
||||||
bacapp_decode_data_len(NULL, tag_number, len_value_type);
|
|
||||||
len += decode_len;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bacapp_encode_context_data_value(uint8_t *apdu,
|
int bacapp_encode_context_data_value(uint8_t *apdu,
|
||||||
@@ -834,7 +841,7 @@ BACNET_APPLICATION_TAG bacapp_context_tag_type(
|
|||||||
date [0] Date,
|
date [0] Date,
|
||||||
date-range [1] BACnetDateRange,
|
date-range [1] BACnetDateRange,
|
||||||
weekNDay [2] BACnetWeekNDay
|
weekNDay [2] BACnetWeekNDay
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
switch (tag_number) {
|
switch (tag_number) {
|
||||||
case 0: /* single calendar date */
|
case 0: /* single calendar date */
|
||||||
@@ -857,7 +864,7 @@ BACNET_APPLICATION_TAG bacapp_context_tag_type(
|
|||||||
percent [0] Unsigned,
|
percent [0] Unsigned,
|
||||||
level [1] Unsigned,
|
level [1] Unsigned,
|
||||||
amount [2] REAL
|
amount [2] REAL
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
switch (tag_number) {
|
switch (tag_number) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -909,9 +916,9 @@ BACNET_APPLICATION_TAG bacapp_context_tag_type(
|
|||||||
case PROP_LIST_OF_GROUP_MEMBERS:
|
case PROP_LIST_OF_GROUP_MEMBERS:
|
||||||
/* ReadAccessSpecification ::= SEQUENCE {
|
/* ReadAccessSpecification ::= SEQUENCE {
|
||||||
object-identifier [0] BACnetObjectIdentifier,
|
object-identifier [0] BACnetObjectIdentifier,
|
||||||
list-of-property-references [1] SEQUENCE OF
|
list-of-property-references [1] SEQUENCE OF
|
||||||
BACnetPropertyReference
|
BACnetPropertyReference
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
switch (tag_number) {
|
switch (tag_number) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -986,17 +993,17 @@ BACNET_APPLICATION_TAG bacapp_context_tag_type(
|
|||||||
monitored-property-reference [1] BACnetObjectPropertyReference,
|
monitored-property-reference [1] BACnetObjectPropertyReference,
|
||||||
issue-confirmed-notifications [2] BOOLEAN,
|
issue-confirmed-notifications [2] BOOLEAN,
|
||||||
time-remaining [3] Unsigned,
|
time-remaining [3] Unsigned,
|
||||||
cov-increment [4] REAL OPTIONAL
|
cov-increment [4] REAL OPTIONAL
|
||||||
-- used only with monitored
|
-- used only with monitored
|
||||||
-- properties with a numeric datatype
|
-- properties with a numeric datatype
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
switch (tag_number) {
|
switch (tag_number) {
|
||||||
case 0:
|
case 0:
|
||||||
/* BACnetRecipientProcess ::= SEQUENCE {
|
/* BACnetRecipientProcess ::= SEQUENCE {
|
||||||
recipient [0] BACnetRecipient,
|
recipient [0] BACnetRecipient,
|
||||||
process-identifier [1] Unsigned32
|
process-identifier [1] Unsigned32
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
case 1: /* BACnetObjectPropertyReference */
|
case 1: /* BACnetObjectPropertyReference */
|
||||||
@@ -1147,43 +1154,54 @@ int bacapp_encode_context_data(uint8_t *apdu,
|
|||||||
return apdu_len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Decode context encoded data
|
||||||
|
*
|
||||||
|
* @param apdu - buffer of data to be decoded
|
||||||
|
* @param apdu_size - number of bytes in the buffer
|
||||||
|
* @param value - stores the decoded property value
|
||||||
|
* @param property - context property identifier
|
||||||
|
* @return number of bytes decoded, or #BACNET_STATUS_ERROR
|
||||||
|
*/
|
||||||
int bacapp_decode_context_data(uint8_t *apdu,
|
int bacapp_decode_context_data(uint8_t *apdu,
|
||||||
unsigned max_apdu_len,
|
unsigned apdu_size,
|
||||||
BACNET_APPLICATION_DATA_VALUE *value,
|
BACNET_APPLICATION_DATA_VALUE *value,
|
||||||
BACNET_PROPERTY_ID property)
|
BACNET_PROPERTY_ID property)
|
||||||
{
|
{
|
||||||
int apdu_len = 0, len = 0;
|
int apdu_len = 0, len = 0;
|
||||||
int tag_len = 0;
|
BACNET_TAG tag = { 0 };
|
||||||
uint8_t tag_number = 0;
|
|
||||||
uint32_t len_value_type = 0;
|
|
||||||
|
|
||||||
if (apdu && value && IS_CONTEXT_SPECIFIC(*apdu)) {
|
if (!value) {
|
||||||
value->context_specific = true;
|
return apdu_len;
|
||||||
value->next = NULL;
|
}
|
||||||
tag_len =
|
len = bacnet_tag_decode(&apdu[0], apdu_size, &tag);
|
||||||
decode_tag_number_and_value(&apdu[0], &tag_number, &len_value_type);
|
if (len > 0) {
|
||||||
apdu_len = tag_len;
|
if (tag.closing) {
|
||||||
/* Empty construct : (closing tag) => returns NULL value */
|
/* Empty construct : (closing tag) */
|
||||||
if (tag_len && ((unsigned)tag_len <= max_apdu_len) &&
|
/* Don't advance over that closing tag. */
|
||||||
!decode_is_closing_tag_number(&apdu[0], tag_number)) {
|
apdu_len = 0;
|
||||||
value->context_tag = tag_number;
|
} else if (tag.context) {
|
||||||
value->tag = bacapp_context_tag_type(property, tag_number);
|
apdu_len += len;
|
||||||
|
value->context_specific = true;
|
||||||
|
value->next = NULL;
|
||||||
|
value->context_tag = tag.number;
|
||||||
|
value->tag = bacapp_context_tag_type(property, tag.number);
|
||||||
if (value->tag != MAX_BACNET_APPLICATION_TAG) {
|
if (value->tag != MAX_BACNET_APPLICATION_TAG) {
|
||||||
len = bacapp_decode_data(
|
len = bacapp_data_decode(&apdu[apdu_len], apdu_size - apdu_len,
|
||||||
&apdu[apdu_len], value->tag, len_value_type, value);
|
value->tag, tag.len_value_type, value);
|
||||||
apdu_len += len;
|
if ((len >= 0) && (value->tag != MAX_BACNET_APPLICATION_TAG)) {
|
||||||
} else if (len_value_type) {
|
apdu_len += len;
|
||||||
|
} else {
|
||||||
|
apdu_len = BACNET_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
} else if (tag.len_value_type) {
|
||||||
/* Unknown value : non null size (elementary type) */
|
/* Unknown value : non null size (elementary type) */
|
||||||
apdu_len += len_value_type;
|
apdu_len += tag.len_value_type;
|
||||||
/* SHOULD NOT HAPPEN, EXCEPTED WHEN READING UNKNOWN CONTEXTUAL
|
/* SHOULD NOT HAPPEN, EXCEPTED WHEN READING UNKNOWN CONTEXTUAL
|
||||||
* PROPERTY */
|
* PROPERTY */
|
||||||
} else {
|
} else {
|
||||||
apdu_len = BACNET_STATUS_ERROR;
|
apdu_len = BACNET_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
} else if (tag_len == 1) {
|
|
||||||
/* and is a Closing tag */
|
|
||||||
/* Don't advance over that closing tag. */
|
|
||||||
apdu_len = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1195,62 +1213,68 @@ int bacapp_decode_context_data(uint8_t *apdu,
|
|||||||
* @brief Context or Application tagged property value decoding
|
* @brief Context or Application tagged property value decoding
|
||||||
*
|
*
|
||||||
* @param apdu - buffer of data to be decoded
|
* @param apdu - buffer of data to be decoded
|
||||||
* @param max_apdu_len - number of bytes in the buffer
|
* @param apdu_size - number of bytes in the buffer
|
||||||
* @param value - stores the decoded property value
|
* @param value - stores the decoded property value
|
||||||
* @param property - context property identifier
|
* @param property - context property identifier
|
||||||
* @return number of bytes decoded, or ERROR if errors occur
|
* @return number of bytes decoded, or #BACNET_STATUS_ERROR
|
||||||
*/
|
*/
|
||||||
int bacapp_decode_generic_property(uint8_t *apdu,
|
int bacapp_decode_generic_property(uint8_t *apdu,
|
||||||
int max_apdu_len,
|
int apdu_size,
|
||||||
BACNET_APPLICATION_DATA_VALUE *value,
|
BACNET_APPLICATION_DATA_VALUE *value,
|
||||||
BACNET_PROPERTY_ID prop)
|
BACNET_PROPERTY_ID prop)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int apdu_len = BACNET_STATUS_ERROR;
|
||||||
if (IS_CONTEXT_SPECIFIC(*apdu)) {
|
|
||||||
len = bacapp_decode_context_data(apdu, max_apdu_len, value, prop);
|
if (apdu && (apdu_size > 0)) {
|
||||||
} else {
|
if (IS_CONTEXT_SPECIFIC(*apdu)) {
|
||||||
len = bacapp_decode_application_data(apdu, max_apdu_len, value);
|
apdu_len = bacapp_decode_context_data(apdu, apdu_size, value, prop);
|
||||||
|
} else {
|
||||||
|
apdu_len = bacapp_decode_application_data(apdu, apdu_size, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return len;
|
|
||||||
|
return apdu_len;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(BACAPP_COMPLEX_TYPES)
|
#if defined(BACAPP_COMPLEX_TYPES)
|
||||||
/* decode one value of a priority array */
|
/**
|
||||||
|
* @brief Decode BACnetPriorityValue complex data
|
||||||
|
*
|
||||||
|
* @param apdu - buffer of data to be decoded
|
||||||
|
* @param apdu_size - number of bytes in the buffer
|
||||||
|
* @param value - stores the decoded property value
|
||||||
|
* @param property - context property identifier
|
||||||
|
* @return number of bytes decoded, or #BACNET_STATUS_ERROR
|
||||||
|
*/
|
||||||
static int decode_priority_value(uint8_t *apdu,
|
static int decode_priority_value(uint8_t *apdu,
|
||||||
unsigned max_apdu_len,
|
unsigned apdu_size,
|
||||||
BACNET_APPLICATION_DATA_VALUE *value,
|
BACNET_APPLICATION_DATA_VALUE *value,
|
||||||
BACNET_PROPERTY_ID prop)
|
BACNET_PROPERTY_ID property)
|
||||||
{
|
{
|
||||||
int val_len = 0;
|
int apdu_len = 0;
|
||||||
uint32_t len_value_type = 0;
|
|
||||||
int len = 0;
|
int len = 0;
|
||||||
bool is_opening_tag;
|
|
||||||
uint8_t tag_number;
|
|
||||||
|
|
||||||
if (decode_is_context_tag(apdu, 0) && !decode_is_closing_tag(apdu)) {
|
if (bacnet_is_opening_tag_number(apdu, apdu_size, 0, &len)) {
|
||||||
/* Contextual Abstract-syntax & type */
|
/* Contextual Abstract-syntax & type */
|
||||||
val_len =
|
apdu_len += len;
|
||||||
decode_tag_number_and_value(apdu, &tag_number, &len_value_type);
|
len = bacapp_decode_generic_property(
|
||||||
is_opening_tag = decode_is_opening_tag(apdu);
|
&apdu[apdu_len], apdu_size - apdu_len, value, property);
|
||||||
len += val_len;
|
if (len < 0) {
|
||||||
val_len = bacapp_decode_generic_property(
|
|
||||||
&apdu[len], max_apdu_len - len, value, prop);
|
|
||||||
if (val_len < 0) {
|
|
||||||
return BACNET_STATUS_ERROR;
|
return BACNET_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
len += val_len;
|
apdu_len += len;
|
||||||
if (is_opening_tag) {
|
if (!bacnet_is_closing_tag_number(
|
||||||
if (!decode_is_closing_tag_number(apdu, 0)) {
|
&apdu[apdu_len], apdu_size - apdu_len, 0, &len)) {
|
||||||
return BACNET_STATUS_ERROR;
|
return BACNET_STATUS_ERROR;
|
||||||
}
|
|
||||||
len++;
|
|
||||||
}
|
}
|
||||||
|
apdu_len += len;
|
||||||
} else {
|
} else {
|
||||||
len = bacapp_decode_generic_property(apdu, max_apdu_len, value, prop);
|
apdu_len =
|
||||||
|
bacapp_decode_generic_property(apdu, apdu_size, value, property);
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1492,7 +1516,8 @@ int bacapp_decode_known_property(uint8_t *apdu,
|
|||||||
case PROP_ACCESS_EVENT_TIME:
|
case PROP_ACCESS_EVENT_TIME:
|
||||||
#ifdef BACAPP_TIMESTAMP
|
#ifdef BACAPP_TIMESTAMP
|
||||||
/* Properties using BACnetTimeStamp */
|
/* Properties using BACnetTimeStamp */
|
||||||
len = bacapp_decode_timestamp(apdu, &value->type.Time_Stamp);
|
len = bacnet_timestamp_decode(
|
||||||
|
apdu, max_apdu_len, &value->type.Time_Stamp);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1619,23 +1644,19 @@ int bacapp_decode_context_data_len(
|
|||||||
uint8_t *apdu, unsigned apdu_len_max, BACNET_PROPERTY_ID property)
|
uint8_t *apdu, unsigned apdu_len_max, BACNET_PROPERTY_ID property)
|
||||||
{
|
{
|
||||||
int apdu_len = 0, len = 0;
|
int apdu_len = 0, len = 0;
|
||||||
int tag_len = 0;
|
BACNET_TAG tag = { 0 };
|
||||||
uint8_t tag_number = 0;
|
uint8_t application_tag = 0;
|
||||||
uint32_t len_value_type = 0;
|
|
||||||
uint8_t tag = 0;
|
|
||||||
|
|
||||||
if (apdu && IS_CONTEXT_SPECIFIC(*apdu)) {
|
len = bacnet_tag_decode(&apdu[0], apdu_len_max, &tag);
|
||||||
tag_len = bacnet_tag_number_and_value_decode(
|
if ((len > 0) && tag.context) {
|
||||||
&apdu[0], apdu_len_max, &tag_number, &len_value_type);
|
apdu_len = len;
|
||||||
if (tag_len) {
|
application_tag = bacapp_context_tag_type(property, tag.number);
|
||||||
apdu_len = tag_len;
|
if (application_tag != MAX_BACNET_APPLICATION_TAG) {
|
||||||
tag = bacapp_context_tag_type(property, tag_number);
|
len = bacapp_decode_data_len(
|
||||||
if (tag != MAX_BACNET_APPLICATION_TAG) {
|
NULL, application_tag, tag.len_value_type);
|
||||||
len = bacapp_decode_data_len(NULL, tag, len_value_type);
|
apdu_len += len;
|
||||||
apdu_len += len;
|
} else {
|
||||||
} else {
|
apdu_len += tag.len_value_type;
|
||||||
apdu_len += len_value_type;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1758,69 +1779,68 @@ bool bacapp_copy(BACNET_APPLICATION_DATA_VALUE *dest_value,
|
|||||||
* Include a value property identifier for context specific data
|
* Include a value property identifier for context specific data
|
||||||
* such as the value received in a WriteProperty request.
|
* such as the value received in a WriteProperty request.
|
||||||
*
|
*
|
||||||
* @param Pointer to the APDU buffer
|
* @param apdu Pointer to the APDU buffer
|
||||||
* @param apdu_len_max Bytes valid in the buffer
|
* @param apdu_size Bytes valid in the buffer
|
||||||
* @param property ID of the property to get the length for.
|
* @param property ID of the property to get the length for.
|
||||||
*
|
*
|
||||||
* @return Length in bytes 0..N, or BACNET_STATUS_ERROR.
|
* @return Length in bytes 0..N, or BACNET_STATUS_ERROR.
|
||||||
*/
|
*/
|
||||||
int bacapp_data_len(
|
int bacapp_data_len(
|
||||||
uint8_t *apdu, unsigned apdu_len_max, BACNET_PROPERTY_ID property)
|
uint8_t *apdu, unsigned apdu_size, BACNET_PROPERTY_ID property)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int total_len = 0;
|
int total_len = 0;
|
||||||
int apdu_len = 0;
|
int apdu_len = 0;
|
||||||
uint8_t tag_number = 0;
|
BACNET_TAG tag = { 0 };
|
||||||
uint8_t opening_tag_number = 0;
|
uint8_t opening_tag_number = 0;
|
||||||
uint8_t opening_tag_number_counter = 0;
|
uint8_t opening_tag_number_counter = 0;
|
||||||
uint32_t value = 0;
|
|
||||||
bool total_len_enable = false;
|
bool total_len_enable = false;
|
||||||
|
|
||||||
if (!apdu) {
|
if (!apdu) {
|
||||||
return BACNET_STATUS_ERROR;
|
return BACNET_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
if (apdu_len_max <= apdu_len) {
|
if (apdu_size <= apdu_len) {
|
||||||
/* error: exceeding our buffer limit */
|
/* error: exceeding our buffer limit */
|
||||||
return BACNET_STATUS_ERROR;
|
return BACNET_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
if (!bacnet_is_opening_tag(apdu, apdu_len_max)) {
|
if (!bacnet_is_opening_tag(apdu, apdu_size)) {
|
||||||
/* error: opening tag is missing */
|
/* error: opening tag is missing */
|
||||||
return BACNET_STATUS_ERROR;
|
return BACNET_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
if (bacnet_is_opening_tag(apdu, apdu_len_max)) {
|
len = bacnet_tag_decode(apdu, apdu_size - apdu_len, &tag);
|
||||||
len = bacnet_tag_number_and_value_decode(
|
if (len == 0) {
|
||||||
apdu, apdu_len_max - apdu_len, &tag_number, &value);
|
return BACNET_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
if (tag.opening) {
|
||||||
if (opening_tag_number_counter == 0) {
|
if (opening_tag_number_counter == 0) {
|
||||||
opening_tag_number = tag_number;
|
opening_tag_number = tag.number;
|
||||||
opening_tag_number_counter = 1;
|
opening_tag_number_counter = 1;
|
||||||
total_len_enable = false;
|
total_len_enable = false;
|
||||||
} else if (tag_number == opening_tag_number) {
|
} else if (tag.number == opening_tag_number) {
|
||||||
total_len_enable = true;
|
total_len_enable = true;
|
||||||
opening_tag_number_counter++;
|
opening_tag_number_counter++;
|
||||||
} else {
|
} else {
|
||||||
total_len_enable = true;
|
total_len_enable = true;
|
||||||
}
|
}
|
||||||
} else if (bacnet_is_closing_tag(apdu, apdu_len_max)) {
|
} else if (tag.closing) {
|
||||||
len = bacnet_tag_number_and_value_decode(
|
if (tag.number == opening_tag_number) {
|
||||||
apdu, apdu_len_max - apdu_len, &tag_number, &value);
|
|
||||||
if (tag_number == opening_tag_number) {
|
|
||||||
if (opening_tag_number_counter > 0) {
|
if (opening_tag_number_counter > 0) {
|
||||||
opening_tag_number_counter--;
|
opening_tag_number_counter--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
total_len_enable = true;
|
total_len_enable = true;
|
||||||
} else if (bacnet_is_context_specific(apdu, apdu_len_max)) {
|
} else if (tag.context) {
|
||||||
#if defined(BACAPP_COMPLEX_TYPES)
|
#if defined(BACAPP_COMPLEX_TYPES)
|
||||||
/* context-specific tagged data */
|
/* context-specific tagged data */
|
||||||
len = bacapp_decode_context_data_len(
|
len = bacapp_decode_context_data_len(
|
||||||
apdu, apdu_len_max - apdu_len, property);
|
apdu, apdu_size - apdu_len, property);
|
||||||
total_len_enable = true;
|
total_len_enable = true;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* application tagged data */
|
/* application tagged data */
|
||||||
len = bacapp_decode_application_data_len(
|
len =
|
||||||
apdu, apdu_len_max - apdu_len);
|
bacapp_decode_application_data_len(apdu, apdu_size - apdu_len);
|
||||||
total_len_enable = true;
|
total_len_enable = true;
|
||||||
}
|
}
|
||||||
if (opening_tag_number_counter > 0) {
|
if (opening_tag_number_counter > 0) {
|
||||||
@@ -1833,7 +1853,7 @@ int bacapp_data_len(
|
|||||||
return BACNET_STATUS_ERROR;
|
return BACNET_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
if (apdu_len_max <= apdu_len) {
|
if (apdu_size <= apdu_len) {
|
||||||
/* error: exceeding our buffer limit */
|
/* error: exceeding our buffer limit */
|
||||||
return BACNET_STATUS_ERROR;
|
return BACNET_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-1
@@ -206,10 +206,18 @@ extern "C" {
|
|||||||
uint8_t * apdu,
|
uint8_t * apdu,
|
||||||
BACNET_APPLICATION_DATA_VALUE * value);
|
BACNET_APPLICATION_DATA_VALUE * value);
|
||||||
BACNET_STACK_EXPORT
|
BACNET_STACK_EXPORT
|
||||||
|
int bacapp_data_decode(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint32_t apdu_size,
|
||||||
|
uint8_t tag_data_type,
|
||||||
|
uint32_t len_value_type,
|
||||||
|
BACNET_APPLICATION_DATA_VALUE * value);
|
||||||
|
BACNET_STACK_DEPRECATED("Use bacapp_data_decode() instead")
|
||||||
|
BACNET_STACK_EXPORT
|
||||||
int bacapp_decode_data(
|
int bacapp_decode_data(
|
||||||
uint8_t * apdu,
|
uint8_t * apdu,
|
||||||
uint8_t tag_data_type,
|
uint8_t tag_data_type,
|
||||||
uint32_t apdu_size,
|
uint32_t len_value_type,
|
||||||
BACNET_APPLICATION_DATA_VALUE * value);
|
BACNET_APPLICATION_DATA_VALUE * value);
|
||||||
|
|
||||||
BACNET_STACK_EXPORT
|
BACNET_STACK_EXPORT
|
||||||
|
|||||||
@@ -379,6 +379,34 @@ void Command_Property_Lists(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Determine if the object property is a member of this object instance
|
||||||
|
* @param object_instance - object-instance number of the object
|
||||||
|
* @param object_property - object-property to be checked
|
||||||
|
* @return true if the property is a member of this object instance
|
||||||
|
*/
|
||||||
|
static bool Property_List_Member(
|
||||||
|
uint32_t object_instance, int object_property)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
const int *pRequired = NULL;
|
||||||
|
const int *pOptional = NULL;
|
||||||
|
const int *pProprietary = NULL;
|
||||||
|
|
||||||
|
(void)object_instance;
|
||||||
|
Command_Property_Lists(
|
||||||
|
&pRequired, &pOptional, &pProprietary);
|
||||||
|
found = property_list_member(pRequired, object_property);
|
||||||
|
if (!found) {
|
||||||
|
found = property_list_member(pOptional, object_property);
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
found = property_list_member(pProprietary, object_property);
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the Command object data
|
* Initializes the Command object data
|
||||||
*/
|
*/
|
||||||
@@ -797,21 +825,16 @@ bool Command_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
|||||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||||
status = false;
|
status = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROP_OBJECT_IDENTIFIER:
|
|
||||||
case PROP_OBJECT_NAME:
|
|
||||||
case PROP_OBJECT_TYPE:
|
|
||||||
case PROP_IN_PROCESS:
|
|
||||||
case PROP_ALL_WRITES_SUCCESSFUL:
|
|
||||||
case PROP_ACTION:
|
|
||||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
|
||||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
if (Property_List_Member(
|
||||||
wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
wp_data->object_instance, wp_data->object_property)) {
|
||||||
|
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||||
|
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||||
|
} else {
|
||||||
|
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||||
|
wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -223,6 +223,33 @@ void Network_Port_Property_Lists(
|
|||||||
Object_List[0].Instance_Number, pRequired, pOptional, pProprietary);
|
Object_List[0].Instance_Number, pRequired, pOptional, pProprietary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Determine if the object property is a member of this object instance
|
||||||
|
* @param object_instance - object-instance number of the object
|
||||||
|
* @param object_property - object-property to be checked
|
||||||
|
* @return true if the property is a member of this object instance
|
||||||
|
*/
|
||||||
|
static bool Property_List_Member(
|
||||||
|
uint32_t object_instance, int object_property)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
const int *pRequired = NULL;
|
||||||
|
const int *pOptional = NULL;
|
||||||
|
const int *pProprietary = NULL;
|
||||||
|
|
||||||
|
Network_Port_Property_List(object_instance,
|
||||||
|
&pRequired, &pOptional, &pProprietary);
|
||||||
|
found = property_list_member(pRequired, object_property);
|
||||||
|
if (!found) {
|
||||||
|
found = property_list_member(pOptional, object_property);
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
found = property_list_member(pProprietary, object_property);
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For a given object instance-number, loads the object-name into
|
* For a given object instance-number, loads the object-name into
|
||||||
* a characterstring. Note that the object name must be unique
|
* a characterstring. Note that the object name must be unique
|
||||||
@@ -2523,26 +2550,15 @@ bool Network_Port_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PROP_OBJECT_IDENTIFIER:
|
|
||||||
case PROP_OBJECT_NAME:
|
|
||||||
case PROP_OBJECT_TYPE:
|
|
||||||
case PROP_STATUS_FLAGS:
|
|
||||||
case PROP_RELIABILITY:
|
|
||||||
case PROP_OUT_OF_SERVICE:
|
|
||||||
case PROP_NETWORK_TYPE:
|
|
||||||
case PROP_PROTOCOL_LEVEL:
|
|
||||||
case PROP_NETWORK_NUMBER:
|
|
||||||
case PROP_NETWORK_NUMBER_QUALITY:
|
|
||||||
case PROP_MAC_ADDRESS:
|
|
||||||
case PROP_LINK_SPEED:
|
|
||||||
case PROP_CHANGES_PENDING:
|
|
||||||
case PROP_APDU_LENGTH:
|
|
||||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
|
||||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
if (Property_List_Member(
|
||||||
wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
wp_data->object_instance, wp_data->object_property)) {
|
||||||
|
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||||
|
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||||
|
} else {
|
||||||
|
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||||
|
wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -829,16 +829,32 @@ static bool verifyBACnetApplicationDataValue(
|
|||||||
uint8_t apdu[480] = { 0 };
|
uint8_t apdu[480] = { 0 };
|
||||||
int apdu_len = 0;
|
int apdu_len = 0;
|
||||||
int null_len = 0;
|
int null_len = 0;
|
||||||
|
int test_len = 0;
|
||||||
|
bool status = false;
|
||||||
BACNET_APPLICATION_DATA_VALUE test_value = { 0 };
|
BACNET_APPLICATION_DATA_VALUE test_value = { 0 };
|
||||||
|
|
||||||
apdu_len = bacapp_encode_application_data(&apdu[0], value);
|
apdu_len = bacapp_encode_application_data(&apdu[0], value);
|
||||||
zassert_true(apdu_len > 0, NULL);
|
zassert_true(apdu_len > 0, NULL);
|
||||||
null_len = bacapp_encode_application_data(NULL, value);
|
null_len = bacapp_encode_application_data(NULL, value);
|
||||||
zassert_equal(apdu_len, null_len, NULL);
|
zassert_equal(apdu_len, null_len, NULL);
|
||||||
apdu_len = bacapp_decode_application_data(&apdu[0], apdu_len, &test_value);
|
test_len = bacapp_decode_application_data(&apdu[0], apdu_len, &test_value);
|
||||||
zassert_true(apdu_len != BACNET_STATUS_ERROR, NULL);
|
zassert_true(test_len != BACNET_STATUS_ERROR, NULL);
|
||||||
|
status = bacapp_same_value(value, &test_value);
|
||||||
|
while (apdu_len) {
|
||||||
|
apdu_len--;
|
||||||
|
test_len =
|
||||||
|
bacapp_decode_application_data(&apdu[0], apdu_len, &test_value);
|
||||||
|
if (apdu_len == 0) {
|
||||||
|
zassert_equal(test_len, 0, "tag=%u apdu_len=%d test_len=%d\n",
|
||||||
|
value->tag, apdu_len, test_len);
|
||||||
|
} else {
|
||||||
|
zassert_equal(test_len, BACNET_STATUS_ERROR,
|
||||||
|
"tag=%u apdu_len=%d test_len=%d null_len=%d\n", value->tag,
|
||||||
|
apdu_len, test_len, null_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return bacapp_same_value(value, &test_value);
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ add_compile_definitions(
|
|||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${SRC_DIR}
|
${SRC_DIR}
|
||||||
|
${TST_DIR}/bacnet/basic/object
|
||||||
${TST_DIR}/ztest/include
|
${TST_DIR}/ztest/include
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -49,6 +50,7 @@ add_executable(${PROJECT_NAME}
|
|||||||
${SRC_DIR}/bacnet/indtext.c
|
${SRC_DIR}/bacnet/indtext.c
|
||||||
${SRC_DIR}/bacnet/hostnport.c
|
${SRC_DIR}/bacnet/hostnport.c
|
||||||
${SRC_DIR}/bacnet/lighting.c
|
${SRC_DIR}/bacnet/lighting.c
|
||||||
|
${SRC_DIR}/bacnet/proplist.c
|
||||||
${SRC_DIR}/bacnet/timestamp.c
|
${SRC_DIR}/bacnet/timestamp.c
|
||||||
${SRC_DIR}/bacnet/wp.c
|
${SRC_DIR}/bacnet/wp.c
|
||||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||||
@@ -58,6 +60,7 @@ add_executable(${PROJECT_NAME}
|
|||||||
${SRC_DIR}/bacnet/special_event.c
|
${SRC_DIR}/bacnet/special_event.c
|
||||||
# Test and test library files
|
# Test and test library files
|
||||||
./src/main.c
|
./src/main.c
|
||||||
|
${TST_DIR}/bacnet/basic/object/property_test.c
|
||||||
${ZTST_DIR}/ztest_mock.c
|
${ZTST_DIR}/ztest_mock.c
|
||||||
${ZTST_DIR}/ztest.c
|
${ZTST_DIR}/ztest.c
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <zephyr/ztest.h>
|
#include <zephyr/ztest.h>
|
||||||
#include <bacnet/basic/object/command.h>
|
#include <bacnet/basic/object/command.h>
|
||||||
#include <bacnet/bactext.h>
|
#include <property_test.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup bacnet_tests
|
* @addtogroup bacnet_tests
|
||||||
@@ -24,83 +24,34 @@ ZTEST(tests_object_command, test_object_command)
|
|||||||
static void test_object_command(void)
|
static void test_object_command(void)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
bool status = false;
|
||||||
int len = 0;
|
|
||||||
int test_len = 0;
|
|
||||||
BACNET_READ_PROPERTY_DATA rpdata;
|
|
||||||
/* for decode value data */
|
|
||||||
BACNET_APPLICATION_DATA_VALUE value;
|
|
||||||
const int *pRequired = NULL;
|
|
||||||
const int *pOptional = NULL;
|
|
||||||
const int *pProprietary = NULL;
|
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
uint32_t object_instance = 0;
|
uint32_t object_instance = 0;
|
||||||
|
const int skip_fail_property_list[] = { PROP_ACTION, -1 };
|
||||||
|
|
||||||
Command_Init();
|
Command_Init();
|
||||||
count = Command_Count();
|
count = Command_Count();
|
||||||
zassert_true(count > 0, NULL);
|
zassert_true(count > 0, NULL);
|
||||||
object_instance = Command_Index_To_Instance(0);
|
object_instance = Command_Index_To_Instance(0);
|
||||||
rpdata.application_data = &apdu[0];
|
bacnet_object_properties_read_write_test(
|
||||||
rpdata.application_data_len = sizeof(apdu);
|
OBJECT_COMMAND,
|
||||||
rpdata.object_type = OBJECT_COMMAND;
|
object_instance,
|
||||||
rpdata.object_instance = object_instance;
|
Command_Property_Lists,
|
||||||
Command_Property_Lists(&pRequired, &pOptional, &pProprietary);
|
Command_Read_Property,
|
||||||
while ((*pRequired) != -1) {
|
Command_Write_Property,
|
||||||
rpdata.object_property = *pRequired;
|
skip_fail_property_list);
|
||||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
|
||||||
len = Command_Read_Property(&rpdata);
|
|
||||||
zassert_not_equal(len, BACNET_STATUS_ERROR, NULL);
|
|
||||||
if (len > 0) {
|
|
||||||
test_len = bacapp_decode_application_data(rpdata.application_data,
|
|
||||||
(uint8_t)rpdata.application_data_len, &value);
|
|
||||||
if (len != test_len) {
|
|
||||||
printf("property '%s': failed to decode!\n",
|
|
||||||
bactext_property_name(rpdata.object_property));
|
|
||||||
}
|
|
||||||
if (rpdata.object_property == PROP_PRIORITY_ARRAY) {
|
|
||||||
/* FIXME: known fail to decode */
|
|
||||||
len = test_len;
|
|
||||||
}
|
|
||||||
zassert_true(test_len >= 0, NULL);
|
|
||||||
}
|
|
||||||
pRequired++;
|
|
||||||
}
|
|
||||||
while ((*pOptional) != -1) {
|
|
||||||
rpdata.object_property = *pOptional;
|
|
||||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
|
||||||
len = Command_Read_Property(&rpdata);
|
|
||||||
zassert_not_equal(len, BACNET_STATUS_ERROR, NULL);
|
|
||||||
if (len > 0) {
|
|
||||||
test_len = bacapp_decode_application_data(rpdata.application_data,
|
|
||||||
(uint8_t)rpdata.application_data_len, &value);
|
|
||||||
if (len != test_len) {
|
|
||||||
printf("property '%s': failed to decode!\n",
|
|
||||||
bactext_property_name(rpdata.object_property));
|
|
||||||
}
|
|
||||||
if (rpdata.object_property == PROP_PRIORITY_ARRAY) {
|
|
||||||
/* FIXME: known fail to decode */
|
|
||||||
len = test_len;
|
|
||||||
}
|
|
||||||
zassert_true(test_len >= 0, NULL);
|
|
||||||
}
|
|
||||||
pOptional++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#if defined(CONFIG_ZTEST_NEW_API)
|
#if defined(CONFIG_ZTEST_NEW_API)
|
||||||
ZTEST_SUITE(tests_object_command, NULL, NULL, NULL, NULL, NULL);
|
ZTEST_SUITE(tests_object_command, NULL, NULL, NULL, NULL, NULL);
|
||||||
#else
|
#else
|
||||||
void test_main(void)
|
void test_main(void)
|
||||||
{
|
{
|
||||||
ztest_test_suite(tests_object_command,
|
ztest_test_suite(
|
||||||
ztest_unit_test(test_object_command)
|
tests_object_command, ztest_unit_test(test_object_command));
|
||||||
);
|
|
||||||
|
|
||||||
ztest_run_test_suite(tests_object_command);
|
ztest_run_test_suite(tests_object_command);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ add_compile_definitions(
|
|||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${SRC_DIR}
|
${SRC_DIR}
|
||||||
|
${TST_DIR}/bacnet/basic/object
|
||||||
${TST_DIR}/ztest/include
|
${TST_DIR}/ztest/include
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -52,6 +53,7 @@ add_executable(${PROJECT_NAME}
|
|||||||
${SRC_DIR}/bacnet/indtext.c
|
${SRC_DIR}/bacnet/indtext.c
|
||||||
${SRC_DIR}/bacnet/hostnport.c
|
${SRC_DIR}/bacnet/hostnport.c
|
||||||
${SRC_DIR}/bacnet/lighting.c
|
${SRC_DIR}/bacnet/lighting.c
|
||||||
|
${SRC_DIR}/bacnet/proplist.c
|
||||||
${SRC_DIR}/bacnet/timestamp.c
|
${SRC_DIR}/bacnet/timestamp.c
|
||||||
${SRC_DIR}/bacnet/wp.c
|
${SRC_DIR}/bacnet/wp.c
|
||||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||||
@@ -61,6 +63,7 @@ add_executable(${PROJECT_NAME}
|
|||||||
${SRC_DIR}/bacnet/special_event.c
|
${SRC_DIR}/bacnet/special_event.c
|
||||||
# Test and test library files
|
# Test and test library files
|
||||||
./src/main.c
|
./src/main.c
|
||||||
|
${TST_DIR}/bacnet/basic/object/property_test.c
|
||||||
${ZTST_DIR}/ztest_mock.c
|
${ZTST_DIR}/ztest_mock.c
|
||||||
${ZTST_DIR}/ztest.c
|
${ZTST_DIR}/ztest.c
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
/*
|
/**
|
||||||
* Copyright (c) 2020 Legrand North America, LLC.
|
* @file
|
||||||
|
* @brief Unit test for object
|
||||||
|
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||||
|
* @date February 2024
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* @file
|
|
||||||
* @brief test BACnet integer encode/decode APIs
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <zephyr/ztest.h>
|
#include <zephyr/ztest.h>
|
||||||
#include <bacnet/basic/object/credential_data_input.h>
|
#include <bacnet/basic/object/credential_data_input.h>
|
||||||
#include <bacnet/bactext.h>
|
#include <bacnet/bactext.h>
|
||||||
|
#include <property_test.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup bacnet_tests
|
* @addtogroup bacnet_tests
|
||||||
@@ -26,65 +25,25 @@ ZTEST(credential_data_input_tests, testCredentialDataInput)
|
|||||||
static void testCredentialDataInput(void)
|
static void testCredentialDataInput(void)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
|
||||||
int len = 0;
|
|
||||||
int test_len = 0;
|
|
||||||
BACNET_READ_PROPERTY_DATA rpdata;
|
|
||||||
/* for decode value data */
|
|
||||||
BACNET_APPLICATION_DATA_VALUE value;
|
|
||||||
const int *pRequired = NULL;
|
|
||||||
const int *pOptional = NULL;
|
|
||||||
const int *pProprietary = NULL;
|
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
uint32_t object_instance = 0;
|
uint32_t object_instance = 0;
|
||||||
|
const int skip_fail_property_list[] = {
|
||||||
|
PROP_PRESENT_VALUE,
|
||||||
|
PROP_UPDATE_TIME,
|
||||||
|
PROP_SUPPORTED_FORMATS,
|
||||||
|
-1 };
|
||||||
|
|
||||||
Credential_Data_Input_Init();
|
Credential_Data_Input_Init();
|
||||||
count = Credential_Data_Input_Count();
|
count = Credential_Data_Input_Count();
|
||||||
zassert_true(count > 0, NULL);
|
zassert_true(count > 0, NULL);
|
||||||
object_instance = Credential_Data_Input_Index_To_Instance(0);
|
object_instance = Credential_Data_Input_Index_To_Instance(0);
|
||||||
rpdata.application_data = &apdu[0];
|
bacnet_object_properties_read_write_test(
|
||||||
rpdata.application_data_len = sizeof(apdu);
|
OBJECT_CREDENTIAL_DATA_INPUT,
|
||||||
rpdata.object_type = OBJECT_CREDENTIAL_DATA_INPUT;
|
object_instance,
|
||||||
rpdata.object_instance = object_instance;
|
Credential_Data_Input_Property_Lists,
|
||||||
Credential_Data_Input_Property_Lists(&pRequired, &pOptional, &pProprietary);
|
Credential_Data_Input_Read_Property,
|
||||||
while ((*pRequired) != -1) {
|
Credential_Data_Input_Write_Property,
|
||||||
rpdata.object_property = *pRequired;
|
skip_fail_property_list);
|
||||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
|
||||||
len = Credential_Data_Input_Read_Property(&rpdata);
|
|
||||||
zassert_not_equal(len, BACNET_STATUS_ERROR, NULL);
|
|
||||||
if (len > 0) {
|
|
||||||
test_len = bacapp_decode_application_data(rpdata.application_data,
|
|
||||||
(uint8_t)rpdata.application_data_len, &value);
|
|
||||||
if (len != test_len) {
|
|
||||||
printf("property '%s': failed to decode!\n",
|
|
||||||
bactext_property_name(rpdata.object_property));
|
|
||||||
}
|
|
||||||
if (rpdata.object_property == PROP_PRIORITY_ARRAY) {
|
|
||||||
/* FIXME: known fail to decode */
|
|
||||||
len = test_len;
|
|
||||||
}
|
|
||||||
zassert_true(test_len >= 0, NULL);
|
|
||||||
} else {
|
|
||||||
printf("property '%s': failed to read!\n",
|
|
||||||
bactext_property_name(rpdata.object_property));
|
|
||||||
}
|
|
||||||
pRequired++;
|
|
||||||
}
|
|
||||||
while ((*pOptional) != -1) {
|
|
||||||
rpdata.object_property = *pOptional;
|
|
||||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
|
||||||
len = Credential_Data_Input_Read_Property(&rpdata);
|
|
||||||
zassert_not_equal(len, BACNET_STATUS_ERROR, NULL);
|
|
||||||
if (len > 0) {
|
|
||||||
test_len = bacapp_decode_application_data(rpdata.application_data,
|
|
||||||
(uint8_t)rpdata.application_data_len, &value);
|
|
||||||
zassert_true(test_len >= 0, NULL);
|
|
||||||
} else {
|
|
||||||
printf("property '%s': failed to read!\n",
|
|
||||||
bactext_property_name(rpdata.object_property));
|
|
||||||
}
|
|
||||||
pOptional++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ add_compile_definitions(
|
|||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${SRC_DIR}
|
${SRC_DIR}
|
||||||
|
${TST_DIR}/bacnet/basic/object
|
||||||
${TST_DIR}/ztest/include
|
${TST_DIR}/ztest/include
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -61,6 +62,7 @@ add_executable(${PROJECT_NAME}
|
|||||||
${SRC_DIR}/bacnet/special_event.c
|
${SRC_DIR}/bacnet/special_event.c
|
||||||
# Test and test library files
|
# Test and test library files
|
||||||
./src/main.c
|
./src/main.c
|
||||||
|
${TST_DIR}/bacnet/basic/object/property_test.c
|
||||||
${ZTST_DIR}/ztest_mock.c
|
${ZTST_DIR}/ztest_mock.c
|
||||||
${ZTST_DIR}/ztest.c
|
${ZTST_DIR}/ztest.c
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
/*
|
/**
|
||||||
* Copyright (c) 2020 Legrand North America, LLC.
|
* @file
|
||||||
|
* @brief Unit test for object
|
||||||
|
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||||
|
* @date February 2024
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* @file
|
|
||||||
* @brief test BACnet integer encode/decode APIs
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <zephyr/ztest.h>
|
#include <zephyr/ztest.h>
|
||||||
#include <bacnet/readrange.h>
|
#include <bacnet/readrange.h>
|
||||||
#include <bacnet/basic/object/netport.h>
|
#include <bacnet/basic/object/netport.h>
|
||||||
|
#include <property_test.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup bacnet_tests
|
* @addtogroup bacnet_tests
|
||||||
@@ -26,23 +25,18 @@ ZTEST(netport_tests, test_network_port)
|
|||||||
static void test_network_port(void)
|
static void test_network_port(void)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
|
||||||
int len = 0;
|
|
||||||
int test_len = 0;
|
|
||||||
BACNET_READ_PROPERTY_DATA rpdata;
|
|
||||||
/* for decode value data */
|
|
||||||
BACNET_APPLICATION_DATA_VALUE value;
|
|
||||||
const int *pRequired = NULL;
|
|
||||||
const int *pOptional = NULL;
|
|
||||||
const int *pProprietary = NULL;
|
|
||||||
unsigned port = 0;
|
unsigned port = 0;
|
||||||
|
bool status = false;
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
uint32_t object_instance = 0;
|
uint32_t object_instance = 0;
|
||||||
bool status = false;
|
|
||||||
uint8_t port_type[] = { PORT_TYPE_ETHERNET, PORT_TYPE_ARCNET,
|
uint8_t port_type[] = { PORT_TYPE_ETHERNET, PORT_TYPE_ARCNET,
|
||||||
PORT_TYPE_MSTP, PORT_TYPE_PTP, PORT_TYPE_LONTALK, PORT_TYPE_BIP,
|
PORT_TYPE_MSTP, PORT_TYPE_PTP, PORT_TYPE_LONTALK, PORT_TYPE_BIP,
|
||||||
PORT_TYPE_ZIGBEE, PORT_TYPE_VIRTUAL, PORT_TYPE_NON_BACNET,
|
PORT_TYPE_ZIGBEE, PORT_TYPE_VIRTUAL, PORT_TYPE_NON_BACNET,
|
||||||
PORT_TYPE_BIP6, PORT_TYPE_MAX };
|
PORT_TYPE_BIP6, PORT_TYPE_MAX };
|
||||||
|
const int known_fail_property_list[] = { PROP_IP_DNS_SERVER,
|
||||||
|
PROP_BBMD_BROADCAST_DISTRIBUTION_TABLE,
|
||||||
|
PROP_BBMD_FOREIGN_DEVICE_TABLE, PROP_FD_BBMD_ADDRESS,
|
||||||
|
PROP_IPV6_DNS_SERVER, -1 };
|
||||||
|
|
||||||
while (port_type[port] != PORT_TYPE_MAX) {
|
while (port_type[port] != PORT_TYPE_MAX) {
|
||||||
object_instance = 1234;
|
object_instance = 1234;
|
||||||
@@ -53,43 +47,13 @@ static void test_network_port(void)
|
|||||||
Network_Port_Init();
|
Network_Port_Init();
|
||||||
count = Network_Port_Count();
|
count = Network_Port_Count();
|
||||||
zassert_true(count > 0, NULL);
|
zassert_true(count > 0, NULL);
|
||||||
rpdata.application_data = &apdu[0];
|
bacnet_object_properties_read_write_test(
|
||||||
rpdata.application_data_len = sizeof(apdu);
|
OBJECT_NETWORK_PORT,
|
||||||
rpdata.object_type = OBJECT_NETWORK_PORT;
|
object_instance,
|
||||||
rpdata.object_instance = object_instance;
|
Network_Port_Property_Lists,
|
||||||
Network_Port_Property_Lists(&pRequired, &pOptional, &pProprietary);
|
Network_Port_Read_Property,
|
||||||
while ((*pRequired) != -1) {
|
Network_Port_Write_Property,
|
||||||
rpdata.object_property = *pRequired;
|
known_fail_property_list);
|
||||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
|
||||||
len = Network_Port_Read_Property(&rpdata);
|
|
||||||
zassert_not_equal(len, BACNET_STATUS_ERROR, NULL);
|
|
||||||
if (len > 0) {
|
|
||||||
test_len = bacapp_decode_application_data(
|
|
||||||
rpdata.application_data,
|
|
||||||
(uint8_t)rpdata.application_data_len, &value);
|
|
||||||
zassert_true(test_len >= 0, NULL);
|
|
||||||
if (test_len < 0) {
|
|
||||||
printf("<decode failed!>\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pRequired++;
|
|
||||||
}
|
|
||||||
while ((*pOptional) != -1) {
|
|
||||||
rpdata.object_property = *pOptional;
|
|
||||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
|
||||||
len = Network_Port_Read_Property(&rpdata);
|
|
||||||
zassert_not_equal(len, BACNET_STATUS_ERROR, NULL);
|
|
||||||
if (len > 0) {
|
|
||||||
test_len = bacapp_decode_application_data(
|
|
||||||
rpdata.application_data,
|
|
||||||
(uint8_t)rpdata.application_data_len, &value);
|
|
||||||
zassert_true(test_len >= 0, NULL);
|
|
||||||
if (test_len < 0) {
|
|
||||||
printf("<decode failed!>\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pOptional++;
|
|
||||||
}
|
|
||||||
port++;
|
port++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,15 +63,12 @@ static void test_network_port(void)
|
|||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#if defined(CONFIG_ZTEST_NEW_API)
|
#if defined(CONFIG_ZTEST_NEW_API)
|
||||||
ZTEST_SUITE(netport_tests, NULL, NULL, NULL, NULL, NULL);
|
ZTEST_SUITE(netport_tests, NULL, NULL, NULL, NULL, NULL);
|
||||||
#else
|
#else
|
||||||
void test_main(void)
|
void test_main(void)
|
||||||
{
|
{
|
||||||
ztest_test_suite(netport_tests,
|
ztest_test_suite(netport_tests, ztest_unit_test(test_network_port));
|
||||||
ztest_unit_test(test_network_port)
|
|
||||||
);
|
|
||||||
|
|
||||||
ztest_run_test_suite(netport_tests);
|
ztest_run_test_suite(netport_tests);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,210 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Unit test for object property read/write
|
||||||
|
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||||
|
* @date February 2024
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
#include <zephyr/ztest.h>
|
||||||
|
#include <bacnet/bactext.h>
|
||||||
|
#include <bacnet/rp.h>
|
||||||
|
#include <bacnet/rpm.h>
|
||||||
|
#include <bacnet/wp.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Perform a read/write test on a property
|
||||||
|
* @param rpdata [in,out] The structure to hold the read property request
|
||||||
|
* @param read_property [in] The function to read the property
|
||||||
|
* @param write_property [in] The function to write the property
|
||||||
|
* @param skip_fail_property_list [in] The list of properties that
|
||||||
|
* are known to fail to decode after reading
|
||||||
|
* @return true if the property was written successfully, false if not
|
||||||
|
*/
|
||||||
|
bool bacnet_object_property_write_test(BACNET_WRITE_PROPERTY_DATA *wpdata,
|
||||||
|
write_property_function write_property,
|
||||||
|
const int *skip_fail_property_list)
|
||||||
|
{
|
||||||
|
bool status = false;
|
||||||
|
int len = 0;
|
||||||
|
int test_len = 0;
|
||||||
|
|
||||||
|
(void)skip_fail_property_list;
|
||||||
|
if (wpdata && write_property) {
|
||||||
|
status = write_property(wpdata);
|
||||||
|
if (!status) {
|
||||||
|
/* verify WriteProperty property is known */
|
||||||
|
zassert_not_equal(wpdata->error_code, ERROR_CODE_UNKNOWN_PROPERTY,
|
||||||
|
"property '%s': WriteProperty Unknown!\n",
|
||||||
|
bactext_property_name(wpdata->object_property));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize the write property parameter structure data from the
|
||||||
|
* read property parameter structure data and the length of the property value
|
||||||
|
* @param wpdata [in,out] The structure to hold the write property request
|
||||||
|
* @param rpdata [in] The structure to hold the read property request
|
||||||
|
*/
|
||||||
|
void bacnet_object_property_write_parameter_init(
|
||||||
|
BACNET_WRITE_PROPERTY_DATA *wpdata,
|
||||||
|
BACNET_READ_PROPERTY_DATA *rpdata,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
if (wpdata && rpdata) {
|
||||||
|
/* WriteProperty parameters */
|
||||||
|
wpdata->object_type = rpdata->object_type;
|
||||||
|
wpdata->object_instance = rpdata->object_instance;
|
||||||
|
wpdata->object_property = rpdata->object_property;
|
||||||
|
wpdata->array_index = rpdata->array_index;
|
||||||
|
memcpy(&wpdata->application_data, rpdata->application_data, MAX_APDU);
|
||||||
|
wpdata->application_data_len = len;
|
||||||
|
wpdata->error_code = ERROR_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Perform a read/write test on a property
|
||||||
|
* @param rpdata [in,out] The structure to hold the read property request
|
||||||
|
* @param read_property [in] The function to read the property
|
||||||
|
* @param write_property [in] The function to write the property
|
||||||
|
* @param skip_fail_property_list [in] The list of properties that
|
||||||
|
* are known to fail to decode after reading
|
||||||
|
* @return length of the property value that was read
|
||||||
|
*/
|
||||||
|
int bacnet_object_property_read_test(BACNET_READ_PROPERTY_DATA *rpdata,
|
||||||
|
read_property_function read_property,
|
||||||
|
const int *skip_fail_property_list)
|
||||||
|
{
|
||||||
|
bool status = false;
|
||||||
|
int len = 0;
|
||||||
|
int test_len = 0;
|
||||||
|
int apdu_len = 0;
|
||||||
|
int read_len = 0;
|
||||||
|
uint8_t *apdu;
|
||||||
|
BACNET_ARRAY_INDEX array_index = 0;
|
||||||
|
BACNET_WRITE_PROPERTY_DATA wpdata = { 0 };
|
||||||
|
BACNET_APPLICATION_DATA_VALUE value = { 0 };
|
||||||
|
|
||||||
|
read_len = read_property(rpdata);
|
||||||
|
if ((read_len == BACNET_STATUS_ERROR) &&
|
||||||
|
(rpdata->error_class == ERROR_CLASS_PROPERTY) &&
|
||||||
|
(rpdata->error_code == ERROR_CODE_READ_ACCESS_DENIED)) {
|
||||||
|
/* read-only is a valid response for some properties */
|
||||||
|
} else if (read_len > 0) {
|
||||||
|
/* validate the data from the read request */
|
||||||
|
apdu = rpdata->application_data;
|
||||||
|
apdu_len = read_len;
|
||||||
|
while (apdu_len) {
|
||||||
|
len = bacapp_decode_known_property(apdu, apdu_len, &value,
|
||||||
|
rpdata->object_type, rpdata->object_property);
|
||||||
|
if (len > 0) {
|
||||||
|
test_len += len;
|
||||||
|
if ((len < apdu_len) &&
|
||||||
|
(rpdata->array_index == BACNET_ARRAY_ALL)) {
|
||||||
|
/* more data, therefore, this is an array */
|
||||||
|
array_index = 1;
|
||||||
|
}
|
||||||
|
if (array_index > 0) {
|
||||||
|
apdu += len;
|
||||||
|
apdu_len -= len;
|
||||||
|
array_index++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("property '%s': failed to decode! len=%d\n",
|
||||||
|
bactext_property_name(rpdata->object_property),
|
||||||
|
len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (read_len != test_len) {
|
||||||
|
printf("property '%s': failed to decode! %d!=%d\n",
|
||||||
|
bactext_property_name(rpdata->object_property), test_len,
|
||||||
|
read_len);
|
||||||
|
}
|
||||||
|
if (property_list_member(
|
||||||
|
skip_fail_property_list, rpdata->object_property)) {
|
||||||
|
/* FIXME: known fail to decode */
|
||||||
|
test_len = read_len;
|
||||||
|
}
|
||||||
|
zassert_true(test_len == read_len, NULL);
|
||||||
|
} else if (read_len == 0) {
|
||||||
|
/* empty response is valid for some properties */
|
||||||
|
} else {
|
||||||
|
zassert_not_equal(len, BACNET_STATUS_ERROR,
|
||||||
|
"property '%s': failed to read!\n",
|
||||||
|
bactext_property_name(rpdata->object_property));
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test all the properties of an object for read/write
|
||||||
|
*
|
||||||
|
* @param object_type The type of object to test
|
||||||
|
* @param object_instance The instance number of the object to test
|
||||||
|
* @param property_list The function to get the list of properties
|
||||||
|
* @param read_property The function to read the property
|
||||||
|
* @param write_property The function to write the property
|
||||||
|
* @param skip_fail_property_list The list of properties that
|
||||||
|
* are known to fail to decode after reading
|
||||||
|
*/
|
||||||
|
void bacnet_object_properties_read_write_test(BACNET_OBJECT_TYPE object_type,
|
||||||
|
uint32_t object_instance,
|
||||||
|
rpm_property_lists_function property_list,
|
||||||
|
read_property_function read_property,
|
||||||
|
write_property_function write_property,
|
||||||
|
const int *skip_fail_property_list)
|
||||||
|
{
|
||||||
|
uint8_t apdu[MAX_APDU] = { 0 };
|
||||||
|
BACNET_READ_PROPERTY_DATA rpdata = { 0 };
|
||||||
|
BACNET_WRITE_PROPERTY_DATA wpdata = { 0 };
|
||||||
|
const int *pRequired = NULL;
|
||||||
|
const int *pOptional = NULL;
|
||||||
|
const int *pProprietary = NULL;
|
||||||
|
unsigned count = 0;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
/* ReadProperty parameters */
|
||||||
|
rpdata.application_data = &apdu[0];
|
||||||
|
rpdata.application_data_len = sizeof(apdu);
|
||||||
|
rpdata.object_type = object_type;
|
||||||
|
rpdata.object_instance = object_instance;
|
||||||
|
property_list(&pRequired, &pOptional, &pProprietary);
|
||||||
|
while ((*pRequired) != -1) {
|
||||||
|
rpdata.object_property = *pRequired;
|
||||||
|
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||||
|
len = bacnet_object_property_read_test(
|
||||||
|
&rpdata, read_property, skip_fail_property_list);
|
||||||
|
bacnet_object_property_write_parameter_init(&wpdata, &rpdata, len);
|
||||||
|
bacnet_object_property_write_test(
|
||||||
|
&wpdata, write_property, skip_fail_property_list);
|
||||||
|
pRequired++;
|
||||||
|
}
|
||||||
|
while ((*pOptional) != -1) {
|
||||||
|
rpdata.object_property = *pOptional;
|
||||||
|
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||||
|
bacnet_object_property_read_test(
|
||||||
|
&rpdata, read_property, skip_fail_property_list);
|
||||||
|
bacnet_object_property_write_parameter_init(&wpdata, &rpdata, len);
|
||||||
|
bacnet_object_property_write_test(
|
||||||
|
&wpdata, write_property, skip_fail_property_list);
|
||||||
|
pOptional++;
|
||||||
|
}
|
||||||
|
while ((*pProprietary) != -1) {
|
||||||
|
rpdata.object_property = *pProprietary;
|
||||||
|
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||||
|
bacnet_object_property_read_test(
|
||||||
|
&rpdata, read_property, skip_fail_property_list);
|
||||||
|
bacnet_object_property_write_parameter_init(&wpdata, &rpdata, len);
|
||||||
|
bacnet_object_property_write_test(
|
||||||
|
&wpdata, write_property, skip_fail_property_list);
|
||||||
|
pProprietary++;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Unit test for object property read/write
|
||||||
|
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||||
|
* @date February 2024
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
#ifndef _BACNET_PROPERTY_TEST_H_
|
||||||
|
#define _BACNET_PROPERTY_TEST_H_
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <bacnet/rp.h>
|
||||||
|
#include <bacnet/rpm.h>
|
||||||
|
#include <bacnet/wp.h>
|
||||||
|
|
||||||
|
void bacnet_object_properties_read_write_test(
|
||||||
|
BACNET_OBJECT_TYPE object_type,
|
||||||
|
uint32_t object_instance,
|
||||||
|
rpm_property_lists_function property_list,
|
||||||
|
read_property_function read_property,
|
||||||
|
write_property_function write_property,
|
||||||
|
const int *skip_fail_property_list);
|
||||||
|
|
||||||
|
int bacnet_object_property_read_test(
|
||||||
|
BACNET_READ_PROPERTY_DATA *rpdata,
|
||||||
|
read_property_function read_property,
|
||||||
|
const int *skip_fail_property_list);
|
||||||
|
|
||||||
|
bool bacnet_object_property_write_test(
|
||||||
|
BACNET_WRITE_PROPERTY_DATA *wpdata,
|
||||||
|
write_property_function write_property,
|
||||||
|
const int *skip_fail_property_list);
|
||||||
|
|
||||||
|
void bacnet_object_property_write_parameter_init(
|
||||||
|
BACNET_WRITE_PROPERTY_DATA *wpdata,
|
||||||
|
BACNET_READ_PROPERTY_DATA *rpdata,
|
||||||
|
int len);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -27,6 +27,7 @@ add_compile_definitions(
|
|||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${SRC_DIR}
|
${SRC_DIR}
|
||||||
|
${TST_DIR}/bacnet/basic/object
|
||||||
${TST_DIR}/ztest/include
|
${TST_DIR}/ztest/include
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -50,6 +51,7 @@ add_executable(${PROJECT_NAME}
|
|||||||
${SRC_DIR}/bacnet/indtext.c
|
${SRC_DIR}/bacnet/indtext.c
|
||||||
${SRC_DIR}/bacnet/hostnport.c
|
${SRC_DIR}/bacnet/hostnport.c
|
||||||
${SRC_DIR}/bacnet/lighting.c
|
${SRC_DIR}/bacnet/lighting.c
|
||||||
|
${SRC_DIR}/bacnet/proplist.c
|
||||||
${SRC_DIR}/bacnet/timestamp.c
|
${SRC_DIR}/bacnet/timestamp.c
|
||||||
${SRC_DIR}/bacnet/wp.c
|
${SRC_DIR}/bacnet/wp.c
|
||||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||||
@@ -58,6 +60,7 @@ add_executable(${PROJECT_NAME}
|
|||||||
${SRC_DIR}/bacnet/special_event.c
|
${SRC_DIR}/bacnet/special_event.c
|
||||||
# Test and test library files
|
# Test and test library files
|
||||||
./src/main.c
|
./src/main.c
|
||||||
|
${TST_DIR}/bacnet/basic/object/property_test.c
|
||||||
${ZTST_DIR}/ztest_mock.c
|
${ZTST_DIR}/ztest_mock.c
|
||||||
${ZTST_DIR}/ztest.c
|
${ZTST_DIR}/ztest.c
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include <zephyr/ztest.h>
|
#include <zephyr/ztest.h>
|
||||||
#include <bacnet/basic/object/schedule.h>
|
#include <bacnet/basic/object/schedule.h>
|
||||||
#include <bacnet/bactext.h>
|
#include <property_test.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup bacnet_tests
|
* @addtogroup bacnet_tests
|
||||||
@@ -25,70 +25,22 @@ ZTEST(schedule_tests, testSchedule)
|
|||||||
static void testSchedule(void)
|
static void testSchedule(void)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
|
||||||
int len = 0;
|
|
||||||
int test_len = 0;
|
|
||||||
BACNET_READ_PROPERTY_DATA rpdata;
|
|
||||||
/* for decode value data */
|
|
||||||
BACNET_APPLICATION_DATA_VALUE value;
|
|
||||||
const int *pRequired = NULL;
|
|
||||||
const int *pOptional = NULL;
|
|
||||||
const int *pProprietary = NULL;
|
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
bool status = false;
|
uint32_t object_instance = 0;
|
||||||
|
const int skip_fail_property_list[] = {
|
||||||
|
PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES, -1 };
|
||||||
|
|
||||||
Schedule_Init();
|
Schedule_Init();
|
||||||
count = Schedule_Count();
|
count = Schedule_Count();
|
||||||
zassert_true(count > 0, NULL);
|
zassert_true(count > 0, NULL);
|
||||||
rpdata.application_data = &apdu[0];
|
object_instance = Schedule_Index_To_Instance(0);
|
||||||
rpdata.application_data_len = sizeof(apdu);
|
bacnet_object_properties_read_write_test(
|
||||||
rpdata.object_type = OBJECT_SCHEDULE;
|
OBJECT_SCHEDULE,
|
||||||
rpdata.object_instance = Schedule_Index_To_Instance(0);;
|
object_instance,
|
||||||
status = Schedule_Valid_Instance(rpdata.object_instance);
|
Schedule_Property_Lists,
|
||||||
zassert_true(status, NULL);
|
Schedule_Read_Property,
|
||||||
Schedule_Property_Lists(&pRequired, &pOptional, &pProprietary);
|
Schedule_Write_Property,
|
||||||
while ((*pRequired) != -1) {
|
skip_fail_property_list);
|
||||||
rpdata.object_property = *pRequired;
|
|
||||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
|
||||||
len = Schedule_Read_Property(&rpdata);
|
|
||||||
zassert_not_equal(len, BACNET_STATUS_ERROR, NULL);
|
|
||||||
if (len > 0) {
|
|
||||||
test_len = bacapp_decode_application_data(rpdata.application_data,
|
|
||||||
(uint8_t)rpdata.application_data_len, &value);
|
|
||||||
if (len != test_len) {
|
|
||||||
printf("property '%s': failed to decode!\n",
|
|
||||||
bactext_property_name(rpdata.object_property));
|
|
||||||
}
|
|
||||||
if (rpdata.object_property == PROP_PRIORITY_ARRAY) {
|
|
||||||
/* FIXME: known fail to decode */
|
|
||||||
len = test_len;
|
|
||||||
}
|
|
||||||
zassert_true(test_len >= 0, NULL);
|
|
||||||
} else {
|
|
||||||
printf("property '%s': failed to read!\n",
|
|
||||||
bactext_property_name(rpdata.object_property));
|
|
||||||
}
|
|
||||||
pRequired++;
|
|
||||||
}
|
|
||||||
while ((*pOptional) != -1) {
|
|
||||||
rpdata.object_property = *pOptional;
|
|
||||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
|
||||||
len = Schedule_Read_Property(&rpdata);
|
|
||||||
zassert_not_equal(len, BACNET_STATUS_ERROR, NULL);
|
|
||||||
if (len > 0) {
|
|
||||||
test_len = bacapp_decode_application_data(rpdata.application_data,
|
|
||||||
(uint8_t)rpdata.application_data_len, &value);
|
|
||||||
if (len != test_len) {
|
|
||||||
printf("property '%s': failed to decode!\n",
|
|
||||||
bactext_property_name(rpdata.object_property));
|
|
||||||
}
|
|
||||||
zassert_true(test_len >= 0, NULL);
|
|
||||||
} else {
|
|
||||||
printf("property '%s': failed to read!\n",
|
|
||||||
bactext_property_name(rpdata.object_property));
|
|
||||||
}
|
|
||||||
pOptional++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ add_compile_definitions(
|
|||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${SRC_DIR}
|
${SRC_DIR}
|
||||||
|
${TST_DIR}/bacnet/basic/object
|
||||||
${TST_DIR}/ztest/include
|
${TST_DIR}/ztest/include
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -50,6 +51,7 @@ add_executable(${PROJECT_NAME}
|
|||||||
${SRC_DIR}/bacnet/indtext.c
|
${SRC_DIR}/bacnet/indtext.c
|
||||||
${SRC_DIR}/bacnet/hostnport.c
|
${SRC_DIR}/bacnet/hostnport.c
|
||||||
${SRC_DIR}/bacnet/lighting.c
|
${SRC_DIR}/bacnet/lighting.c
|
||||||
|
${SRC_DIR}/bacnet/proplist.c
|
||||||
${SRC_DIR}/bacnet/timestamp.c
|
${SRC_DIR}/bacnet/timestamp.c
|
||||||
${SRC_DIR}/bacnet/wp.c
|
${SRC_DIR}/bacnet/wp.c
|
||||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||||
@@ -59,6 +61,7 @@ add_executable(${PROJECT_NAME}
|
|||||||
# Test and test library files
|
# Test and test library files
|
||||||
./src/main.c
|
./src/main.c
|
||||||
../mock/device_mock.c
|
../mock/device_mock.c
|
||||||
|
${TST_DIR}/bacnet/basic/object/property_test.c
|
||||||
${ZTST_DIR}/ztest_mock.c
|
${ZTST_DIR}/ztest_mock.c
|
||||||
${ZTST_DIR}/ztest.c
|
${ZTST_DIR}/ztest.c
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include <zephyr/ztest.h>
|
#include <zephyr/ztest.h>
|
||||||
#include <bacnet/basic/object/trendlog.h>
|
#include <bacnet/basic/object/trendlog.h>
|
||||||
#include <bacnet/bactext.h>
|
#include <property_test.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup bacnet_tests
|
* @addtogroup bacnet_tests
|
||||||
@@ -21,70 +21,24 @@
|
|||||||
*/
|
*/
|
||||||
static void test_Trend_Log_ReadProperty(void)
|
static void test_Trend_Log_ReadProperty(void)
|
||||||
{
|
{
|
||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
|
||||||
int len = 0;
|
|
||||||
int test_len = 0;
|
|
||||||
BACNET_READ_PROPERTY_DATA rpdata;
|
|
||||||
/* for decode value data */
|
|
||||||
BACNET_APPLICATION_DATA_VALUE value;
|
|
||||||
const int *pRequired = NULL;
|
|
||||||
const int *pOptional = NULL;
|
|
||||||
const int *pProprietary = NULL;
|
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
|
uint32_t object_instance = 0;
|
||||||
bool status = false;
|
bool status = false;
|
||||||
|
const int known_fail_property_list[] = { -1 };
|
||||||
|
|
||||||
Trend_Log_Init();
|
Trend_Log_Init();
|
||||||
count = Trend_Log_Count();
|
count = Trend_Log_Count();
|
||||||
zassert_true(count > 0, NULL);
|
zassert_true(count > 0, NULL);
|
||||||
rpdata.application_data = &apdu[0];
|
object_instance = Trend_Log_Index_To_Instance(0);
|
||||||
rpdata.application_data_len = sizeof(apdu);
|
status = Trend_Log_Valid_Instance(object_instance);
|
||||||
rpdata.object_type = OBJECT_TRENDLOG;
|
|
||||||
rpdata.object_instance = Trend_Log_Index_To_Instance(0);;
|
|
||||||
status = Trend_Log_Valid_Instance(rpdata.object_instance);
|
|
||||||
zassert_true(status, NULL);
|
zassert_true(status, NULL);
|
||||||
Trend_Log_Property_Lists(&pRequired, &pOptional, &pProprietary);
|
bacnet_object_properties_read_write_test(
|
||||||
while ((*pRequired) != -1) {
|
OBJECT_TRENDLOG,
|
||||||
rpdata.object_property = *pRequired;
|
object_instance,
|
||||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
Trend_Log_Property_Lists,
|
||||||
len = Trend_Log_Read_Property(&rpdata);
|
Trend_Log_Read_Property,
|
||||||
if (len > 0) {
|
Trend_Log_Write_Property,
|
||||||
zassert_not_equal(len, BACNET_STATUS_ERROR, NULL);
|
known_fail_property_list);
|
||||||
test_len = bacapp_decode_application_data(rpdata.application_data,
|
|
||||||
(uint8_t)rpdata.application_data_len, &value);
|
|
||||||
if (len != test_len) {
|
|
||||||
printf("property '%s': failed to decode!\n",
|
|
||||||
bactext_property_name(rpdata.object_property));
|
|
||||||
}
|
|
||||||
if (rpdata.object_property == PROP_PRIORITY_ARRAY) {
|
|
||||||
/* FIXME: known fail to decode */
|
|
||||||
len = test_len;
|
|
||||||
}
|
|
||||||
zassert_true(test_len >= 0, NULL);
|
|
||||||
} else {
|
|
||||||
printf("property '%s': failed to read!\n",
|
|
||||||
bactext_property_name(rpdata.object_property));
|
|
||||||
}
|
|
||||||
pRequired++;
|
|
||||||
}
|
|
||||||
while ((*pOptional) != -1) {
|
|
||||||
rpdata.object_property = *pOptional;
|
|
||||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
|
||||||
len = Trend_Log_Read_Property(&rpdata);
|
|
||||||
zassert_not_equal(len, BACNET_STATUS_ERROR, NULL);
|
|
||||||
if (len > 0) {
|
|
||||||
test_len = bacapp_decode_application_data(rpdata.application_data,
|
|
||||||
(uint8_t)rpdata.application_data_len, &value);
|
|
||||||
if (len != test_len) {
|
|
||||||
printf("property '%s': failed to decode!\n",
|
|
||||||
bactext_property_name(rpdata.object_property));
|
|
||||||
}
|
|
||||||
zassert_true(test_len >= 0, NULL);
|
|
||||||
} else {
|
|
||||||
printf("property '%s': failed to read!\n",
|
|
||||||
bactext_property_name(rpdata.object_property));
|
|
||||||
}
|
|
||||||
pOptional++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
|
|||||||
@@ -20,12 +20,17 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME)
|
|||||||
# Update include path for this module
|
# Update include path for this module
|
||||||
list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src)
|
list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src)
|
||||||
|
|
||||||
|
set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object)
|
||||||
|
list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC})
|
||||||
|
|
||||||
if(BOARD STREQUAL unit_testing)
|
if(BOARD STREQUAL unit_testing)
|
||||||
file(RELATIVE_PATH BACNET_INCLUDE $ENV{ZEPHYR_BASE} ${BACNET_BASE}/src)
|
file(RELATIVE_PATH BACNET_INCLUDE $ENV{ZEPHYR_BASE} ${BACNET_BASE}/src)
|
||||||
list(APPEND INCLUDE ${BACNET_INCLUDE})
|
file(RELATIVE_PATH TEST_OBJECT_INCLUDE $ENV{ZEPHYR_BASE} ${TEST_OBJECT_SRC})
|
||||||
|
list(APPEND INCLUDE ${BACNET_INCLUDE} ${TEST_OBJECT_INCLUDE})
|
||||||
list(APPEND SOURCES
|
list(APPEND SOURCES
|
||||||
${BACNET_SRC_PATH}.c
|
${BACNET_SRC_PATH}.c
|
||||||
${BACNET_TEST_PATH}/src/main.c
|
${BACNET_TEST_PATH}/src/main.c
|
||||||
|
${TEST_OBJECT_SRC}/property_test.c
|
||||||
)
|
)
|
||||||
|
|
||||||
get_filename_component(BACNET_OBJECT_SRC ${BACNET_SRC_PATH} PATH)
|
get_filename_component(BACNET_OBJECT_SRC ${BACNET_SRC_PATH} PATH)
|
||||||
@@ -46,6 +51,7 @@ if(BOARD STREQUAL unit_testing)
|
|||||||
${BACNET_SRC}/bactext.c
|
${BACNET_SRC}/bactext.c
|
||||||
${BACNET_SRC}/indtext.c
|
${BACNET_SRC}/indtext.c
|
||||||
${BACNET_SRC}/lighting.c
|
${BACNET_SRC}/lighting.c
|
||||||
|
${BACNET_SRC}/proplist.c
|
||||||
${BACNET_SRC}/wp.c
|
${BACNET_SRC}/wp.c
|
||||||
${BACNET_SRC}/hostnport.c
|
${BACNET_SRC}/hostnport.c
|
||||||
${BACNET_SRC}/dailyschedule.c
|
${BACNET_SRC}/dailyschedule.c
|
||||||
@@ -63,7 +69,9 @@ else()
|
|||||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
project(${BACNET_NAME})
|
project(${BACNET_NAME})
|
||||||
|
|
||||||
target_include_directories(app PRIVATE ${BACNET_INCLUDE})
|
target_include_directories(app PRIVATE
|
||||||
|
${BACNET_INCLUDE}
|
||||||
|
${TEST_OBJECT_INCLUDE})
|
||||||
target_sources(app PRIVATE
|
target_sources(app PRIVATE
|
||||||
${BACNET_TEST_PATH}/src/main.c
|
${BACNET_TEST_PATH}/src/main.c
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -20,12 +20,17 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME)
|
|||||||
# Update include path for this module
|
# Update include path for this module
|
||||||
list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src)
|
list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src)
|
||||||
|
|
||||||
|
set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object)
|
||||||
|
list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC})
|
||||||
|
|
||||||
if(BOARD STREQUAL unit_testing)
|
if(BOARD STREQUAL unit_testing)
|
||||||
file(RELATIVE_PATH BACNET_INCLUDE $ENV{ZEPHYR_BASE} ${BACNET_BASE}/src)
|
file(RELATIVE_PATH BACNET_INCLUDE $ENV{ZEPHYR_BASE} ${BACNET_BASE}/src)
|
||||||
list(APPEND INCLUDE ${BACNET_INCLUDE})
|
file(RELATIVE_PATH TEST_OBJECT_INCLUDE $ENV{ZEPHYR_BASE} ${TEST_OBJECT_SRC})
|
||||||
|
list(APPEND INCLUDE ${BACNET_INCLUDE} ${TEST_OBJECT_INCLUDE})
|
||||||
list(APPEND SOURCES
|
list(APPEND SOURCES
|
||||||
${BACNET_SRC_PATH}.c
|
${BACNET_SRC_PATH}.c
|
||||||
${BACNET_TEST_PATH}/src/main.c
|
${BACNET_TEST_PATH}/src/main.c
|
||||||
|
${TEST_OBJECT_SRC}/property_test.c
|
||||||
)
|
)
|
||||||
|
|
||||||
get_filename_component(BACNET_OBJECT_SRC ${BACNET_SRC_PATH} PATH)
|
get_filename_component(BACNET_OBJECT_SRC ${BACNET_SRC_PATH} PATH)
|
||||||
@@ -46,6 +51,7 @@ if(BOARD STREQUAL unit_testing)
|
|||||||
${BACNET_SRC}/bactext.c
|
${BACNET_SRC}/bactext.c
|
||||||
${BACNET_SRC}/indtext.c
|
${BACNET_SRC}/indtext.c
|
||||||
${BACNET_SRC}/lighting.c
|
${BACNET_SRC}/lighting.c
|
||||||
|
${BACNET_SRC}/proplist.c
|
||||||
${BACNET_SRC}/wp.c
|
${BACNET_SRC}/wp.c
|
||||||
${BACNET_SRC}/authentication_factor.c
|
${BACNET_SRC}/authentication_factor.c
|
||||||
${BACNET_SRC}/authentication_factor_format.c
|
${BACNET_SRC}/authentication_factor_format.c
|
||||||
@@ -65,7 +71,9 @@ else()
|
|||||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
project(${BACNET_NAME})
|
project(${BACNET_NAME})
|
||||||
|
|
||||||
target_include_directories(app PRIVATE ${BACNET_INCLUDE})
|
target_include_directories(app PRIVATE
|
||||||
|
${BACNET_INCLUDE}
|
||||||
|
${TEST_OBJECT_INCLUDE})
|
||||||
target_sources(app PRIVATE
|
target_sources(app PRIVATE
|
||||||
${BACNET_TEST_PATH}/src/main.c
|
${BACNET_TEST_PATH}/src/main.c
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ if(BOARD STREQUAL unit_testing)
|
|||||||
list(APPEND SOURCES
|
list(APPEND SOURCES
|
||||||
${BACNET_SRC_PATH}.c
|
${BACNET_SRC_PATH}.c
|
||||||
${BACNET_TEST_PATH}/src/main.c
|
${BACNET_TEST_PATH}/src/main.c
|
||||||
|
${BACNET_TEST_PATH}/../property_test.c
|
||||||
|
${BACNET_TEST_PATH}/../property_test.h
|
||||||
)
|
)
|
||||||
|
|
||||||
get_filename_component(BACNET_OBJECT_SRC ${BACNET_SRC_PATH} PATH)
|
get_filename_component(BACNET_OBJECT_SRC ${BACNET_SRC_PATH} PATH)
|
||||||
@@ -46,6 +48,7 @@ if(BOARD STREQUAL unit_testing)
|
|||||||
${BACNET_SRC}/bactext.c
|
${BACNET_SRC}/bactext.c
|
||||||
${BACNET_SRC}/indtext.c
|
${BACNET_SRC}/indtext.c
|
||||||
${BACNET_SRC}/lighting.c
|
${BACNET_SRC}/lighting.c
|
||||||
|
${BACNET_SRC}/proplist.c
|
||||||
${BACNET_SRC}/wp.c
|
${BACNET_SRC}/wp.c
|
||||||
${BACNET_SRC}/proplist.c
|
${BACNET_SRC}/proplist.c
|
||||||
${BACNET_SRC}/datalink/bvlc.c
|
${BACNET_SRC}/datalink/bvlc.c
|
||||||
|
|||||||
@@ -20,12 +20,17 @@ get_filename_component(BACNET_NAME ${BACNET_BASE} NAME)
|
|||||||
# Update include path for this module
|
# Update include path for this module
|
||||||
list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src)
|
list(APPEND BACNET_INCLUDE ${BACNET_BASE}/src)
|
||||||
|
|
||||||
|
set(TEST_OBJECT_SRC ${BACNET_BASE}/test/bacnet/basic/object)
|
||||||
|
list(APPEND TEST_OBJECT_INCLUDE ${TEST_OBJECT_SRC})
|
||||||
|
|
||||||
if(BOARD STREQUAL unit_testing)
|
if(BOARD STREQUAL unit_testing)
|
||||||
file(RELATIVE_PATH BACNET_INCLUDE $ENV{ZEPHYR_BASE} ${BACNET_BASE}/src)
|
file(RELATIVE_PATH BACNET_INCLUDE $ENV{ZEPHYR_BASE} ${BACNET_BASE}/src)
|
||||||
list(APPEND INCLUDE ${BACNET_INCLUDE})
|
file(RELATIVE_PATH TEST_OBJECT_INCLUDE $ENV{ZEPHYR_BASE} ${TEST_OBJECT_SRC})
|
||||||
|
list(APPEND INCLUDE ${BACNET_INCLUDE} ${TEST_OBJECT_INCLUDE})
|
||||||
list(APPEND SOURCES
|
list(APPEND SOURCES
|
||||||
${BACNET_SRC_PATH}.c
|
${BACNET_SRC_PATH}.c
|
||||||
${BACNET_TEST_PATH}/src/main.c
|
${BACNET_TEST_PATH}/src/main.c
|
||||||
|
${TEST_OBJECT_SRC}/property_test.c
|
||||||
)
|
)
|
||||||
|
|
||||||
get_filename_component(BACNET_OBJECT_SRC ${BACNET_SRC_PATH} PATH)
|
get_filename_component(BACNET_OBJECT_SRC ${BACNET_SRC_PATH} PATH)
|
||||||
@@ -46,6 +51,7 @@ if(BOARD STREQUAL unit_testing)
|
|||||||
${BACNET_SRC}/bactext.c
|
${BACNET_SRC}/bactext.c
|
||||||
${BACNET_SRC}/indtext.c
|
${BACNET_SRC}/indtext.c
|
||||||
${BACNET_SRC}/lighting.c
|
${BACNET_SRC}/lighting.c
|
||||||
|
${BACNET_SRC}/proplist.c
|
||||||
${BACNET_SRC}/wp.c
|
${BACNET_SRC}/wp.c
|
||||||
${BACNET_SRC}/bactimevalue.c
|
${BACNET_SRC}/bactimevalue.c
|
||||||
${BACNET_SRC}/hostnport.c
|
${BACNET_SRC}/hostnport.c
|
||||||
@@ -64,7 +70,9 @@ else()
|
|||||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
project(${BACNET_NAME})
|
project(${BACNET_NAME})
|
||||||
|
|
||||||
target_include_directories(app PRIVATE ${BACNET_INCLUDE})
|
target_include_directories(app PRIVATE
|
||||||
|
${BACNET_INCLUDE}
|
||||||
|
${TEST_OBJECT_INCLUDE})
|
||||||
target_sources(app PRIVATE
|
target_sources(app PRIVATE
|
||||||
${BACNET_TEST_PATH}/src/main.c
|
${BACNET_TEST_PATH}/src/main.c
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user