Add octet and character string buffer codecs to used with fixed size buffers that are not declared as BACNET_OCTET_STRING or BACNET_CHARACTER_STRING. (#1237)
This commit is contained in:
+3
-1
@@ -12,7 +12,7 @@ The git repositories are hosted at the following sites:
|
||||
* https://bacnet.sourceforge.net/
|
||||
* https://github.com/bacnet-stack/bacnet-stack/
|
||||
|
||||
## [Unreleased] - 2026-02-13
|
||||
## [Unreleased] - 2026-02-19
|
||||
|
||||
### Security
|
||||
|
||||
@@ -40,6 +40,8 @@ The git repositories are hosted at the following sites:
|
||||
|
||||
### Added
|
||||
|
||||
* Added octet and character string buffer codecs to used with fixed
|
||||
size buffers that are not declared as BACNET_OCTET_STRING or BACNET_CHARACTER_STRING. (#1237)
|
||||
* Added CreateObject and DeleteObject for basic Accumulator objects and
|
||||
WriteProperty handling for object-name, scale, out-of-service, units,
|
||||
and max-pres-value. (#1234)
|
||||
|
||||
+605
-30
@@ -1394,6 +1394,31 @@ int encode_context_null(uint8_t *apdu, uint8_t tag_number)
|
||||
return encode_tag(apdu, tag_number, true, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the NULL value as application encoded
|
||||
* From clause 20.2.2 Encoding of a Null Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the data to be encoded, or NULL for length
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
*
|
||||
* @return returns the number of apdu bytes consumed,
|
||||
* or 0 if apdu_size is too small to fit the data
|
||||
*/
|
||||
int bacnet_null_application_encode(uint8_t *apdu, uint32_t apdu_size)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
|
||||
apdu_len = encode_application_null(NULL);
|
||||
if (apdu_len > apdu_size) {
|
||||
apdu_len = 0;
|
||||
} else {
|
||||
apdu_len = encode_application_null(apdu);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decode the NULL value when application encoded
|
||||
* From clause 20.2.2 Encoding of a Null Value
|
||||
@@ -2224,6 +2249,283 @@ int encode_application_object_id(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Octet String value as application tagged
|
||||
* from clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
* @param apdu - buffer to hold the bytes
|
||||
* @param buffer - the octet string to be encoded
|
||||
* @param buffer_size - the size of the octet string to be encoded
|
||||
* @return returns the number of apdu bytes encoded
|
||||
*/
|
||||
int encode_application_octet_string_buffer(
|
||||
uint8_t *apdu, const uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
int apdu_len = 0, len = 0, i = 0;
|
||||
|
||||
len = encode_tag(
|
||||
apdu, BACNET_APPLICATION_TAG_OCTET_STRING, false, buffer_size);
|
||||
apdu_len += len;
|
||||
if (apdu) {
|
||||
apdu += len;
|
||||
}
|
||||
for (i = 0; i < buffer_size; i++) {
|
||||
if (apdu && buffer) {
|
||||
apdu[i] = buffer[i];
|
||||
}
|
||||
}
|
||||
apdu_len += buffer_size;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Octet String Value as context tagged
|
||||
* from clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes, or NULL for length
|
||||
* @param tag_number - context tag number to be encoded
|
||||
* @param buffer - the octet string to be encoded
|
||||
* @param buffer_size - the size of the octet string to be encoded
|
||||
* @return returns the number of apdu bytes encoded
|
||||
*/
|
||||
int encode_context_octet_string_buffer(
|
||||
uint8_t *apdu,
|
||||
uint8_t tag_number,
|
||||
const uint8_t *buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
int apdu_len = 0, len = 0, i = 0;
|
||||
|
||||
len = encode_tag(apdu, tag_number, true, buffer_size);
|
||||
apdu_len += len;
|
||||
if (apdu) {
|
||||
apdu += len;
|
||||
}
|
||||
for (i = 0; i < buffer_size; i++) {
|
||||
if (apdu && buffer) {
|
||||
apdu[i] = buffer[i];
|
||||
}
|
||||
}
|
||||
apdu_len += buffer_size;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode an application tagged BACnet Octet String Value
|
||||
* From clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the data to be encoded, or NULL for length
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
* @param value - value to encode
|
||||
*
|
||||
* @return returns the number of apdu bytes encoded
|
||||
* or 0 if apdu_size is too small to fit the data
|
||||
*/
|
||||
int bacnet_octet_string_buffer_application_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
const uint8_t *buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
|
||||
apdu_len =
|
||||
encode_application_octet_string_buffer(NULL, buffer, buffer_size);
|
||||
if (apdu_len > apdu_size) {
|
||||
apdu_len = 0;
|
||||
} else {
|
||||
apdu_len =
|
||||
encode_application_octet_string_buffer(apdu, buffer, buffer_size);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode an context tagged BACnet Octet String Value
|
||||
* From clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the data to be encoded, or NULL for length
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
* @param tag_number - context tag number to be encoded
|
||||
* @param buffer - the octet string to be encoded
|
||||
* @param buffer_size - the size of the octet string to be encoded
|
||||
*
|
||||
* @return returns the number of apdu bytes encoded
|
||||
* or 0 if apdu_size is too small to fit the data
|
||||
*/
|
||||
int bacnet_octet_string_buffer_context_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_number,
|
||||
const uint8_t *buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
|
||||
apdu_len = encode_context_octet_string_buffer(
|
||||
NULL, tag_number, buffer, buffer_size);
|
||||
if (apdu_len > apdu_size) {
|
||||
apdu_len = 0;
|
||||
} else {
|
||||
apdu_len = encode_context_octet_string_buffer(
|
||||
apdu, tag_number, buffer, buffer_size);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decode the BACnet Octet String Value
|
||||
* from clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes
|
||||
* @param apdu_size - number of bytes in the buffer to decode
|
||||
* @param len_value - number of bytes in the octet string value encoding,
|
||||
* may be zero
|
||||
* @param buffer - the buffer where the decoded value is stored,
|
||||
* or NULL for length only.
|
||||
* @param buffer_size - number of bytes in the buffer where the
|
||||
* decoded value is stored
|
||||
*
|
||||
* @return number of bytes in the octet string value encoding (0..N)
|
||||
* or BACNET_STATUS_ERROR if malformed
|
||||
*/
|
||||
int bacnet_octet_string_buffer_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint32_t len_value,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
size_t i;
|
||||
size_t copy_len;
|
||||
|
||||
if (len_value > apdu_size) {
|
||||
/* malformed */
|
||||
return BACNET_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (apdu && buffer && buffer_size > 0) {
|
||||
/* copy only the available octets, up to the buffer size */
|
||||
copy_len = (len_value < buffer_size) ? (size_t)len_value : buffer_size;
|
||||
for (i = 0; i < copy_len; i++) {
|
||||
buffer[i] = apdu[i];
|
||||
}
|
||||
/* pad any remaining buffer space with zeros */
|
||||
for (i = copy_len; i < buffer_size; i++) {
|
||||
buffer[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (int)len_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes from bytes into a BACnet Octet String application encoding
|
||||
* from clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer of data to be decoded
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
* @param buffer - the buffer where the decoded value is stored,
|
||||
* or NULL for length only.
|
||||
* @param buffer_size - number of bytes in the buffer where the
|
||||
* decoded value is stored
|
||||
*
|
||||
* @return number of bytes decoded, zero if tag mismatch,
|
||||
* or #BACNET_STATUS_ERROR (-1) if malformed
|
||||
*/
|
||||
int bacnet_octet_string_buffer_application_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
int len = 0;
|
||||
BACNET_TAG tag = { 0 };
|
||||
|
||||
if (apdu_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
len = bacnet_tag_decode(apdu, apdu_size, &tag);
|
||||
if (len > 0) {
|
||||
if (tag.application &&
|
||||
(tag.number == BACNET_APPLICATION_TAG_OCTET_STRING)) {
|
||||
apdu_len = len;
|
||||
len = bacnet_octet_string_buffer_decode(
|
||||
&apdu[len], apdu_size - apdu_len, tag.len_value_type, buffer,
|
||||
buffer_size);
|
||||
if (len >= 0) {
|
||||
apdu_len += len;
|
||||
} else {
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
} else {
|
||||
apdu_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes from bytes into a BACnet Octet String application encoding
|
||||
* from clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes
|
||||
* @param apdu_size - number of bytes in the buffer to decode
|
||||
* @param tag_value - context tag number expected
|
||||
* @param buffer - the buffer where the decoded value is stored,
|
||||
* or NULL for length only.
|
||||
* @param buffer_size - number of bytes in the buffer where the
|
||||
* decoded value is stored
|
||||
*
|
||||
* @return number of bytes decoded, or zero if tag mismatch, or
|
||||
* #BACNET_STATUS_ERROR (-1) if malformed
|
||||
*/
|
||||
int bacnet_octet_string_buffer_context_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_value,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
int len = 0;
|
||||
BACNET_TAG tag = { 0 };
|
||||
|
||||
if (apdu_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
len = bacnet_tag_decode(apdu, apdu_size, &tag);
|
||||
if (len > 0) {
|
||||
if (tag.context && (tag.number == tag_value)) {
|
||||
apdu_len = len;
|
||||
len = bacnet_octet_string_buffer_decode(
|
||||
&apdu[apdu_len], apdu_size - apdu_len, tag.len_value_type,
|
||||
buffer, buffer_size);
|
||||
if (len >= 0) {
|
||||
apdu_len += len;
|
||||
} else {
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
} else {
|
||||
apdu_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
#if BACNET_USE_OCTETSTRING
|
||||
/**
|
||||
* @brief Encode the BACnet Octet String value
|
||||
@@ -2282,36 +2584,6 @@ int encode_application_octet_string(
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Octet String value as application tagged
|
||||
* from clause 20.2.8 Encoding of an Octet String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
* @param apdu - buffer to hold the bytes
|
||||
* @param buffer - the octet string to be encoded
|
||||
* @param buffer_size - the size of the octet string to be encoded
|
||||
* @return returns the number of apdu bytes encoded
|
||||
*/
|
||||
int encode_application_octet_string_buffer(
|
||||
uint8_t *apdu, const uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
int apdu_len = 0, len = 0, i = 0;
|
||||
|
||||
len = encode_tag(
|
||||
apdu, BACNET_APPLICATION_TAG_OCTET_STRING, false, buffer_size);
|
||||
apdu_len += len;
|
||||
if (apdu) {
|
||||
apdu += len;
|
||||
}
|
||||
for (i = 0; i < buffer_size; i++) {
|
||||
if (apdu && buffer) {
|
||||
apdu[i] = buffer[i];
|
||||
}
|
||||
}
|
||||
apdu_len += buffer_size;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Octet String Value as context tagged
|
||||
* from clause 20.2.8 Encoding of an Octet String Value
|
||||
@@ -2881,6 +3153,309 @@ int decode_context_character_string(
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Character String Value
|
||||
* from 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes
|
||||
* @param value - the BACnetCharacterString buffer value to be encoded
|
||||
*
|
||||
* @return returns the number of apdu bytes consumed, or 0 if too large
|
||||
*/
|
||||
uint32_t encode_bacnet_character_string_buffer(
|
||||
uint8_t *apdu, const BACNET_CHARACTER_STRING_BUFFER *value)
|
||||
{
|
||||
uint32_t apdu_len = 1 /*encoding */;
|
||||
uint32_t i;
|
||||
|
||||
if (!value || !value->buffer) {
|
||||
return 0;
|
||||
}
|
||||
if (value->buffer_length > value->buffer_size) {
|
||||
return 0;
|
||||
}
|
||||
if (apdu) {
|
||||
apdu[0] = value->encoding;
|
||||
for (i = 0; i < value->buffer_length; i++) {
|
||||
apdu[1 + i] = value->buffer[i];
|
||||
}
|
||||
}
|
||||
apdu_len += value->buffer_length;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Character String Value as context tagged
|
||||
* from 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes, or NULL for length
|
||||
* @param tag_number - context tag number to encode
|
||||
* @param char_string - the BACnet Character String to be encoded
|
||||
*
|
||||
* @return returns the number of apdu bytes consumed
|
||||
*/
|
||||
int encode_context_character_string_buffer(
|
||||
uint8_t *apdu,
|
||||
uint8_t tag_number,
|
||||
const BACNET_CHARACTER_STRING_BUFFER *char_string)
|
||||
{
|
||||
int apdu_len = 0;
|
||||
int len = 0;
|
||||
uint32_t tag_len;
|
||||
|
||||
tag_len = encode_bacnet_character_string_buffer(NULL, char_string);
|
||||
if (tag_len == 0) {
|
||||
/* malformed, cannot be zero */
|
||||
return 0;
|
||||
}
|
||||
len = encode_tag(apdu, tag_number, true, tag_len);
|
||||
apdu_len += len;
|
||||
if (apdu) {
|
||||
apdu += len;
|
||||
}
|
||||
len = encode_bacnet_character_string_buffer(apdu, char_string);
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Character String Value as application tagged
|
||||
* from 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes, or NULL for length
|
||||
* @param char_string - the BACnet Character String to be encoded
|
||||
*
|
||||
* @return returns the number of apdu bytes consumed
|
||||
*/
|
||||
int encode_application_character_string_buffer(
|
||||
uint8_t *apdu, const BACNET_CHARACTER_STRING_BUFFER *char_string)
|
||||
{
|
||||
int apdu_len = 0;
|
||||
int len = 0;
|
||||
uint32_t tag_len;
|
||||
|
||||
tag_len = encode_bacnet_character_string_buffer(NULL, char_string);
|
||||
len = encode_tag(
|
||||
apdu, BACNET_APPLICATION_TAG_CHARACTER_STRING, false, tag_len);
|
||||
apdu_len += len;
|
||||
if (apdu) {
|
||||
apdu += len;
|
||||
}
|
||||
len = encode_bacnet_character_string_buffer(apdu, char_string);
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Character String Value as application tagged
|
||||
* from 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the data to be encoded, or NULL for length
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
* @param value - the BACnet Character String to be encoded
|
||||
*
|
||||
* @return returns the number of apdu bytes encoded
|
||||
* or 0 if apdu_size is too small to fit the data
|
||||
*/
|
||||
int bacnet_character_string_buffer_application_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
const BACNET_CHARACTER_STRING_BUFFER *value)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
|
||||
apdu_len = encode_application_character_string_buffer(NULL, value);
|
||||
if (apdu_len > apdu_size) {
|
||||
apdu_len = 0;
|
||||
} else {
|
||||
apdu_len = encode_application_character_string_buffer(apdu, value);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode the BACnet Character String Value as context tagged
|
||||
* from 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the data to be encoded, or NULL for length
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
* @param tag_number - context tag number to be encoded
|
||||
* @param value - the BACnet Character String to be encoded
|
||||
*
|
||||
* @return returns the number of apdu bytes encoded
|
||||
* or 0 if apdu_size is too small to fit the data
|
||||
*/
|
||||
int bacnet_character_string_buffer_context_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_number,
|
||||
const BACNET_CHARACTER_STRING_BUFFER *value)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
|
||||
apdu_len = encode_context_character_string_buffer(NULL, tag_number, value);
|
||||
if (apdu_len > apdu_size) {
|
||||
apdu_len = 0;
|
||||
} else {
|
||||
apdu_len =
|
||||
encode_context_character_string_buffer(apdu, tag_number, value);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes from bytes into a BACnet Character String value
|
||||
* from clause 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes
|
||||
* @param apdu_size - number of bytes in the buffer to decode
|
||||
* @param len_value - number of bytes in the unsigned value encoding
|
||||
* @param value - the BACnetCharacterString buffer value to be encoded
|
||||
*
|
||||
* @return number of bytes decoded, or zero if malformed or APDU overflow.
|
||||
* String size overflow is detectable by the caller by comparing the
|
||||
* buffer size to the buffer length in the value.
|
||||
*/
|
||||
int bacnet_character_string_buffer_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint32_t len_value,
|
||||
BACNET_CHARACTER_STRING_BUFFER *value)
|
||||
{
|
||||
const char *string_value = NULL;
|
||||
uint32_t string_length = 0;
|
||||
int len = 0, i = 0;
|
||||
uint8_t encoding = 0;
|
||||
|
||||
if ((len_value > apdu_size) || (len_value == 0)) {
|
||||
/* malformed */
|
||||
return 0;
|
||||
}
|
||||
encoding = apdu[0];
|
||||
if (len_value > 1) {
|
||||
string_length = len_value - 1;
|
||||
}
|
||||
if (value) {
|
||||
value->encoding = encoding;
|
||||
value->buffer_length = string_length;
|
||||
if (value->buffer) {
|
||||
string_value = (const char *)&apdu[1];
|
||||
for (i = 0; i < value->buffer_size; i++) {
|
||||
if (i < string_length) {
|
||||
value->buffer[i] = string_value[i];
|
||||
} else {
|
||||
/* pad buffer */
|
||||
value->buffer[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
len = (int)len_value;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes from bytes into a BACnet Character String value
|
||||
* from clause 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer of data to be decoded
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
* @param value - the BACnetCharacterString buffer value to be decoded
|
||||
*
|
||||
* @return number of bytes decoded, zero if tag mismatch,
|
||||
* or #BACNET_STATUS_ERROR (-1) if malformed
|
||||
*/
|
||||
int bacnet_character_string_buffer_application_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
BACNET_CHARACTER_STRING_BUFFER *value)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
int len = 0;
|
||||
BACNET_TAG tag = { 0 };
|
||||
|
||||
if (apdu_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
len = bacnet_tag_decode(apdu, apdu_size, &tag);
|
||||
if (len > 0) {
|
||||
if (tag.application &&
|
||||
(tag.number == BACNET_APPLICATION_TAG_CHARACTER_STRING)) {
|
||||
apdu_len = len;
|
||||
len = bacnet_character_string_buffer_decode(
|
||||
&apdu[len], apdu_size - apdu_len, tag.len_value_type, value);
|
||||
if (len > 0) {
|
||||
apdu_len += len;
|
||||
} else {
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
} else {
|
||||
apdu_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes from bytes into a BACnet Character String value
|
||||
* from clause 20.2.9 Encoding of a Character String Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @param apdu - buffer to hold the bytes
|
||||
* @param apdu_size - number of bytes in the buffer to decode
|
||||
* @param tag_value - context tag number expected
|
||||
* @param value - the BACnetCharacterString buffer value to be decoded
|
||||
*
|
||||
* @return number of bytes decoded, or zero if tag mismatch, or
|
||||
* #BACNET_STATUS_ERROR (-1) if malformed
|
||||
*/
|
||||
int bacnet_character_string_buffer_context_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_value,
|
||||
BACNET_CHARACTER_STRING_BUFFER *value)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
int len = 0;
|
||||
BACNET_TAG tag = { 0 };
|
||||
|
||||
if (apdu_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
len = bacnet_tag_decode(apdu, apdu_size, &tag);
|
||||
if (len > 0) {
|
||||
if (tag.context && (tag.number == tag_value)) {
|
||||
apdu_len = len;
|
||||
len = bacnet_character_string_buffer_decode(
|
||||
&apdu[apdu_len], apdu_size - apdu_len, tag.len_value_type,
|
||||
value);
|
||||
if (len > 0) {
|
||||
apdu_len += len;
|
||||
} else {
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
} else {
|
||||
apdu_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes from bytes into a BACnet Unsigned value
|
||||
* from clause 20.2.4 Encoding of an Unsigned Integer Value
|
||||
|
||||
+98
-3
@@ -86,6 +86,19 @@ typedef struct BACnetTag {
|
||||
uint32_t len_value_type;
|
||||
} BACNET_TAG;
|
||||
|
||||
typedef struct BACnetCharacterStringBuffer {
|
||||
uint8_t encoding;
|
||||
char *buffer;
|
||||
size_t buffer_size;
|
||||
uint32_t buffer_length;
|
||||
} BACNET_CHARACTER_STRING_BUFFER;
|
||||
|
||||
typedef struct BACnetOctetStringBuffer {
|
||||
uint8_t *buffer;
|
||||
size_t buffer_size;
|
||||
uint32_t buffer_length;
|
||||
} BACNET_OCTET_STRING_BUFFER;
|
||||
|
||||
/* max size of a BACnet tag */
|
||||
#define BACNET_TAG_SIZE 7
|
||||
|
||||
@@ -183,6 +196,8 @@ int encode_application_null(uint8_t *apdu);
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_context_null(uint8_t *apdu, uint8_t tag_number);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_null_application_encode(uint8_t *apdu, uint32_t apdu_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_null_application_decode(const uint8_t *apdu, uint32_t apdu_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_null_context_decode(
|
||||
@@ -384,15 +399,55 @@ bool bacnet_object_id_same(
|
||||
BACNET_OBJECT_TYPE object_type2,
|
||||
uint32_t instance2);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_application_octet_string_buffer(
|
||||
uint8_t *apdu, const uint8_t *buffer, size_t buffer_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_context_octet_string_buffer(
|
||||
uint8_t *apdu,
|
||||
uint8_t tag_number,
|
||||
const uint8_t *buffer,
|
||||
size_t buffer_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_octet_string_buffer_application_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
const uint8_t *buffer,
|
||||
size_t buffer_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_octet_string_buffer_context_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_number,
|
||||
const uint8_t *buffer,
|
||||
size_t buffer_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_octet_string_buffer_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint32_t len_value,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_octet_string_buffer_application_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_octet_string_buffer_context_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_value,
|
||||
uint8_t *buffer,
|
||||
size_t buffer_size);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_octet_string(uint8_t *apdu, const BACNET_OCTET_STRING *octet_string);
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_application_octet_string(
|
||||
uint8_t *apdu, const BACNET_OCTET_STRING *octet_string);
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_application_octet_string_buffer(
|
||||
uint8_t *apdu, const uint8_t *buffer, size_t buffer_size);
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_context_octet_string(
|
||||
uint8_t *apdu, uint8_t tag_number, const BACNET_OCTET_STRING *octet_string);
|
||||
BACNET_STACK_EXPORT
|
||||
@@ -431,6 +486,46 @@ uint32_t encode_bacnet_character_string_safe(
|
||||
const char *pString,
|
||||
uint32_t length);
|
||||
BACNET_STACK_EXPORT
|
||||
uint32_t encode_bacnet_character_string_buffer(
|
||||
uint8_t *apdu, const BACNET_CHARACTER_STRING_BUFFER *value);
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_context_character_string_buffer(
|
||||
uint8_t *apdu,
|
||||
uint8_t tag_number,
|
||||
const BACNET_CHARACTER_STRING_BUFFER *char_string);
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_application_character_string_buffer(
|
||||
uint8_t *apdu, const BACNET_CHARACTER_STRING_BUFFER *char_string);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_character_string_buffer_application_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
const BACNET_CHARACTER_STRING_BUFFER *value);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_character_string_buffer_context_encode(
|
||||
uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_number,
|
||||
const BACNET_CHARACTER_STRING_BUFFER *value);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_character_string_buffer_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint32_t len_value,
|
||||
BACNET_CHARACTER_STRING_BUFFER *value);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_character_string_buffer_application_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
BACNET_CHARACTER_STRING_BUFFER *value);
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_character_string_buffer_context_decode(
|
||||
const uint8_t *apdu,
|
||||
uint32_t apdu_size,
|
||||
uint8_t tag_value,
|
||||
BACNET_CHARACTER_STRING_BUFFER *value);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int encode_bacnet_character_string(
|
||||
uint8_t *apdu, const BACNET_CHARACTER_STRING *char_string);
|
||||
BACNET_STACK_EXPORT
|
||||
|
||||
+555
-24
@@ -166,6 +166,14 @@ static void testBACDCodeTags(void)
|
||||
len = encode_opening_tag(&apdu[0], tag_number);
|
||||
test_len = get_apdu_len(IS_EXTENDED_TAG_NUMBER(apdu[0]), 0);
|
||||
zassert_equal(len, test_len, NULL);
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
status = decode_is_opening_tag(&apdu[0]);
|
||||
zassert_true(status, NULL);
|
||||
#endif
|
||||
status = bacnet_is_opening_tag(apdu, 1);
|
||||
zassert_true(status, NULL);
|
||||
status = bacnet_is_opening_tag(apdu, 0);
|
||||
zassert_false(status, NULL);
|
||||
test_len = encode_opening_tag(NULL, tag_number);
|
||||
zassert_equal(len, test_len, NULL);
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
@@ -173,15 +181,27 @@ static void testBACDCodeTags(void)
|
||||
zassert_equal(value, 0, NULL);
|
||||
zassert_equal(len, test_len, NULL);
|
||||
zassert_equal(tag_number, test_tag_number, NULL);
|
||||
status = decode_is_opening_tag_number(apdu, tag_number);
|
||||
zassert_true(status, NULL);
|
||||
#endif
|
||||
zassert_true(IS_OPENING_TAG(apdu[0]), NULL);
|
||||
zassert_false(IS_CLOSING_TAG(apdu[0]), NULL);
|
||||
test_len = bacnet_tag_decode(apdu, sizeof(apdu), &tag);
|
||||
zassert_true(test_len > 0, NULL);
|
||||
zassert_true(tag.opening, NULL);
|
||||
zassert_false(tag.closing, NULL);
|
||||
len = encode_closing_tag(&apdu[0], tag_number);
|
||||
zassert_equal(len, test_len, NULL);
|
||||
/* closing tag */
|
||||
len = encode_closing_tag(&apdu[0], tag_number);
|
||||
test_len = get_apdu_len(IS_EXTENDED_TAG_NUMBER(apdu[0]), 0);
|
||||
zassert_equal(len, test_len, NULL);
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
status = decode_is_closing_tag(&apdu[0]);
|
||||
zassert_true(status, NULL);
|
||||
#endif
|
||||
status = bacnet_is_closing_tag(apdu, 1);
|
||||
zassert_true(status, NULL);
|
||||
status = bacnet_is_closing_tag(apdu, 0);
|
||||
zassert_false(status, NULL);
|
||||
test_len = encode_closing_tag(NULL, tag_number);
|
||||
zassert_equal(len, test_len, NULL);
|
||||
test_len = bacnet_tag_decode(apdu, sizeof(apdu), &tag);
|
||||
@@ -193,12 +213,15 @@ static void testBACDCodeTags(void)
|
||||
zassert_equal(len, test_len, NULL);
|
||||
zassert_equal(value, 0, NULL);
|
||||
zassert_equal(tag_number, test_tag_number, NULL);
|
||||
status = decode_is_closing_tag_number(apdu, tag_number);
|
||||
zassert_true(status, NULL);
|
||||
#endif
|
||||
zassert_false(IS_OPENING_TAG(apdu[0]), NULL);
|
||||
zassert_true(IS_CLOSING_TAG(apdu[0]), NULL);
|
||||
/* test the len-value-type portion */
|
||||
value = 0;
|
||||
for (i = 0; i < 32; i++) {
|
||||
/* non-context tag = application tag */
|
||||
len = encode_tag(&apdu[0], tag_number, false, value);
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
len = decode_tag_number_and_value(
|
||||
@@ -218,6 +241,46 @@ static void testBACDCodeTags(void)
|
||||
zassert_false(status, NULL);
|
||||
zassert_false(tag.closing, NULL);
|
||||
zassert_false(tag.opening, NULL);
|
||||
status = bacnet_is_context_specific(apdu, sizeof(apdu));
|
||||
zassert_false(status, NULL);
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
status = decode_is_context_tag(apdu, tag_number);
|
||||
zassert_false(status, NULL);
|
||||
status =
|
||||
decode_is_context_tag_with_length(apdu, tag_number, &tag_len);
|
||||
zassert_false(status, NULL);
|
||||
#endif
|
||||
len = bacnet_tag_number_and_value_decode(
|
||||
apdu, sizeof(apdu), &test_tag_number, &test_value);
|
||||
zassert_equal(len, test_len, NULL);
|
||||
zassert_equal(tag_number, test_tag_number, NULL);
|
||||
zassert_equal(value, test_value, NULL);
|
||||
/* context tag */
|
||||
len = encode_tag(&apdu[0], tag_number, true, value);
|
||||
test_len = bacnet_tag_decode(apdu, sizeof(apdu), &tag);
|
||||
zassert_equal(len, test_len, NULL);
|
||||
zassert_equal(tag.number, tag_number, NULL);
|
||||
zassert_true(tag.context, NULL);
|
||||
zassert_false(tag.application, NULL);
|
||||
status = bacnet_is_context_tag_number(
|
||||
apdu, sizeof(apdu), tag_number, &tag_len, &tag_len_value_type);
|
||||
zassert_true(status, NULL);
|
||||
zassert_false(tag.closing, NULL);
|
||||
zassert_false(tag.opening, NULL);
|
||||
status = bacnet_is_context_specific(apdu, sizeof(apdu));
|
||||
zassert_true(status, NULL);
|
||||
len = bacnet_tag_number_and_value_decode(
|
||||
apdu, sizeof(apdu), &test_tag_number, &test_value);
|
||||
zassert_equal(len, test_len, NULL);
|
||||
zassert_equal(tag_number, test_tag_number, NULL);
|
||||
zassert_equal(value, test_value, NULL);
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
status = decode_is_context_tag(apdu, tag_number);
|
||||
zassert_true(status, NULL);
|
||||
status =
|
||||
decode_is_context_tag_with_length(apdu, tag_number, &tag_len);
|
||||
zassert_true(status, NULL);
|
||||
#endif
|
||||
/* next value */
|
||||
value = BIT(i);
|
||||
}
|
||||
@@ -258,9 +321,24 @@ static void testBACnetTagEncoder(void)
|
||||
zassert_equal(tag.context, test_tag.context, NULL);
|
||||
zassert_equal(tag.closing, test_tag.closing, NULL);
|
||||
zassert_equal(tag.opening, test_tag.opening, NULL);
|
||||
len = bacnet_application_data_length(
|
||||
tag.number, tag.len_value_type);
|
||||
if ((tag.number == BACNET_APPLICATION_TAG_NULL) ||
|
||||
(tag.number == BACNET_APPLICATION_TAG_BOOLEAN)) {
|
||||
zassert_equal(len, 0, NULL);
|
||||
} else if (
|
||||
tag.application &&
|
||||
(tag.number <= BACNET_APPLICATION_TAG_OBJECT_ID) &&
|
||||
(tag.len_value_type < INT_MAX)) {
|
||||
zassert_equal(
|
||||
len, tag.len_value_type,
|
||||
"len=%d tag=%u len_value_type=%u", len,
|
||||
(unsigned)tag.number, tag.len_value_type);
|
||||
}
|
||||
/* next value */
|
||||
tag.len_value_type = BIT(i);
|
||||
}
|
||||
tag.number = BIT(i);
|
||||
tag.number = BIT(j);
|
||||
}
|
||||
tag.context = true;
|
||||
tag.application = false;
|
||||
@@ -309,6 +387,115 @@ static void testBACnetTagEncoder(void)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST(bacdcode_tests, testBACDCodeNULL)
|
||||
#else
|
||||
static void testBACDCodeNULL(void)
|
||||
#endif
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
int apdu_len = 0;
|
||||
int len = 0, null_len = 0;
|
||||
uint8_t tag_number = 3;
|
||||
BACNET_TAG tag = { 0 };
|
||||
|
||||
apdu_len = encode_application_null(&apdu[0]);
|
||||
null_len = encode_application_null(NULL);
|
||||
len = bacnet_null_application_decode(&apdu[0], apdu_len);
|
||||
zassert_equal(len, apdu_len, NULL);
|
||||
zassert_equal(null_len, apdu_len, NULL);
|
||||
len = bacnet_tag_decode(apdu, sizeof(apdu), &tag);
|
||||
zassert_true(len > 0, NULL);
|
||||
zassert_equal(tag.number, BACNET_APPLICATION_TAG_NULL, NULL);
|
||||
zassert_true(tag.application, NULL);
|
||||
zassert_false(tag.context, NULL);
|
||||
zassert_false(tag.closing, NULL);
|
||||
zassert_false(tag.opening, NULL);
|
||||
/* context specific encoding */
|
||||
apdu_len = encode_context_null(&apdu[0], tag_number);
|
||||
null_len = encode_context_null(NULL, tag_number);
|
||||
len = bacnet_tag_decode(apdu, sizeof(apdu), &tag);
|
||||
zassert_true(tag.context, NULL);
|
||||
zassert_false(tag.application, NULL);
|
||||
zassert_false(tag.closing, NULL);
|
||||
zassert_false(tag.opening, NULL);
|
||||
zassert_equal(tag.number, tag_number, NULL);
|
||||
zassert_equal(null_len, apdu_len, NULL);
|
||||
len = bacnet_null_context_decode(apdu, sizeof(apdu), tag_number);
|
||||
zassert_equal(len, apdu_len, NULL);
|
||||
/* test the interesting values */
|
||||
apdu_len = bacnet_null_application_encode(apdu, sizeof(apdu));
|
||||
null_len = bacnet_null_application_encode(NULL, sizeof(apdu));
|
||||
zassert_equal(apdu_len, null_len, NULL);
|
||||
len = bacnet_null_application_decode(apdu, apdu_len);
|
||||
zassert_equal(apdu_len, len, "len=%d apdu_len=%d", len, apdu_len);
|
||||
while (--apdu_len) {
|
||||
len = bacnet_null_application_encode(apdu, apdu_len);
|
||||
zassert_equal(len, 0, NULL);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST(bacdcode_tests, testBACDCodeBoolean)
|
||||
#else
|
||||
static void testBACDCodeBoolean(void)
|
||||
#endif
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
bool value = 0, decoded_value = 0;
|
||||
int i = 0, apdu_len = 0;
|
||||
int len = 0, null_len = 0;
|
||||
uint8_t tag_number = 3;
|
||||
BACNET_TAG tag = { 0 };
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
apdu_len = encode_application_boolean(&apdu[0], value);
|
||||
null_len = encode_application_boolean(NULL, value);
|
||||
len = bacnet_boolean_application_decode(
|
||||
&apdu[0], apdu_len, &decoded_value);
|
||||
zassert_equal(decoded_value, value, NULL);
|
||||
zassert_equal(len, apdu_len, NULL);
|
||||
zassert_equal(null_len, apdu_len, NULL);
|
||||
len = bacnet_tag_decode(apdu, sizeof(apdu), &tag);
|
||||
zassert_true(len > 0, NULL);
|
||||
zassert_equal(tag.number, BACNET_APPLICATION_TAG_BOOLEAN, NULL);
|
||||
zassert_true(tag.application, NULL);
|
||||
zassert_false(tag.context, NULL);
|
||||
zassert_false(tag.closing, NULL);
|
||||
zassert_false(tag.opening, NULL);
|
||||
/* context specific encoding */
|
||||
apdu_len = encode_context_boolean(&apdu[0], tag_number, value);
|
||||
null_len = encode_context_boolean(NULL, tag_number, value);
|
||||
len = bacnet_tag_decode(apdu, sizeof(apdu), &tag);
|
||||
zassert_true(tag.context, NULL);
|
||||
zassert_false(tag.application, NULL);
|
||||
zassert_false(tag.closing, NULL);
|
||||
zassert_false(tag.opening, NULL);
|
||||
zassert_equal(tag.number, tag_number, NULL);
|
||||
zassert_equal(null_len, apdu_len, NULL);
|
||||
len = bacnet_boolean_context_decode(
|
||||
apdu, sizeof(apdu), tag_number, &decoded_value);
|
||||
zassert_equal(len, apdu_len, NULL);
|
||||
zassert_equal(value, decoded_value, NULL);
|
||||
/* test the interesting values */
|
||||
value = (bool)i;
|
||||
}
|
||||
apdu_len = bacnet_boolean_application_encode(apdu, sizeof(apdu), value);
|
||||
null_len = bacnet_boolean_application_encode(NULL, sizeof(apdu), value);
|
||||
zassert_equal(apdu_len, null_len, NULL);
|
||||
len = bacnet_boolean_application_decode(apdu, apdu_len, &decoded_value);
|
||||
zassert_equal(apdu_len, len, "len=%d apdu_len=%d", len, apdu_len);
|
||||
zassert_equal(decoded_value, value, NULL);
|
||||
while (--apdu_len) {
|
||||
len = bacnet_boolean_application_encode(apdu, apdu_len, value);
|
||||
zassert_equal(len, 0, NULL);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST(bacdcode_tests, testBACDCodeEnumerated)
|
||||
#else
|
||||
@@ -534,7 +721,19 @@ static void testBACnetDateDecodes(void)
|
||||
zassert_equal(value.month, test_value.month, NULL);
|
||||
zassert_equal(value.wday, test_value.wday, NULL);
|
||||
zassert_equal(value.year, test_value.year, NULL);
|
||||
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
len = encode_bacnet_date(apdu, &value);
|
||||
test_len = decode_date(apdu, &test_value);
|
||||
zassert_equal(len, test_len, "len=%d test_len=%d", len, test_len);
|
||||
zassert_equal(value.day, test_value.day, NULL);
|
||||
zassert_equal(value.month, test_value.month, NULL);
|
||||
zassert_equal(value.wday, test_value.wday, NULL);
|
||||
zassert_equal(value.year, test_value.year, NULL);
|
||||
test_len = decode_date_safe(apdu, len, &test_value);
|
||||
zassert_equal(test_len, len, NULL);
|
||||
test_len = decode_date_safe(apdu, 0, &test_value);
|
||||
zassert_equal(test_len, 0, NULL);
|
||||
#endif
|
||||
memset(&test_value, 0, sizeof(test_value));
|
||||
test_len = decode_application_date(sample, &test_value);
|
||||
/* try decoding sample data captured from a bacnet device - all wildcards */
|
||||
@@ -1016,6 +1215,10 @@ static void testBACDCodeCharacterString(void)
|
||||
characterstring_value(&value), &test_name[0],
|
||||
characterstring_length(&value));
|
||||
zassert_equal(diff, 0, NULL);
|
||||
len = encode_bacnet_character_string_safe(
|
||||
&apdu[0], sizeof(apdu), CHARACTER_ANSI_X34, &test_name[0],
|
||||
characterstring_length(&value) + 1);
|
||||
zassert_equal(apdu_len, len, "len=%d apdu_len=%d", len, apdu_len);
|
||||
#endif
|
||||
for (i = 0; i < MAX_CHARACTER_STRING_BYTES - 1; i++) {
|
||||
test_name[i] = 'S';
|
||||
@@ -1210,6 +1413,7 @@ static void testBACDCodeBitString(void)
|
||||
BACNET_BIT_STRING test_value;
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
int len, null_len, apdu_len, test_len;
|
||||
uint8_t tag_number = 0;
|
||||
BACNET_TAG tag = { 0 };
|
||||
|
||||
bitstring_init(&value);
|
||||
@@ -1223,7 +1427,7 @@ static void testBACDCodeBitString(void)
|
||||
bitstring_set_bit(&value, bit, true);
|
||||
zassert_equal(bitstring_bits_used(&value), (bit + 1), NULL);
|
||||
zassert_true(bitstring_bit(&value, bit), NULL);
|
||||
/* encode */
|
||||
/* encode application tagged value */
|
||||
len = encode_application_bitstring(&apdu[0], &value);
|
||||
null_len = encode_application_bitstring(NULL, &value);
|
||||
zassert_equal(len, null_len, NULL);
|
||||
@@ -1234,6 +1438,22 @@ static void testBACDCodeBitString(void)
|
||||
len = bacnet_tag_decode(apdu, len, &tag);
|
||||
zassert_true(len > 0, NULL);
|
||||
zassert_equal(tag.number, BACNET_APPLICATION_TAG_BIT_STRING, NULL);
|
||||
/* encode context tagged value */
|
||||
tag_number = bit;
|
||||
len = encode_context_bitstring(&apdu[0], tag_number, &value);
|
||||
null_len = encode_context_bitstring(NULL, tag_number, &value);
|
||||
zassert_equal(len, null_len, NULL);
|
||||
/* decode */
|
||||
len = bacnet_bitstring_context_decode(
|
||||
apdu, null_len, tag_number, &test_value);
|
||||
zassert_equal(bitstring_bits_used(&test_value), (bit + 1), NULL);
|
||||
zassert_true(bitstring_bit(&test_value, bit), NULL);
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
len = decode_context_bitstring(&apdu[0], tag_number, &test_value);
|
||||
zassert_equal(len, null_len, NULL);
|
||||
zassert_equal(bitstring_bits_used(&test_value), (bit + 1), NULL);
|
||||
zassert_true(bitstring_bit(&test_value, bit), NULL);
|
||||
#endif
|
||||
}
|
||||
/* test encode/decode -- false */
|
||||
bitstring_init(&value);
|
||||
@@ -1488,6 +1708,11 @@ static void testFloatContextDecodes(void)
|
||||
zassert_false(islessgreater(in, out), NULL);
|
||||
zassert_equal(outLen2, 0, NULL);
|
||||
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
outLen = decode_context_real(apdu, 10, &out);
|
||||
zassert_equal(inLen, outLen, NULL);
|
||||
#endif
|
||||
|
||||
inLen = encode_context_real(apdu, large_context_tag, in);
|
||||
outLen = bacnet_real_context_decode(apdu, inLen, large_context_tag, &out);
|
||||
outLen2 =
|
||||
@@ -1545,6 +1770,11 @@ static void testDoubleContextDecodes(void)
|
||||
zassert_false(islessgreater(in, out), NULL);
|
||||
zassert_equal(outLen2, 0, NULL);
|
||||
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
outLen = decode_context_double(apdu, 10, &out);
|
||||
zassert_equal(inLen, outLen, NULL);
|
||||
#endif
|
||||
|
||||
inLen = encode_context_double(apdu, large_context_tag, in);
|
||||
outLen = bacnet_double_context_decode(apdu, inLen, large_context_tag, &out);
|
||||
outLen2 =
|
||||
@@ -1592,6 +1822,7 @@ static void testObjectIDContextDecodes(void)
|
||||
uint32_t in_id;
|
||||
BACNET_OBJECT_TYPE out_type;
|
||||
uint32_t out_id;
|
||||
bool status;
|
||||
|
||||
in_type = 0xde;
|
||||
in_id = 0xbeef;
|
||||
@@ -1605,7 +1836,12 @@ static void testObjectIDContextDecodes(void)
|
||||
zassert_equal(in_type, out_type, NULL);
|
||||
zassert_equal(in_id, out_id, NULL);
|
||||
zassert_equal(outLen2, 0, NULL);
|
||||
|
||||
status = bacnet_object_id_same(in_type, in_id, out_type, out_id);
|
||||
zassert_true(status, NULL);
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
outLen = decode_context_object_id(apdu, 10, &out_type, &out_id);
|
||||
zassert_equal(inLen, outLen, NULL);
|
||||
#endif
|
||||
inLen = encode_context_object_id(apdu, large_context_tag, in_type, in_id);
|
||||
outLen = bacnet_object_id_context_decode(
|
||||
apdu, inLen, large_context_tag, &out_type, &out_id);
|
||||
@@ -1737,7 +1973,10 @@ static void testOctetStringContextDecodes(void)
|
||||
inLen = encode_context_octet_string(apdu, 10, &in);
|
||||
outLen = bacnet_octet_string_context_decode(apdu, inLen, 10, &out);
|
||||
outLen2 = bacnet_octet_string_context_decode(apdu, inLen, 9, &out);
|
||||
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
outLen = decode_context_octet_string(apdu, 10, &out);
|
||||
zassert_equal(inLen, outLen, NULL);
|
||||
#endif
|
||||
zassert_equal(outLen2, 0, NULL);
|
||||
zassert_equal(inLen, outLen, "inLen=%d outLen=%d", inLen, outLen);
|
||||
zassert_equal(in.length, out.length, NULL);
|
||||
@@ -1762,9 +2001,9 @@ static void testOctetStringContextDecodes(void)
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST(bacdcode_tests, testTimeContextDecodes)
|
||||
ZTEST(bacdcode_tests, testTimeDecodes)
|
||||
#else
|
||||
static void testTimeContextDecodes(void)
|
||||
static void testTimeDecodes(void)
|
||||
#endif
|
||||
{
|
||||
uint8_t apdu[MAX_APDU];
|
||||
@@ -1781,17 +2020,43 @@ static void testTimeContextDecodes(void)
|
||||
in.min = 30;
|
||||
in.sec = 40;
|
||||
|
||||
inLen = bacnet_time_application_encode(apdu, sizeof(apdu), &in);
|
||||
outLen = bacnet_time_application_decode(apdu, inLen, &out);
|
||||
zassert_equal(inLen, outLen, NULL);
|
||||
zassert_equal(in.hour, out.hour, NULL);
|
||||
zassert_equal(in.hundredths, out.hundredths, NULL);
|
||||
zassert_equal(in.min, out.min, NULL);
|
||||
zassert_equal(in.sec, out.sec, NULL);
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
outLen = decode_application_time(apdu, &out);
|
||||
zassert_equal(inLen, outLen, NULL);
|
||||
#endif
|
||||
while (inLen) {
|
||||
inLen--;
|
||||
outLen2 = bacnet_time_application_decode(apdu, inLen, &out);
|
||||
zassert_true(outLen2 <= 0, NULL);
|
||||
}
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
inLen = encode_bacnet_time(apdu, &in);
|
||||
outLen = decode_bacnet_time(apdu, &out);
|
||||
zassert_equal(inLen, outLen, NULL);
|
||||
outLen = decode_bacnet_time_safe(apdu, inLen, &out);
|
||||
zassert_equal(inLen, outLen, NULL);
|
||||
#endif
|
||||
|
||||
inLen = encode_context_time(apdu, 10, &in);
|
||||
outLen = bacnet_time_context_decode(apdu, inLen, 10, &out);
|
||||
outLen2 = bacnet_time_context_decode(apdu, inLen, 9, &out);
|
||||
|
||||
zassert_equal(outLen2, 0, NULL);
|
||||
zassert_equal(inLen, outLen, NULL);
|
||||
zassert_equal(in.hour, out.hour, NULL);
|
||||
zassert_equal(in.hundredths, out.hundredths, NULL);
|
||||
zassert_equal(in.min, out.min, NULL);
|
||||
zassert_equal(in.sec, out.sec, NULL);
|
||||
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
outLen = decode_context_bacnet_time(apdu, 10, &out);
|
||||
zassert_equal(inLen, outLen, NULL);
|
||||
#endif
|
||||
inLen = encode_context_time(apdu, large_context_tag, &in);
|
||||
outLen = bacnet_time_context_decode(apdu, inLen, large_context_tag, &out);
|
||||
outLen2 =
|
||||
@@ -1835,13 +2100,16 @@ static void testDateContextDecodes(void)
|
||||
inLen = encode_context_date(apdu, 10, &in);
|
||||
outLen = bacnet_date_context_decode(apdu, inLen, 10, &out);
|
||||
outLen2 = bacnet_date_context_decode(apdu, inLen, 9, &out);
|
||||
|
||||
zassert_equal(outLen2, 0, NULL);
|
||||
zassert_equal(inLen, outLen, NULL);
|
||||
zassert_equal(in.day, out.day, NULL);
|
||||
zassert_equal(in.month, out.month, NULL);
|
||||
zassert_equal(in.wday, out.wday, NULL);
|
||||
zassert_equal(in.year, out.year, NULL);
|
||||
#if defined(BACNET_STACK_DEPRECATED_DISABLE)
|
||||
outLen = decode_context_date(apdu, 10, &out);
|
||||
zassert_equal(inLen, outLen, NULL);
|
||||
#endif
|
||||
|
||||
/* Test large tags */
|
||||
inLen = encode_context_date(apdu, large_context_tag, &in);
|
||||
@@ -1931,6 +2199,30 @@ static int bacnet_apdu_property_element_encode(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode a BACnetARRAY property element; a function template
|
||||
* @param object_instance [in] BACnet network port object instance number
|
||||
* @param apdu_index [in] apdu index requested:
|
||||
* 0 to N for individual apdu members
|
||||
* @param apdu [out] Buffer in which the APDU contents are built, or NULL to
|
||||
* return the length of buffer if it had been built
|
||||
* @return The length of the apdu encoded or
|
||||
* BACNET_STATUS_ERROR for ERROR_CODE_INVALID_ARRAY_INDEX
|
||||
*/
|
||||
static int bacnet_apdu_property_zero_element_encode(
|
||||
uint32_t object_instance, BACNET_ARRAY_INDEX apdu_index, uint8_t *apdu)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
|
||||
(void)object_instance;
|
||||
(void)apdu;
|
||||
if (apdu_index < 1) {
|
||||
apdu_len = 0;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST(bacdcode_tests, test_bacnet_array_encode)
|
||||
#else
|
||||
@@ -1939,7 +2231,7 @@ static void test_bacnet_array_encode(void)
|
||||
{
|
||||
uint32_t object_instance = 0;
|
||||
BACNET_ARRAY_INDEX apdu_index = 0;
|
||||
BACNET_UNSIGNED_INTEGER apdu_size = 1;
|
||||
BACNET_UNSIGNED_INTEGER array_count = 1;
|
||||
uint8_t apdu[480] = { 0 };
|
||||
int apdu_len, len;
|
||||
uint8_t tag_number = 0;
|
||||
@@ -1947,27 +2239,27 @@ static void test_bacnet_array_encode(void)
|
||||
BACNET_UNSIGNED_INTEGER decoded_value = 0;
|
||||
BACNET_TAG tag = { 0 };
|
||||
|
||||
/* element zero returns the apdu size */
|
||||
/* element zero returns the count of array elements */
|
||||
apdu_len = bacnet_array_encode(
|
||||
object_instance, apdu_index, bacnet_apdu_property_element_encode,
|
||||
apdu_size, apdu, sizeof(apdu));
|
||||
array_count, apdu, sizeof(apdu));
|
||||
zassert_true(apdu_len > 0, NULL);
|
||||
len = bacnet_tag_decode(apdu, apdu_len, &tag);
|
||||
zassert_true(len > 0, NULL);
|
||||
zassert_equal(tag.number, BACNET_APPLICATION_TAG_UNSIGNED_INT, NULL);
|
||||
len = bacnet_unsigned_decode(
|
||||
&apdu[len], apdu_len - len, tag.len_value_type, &decoded_value);
|
||||
zassert_equal(decoded_value, apdu_size, NULL);
|
||||
zassert_equal(decoded_value, array_count, NULL);
|
||||
/* element zero - APDU too small */
|
||||
apdu_len = bacnet_array_encode(
|
||||
object_instance, apdu_index, bacnet_apdu_property_element_encode,
|
||||
apdu_size, apdu, 1);
|
||||
array_count, apdu, 1);
|
||||
zassert_true(apdu_len == BACNET_STATUS_ABORT, NULL);
|
||||
/* element 1 returns the first element */
|
||||
apdu_index = 1;
|
||||
apdu_len = bacnet_array_encode(
|
||||
object_instance, apdu_index, bacnet_apdu_property_element_encode,
|
||||
apdu_size, apdu, sizeof(apdu));
|
||||
array_count, apdu, sizeof(apdu));
|
||||
zassert_true(apdu_len > 0, NULL);
|
||||
len = decode_tag_number_and_value(apdu, &tag_number, &len_value);
|
||||
zassert_true(len > 0, NULL);
|
||||
@@ -1975,25 +2267,257 @@ static void test_bacnet_array_encode(void)
|
||||
/* element 1 - APDU too small */
|
||||
apdu_len = bacnet_array_encode(
|
||||
object_instance, apdu_index, bacnet_apdu_property_element_encode,
|
||||
apdu_size, apdu, 1);
|
||||
array_count, apdu, 1);
|
||||
zassert_true(apdu_len == BACNET_STATUS_ABORT, NULL);
|
||||
/* element 2, in this test case, returns an error */
|
||||
apdu_index = 2;
|
||||
apdu_len = bacnet_array_encode(
|
||||
object_instance, apdu_index, bacnet_apdu_property_element_encode,
|
||||
apdu_size, apdu, sizeof(apdu));
|
||||
array_count, apdu, sizeof(apdu));
|
||||
zassert_true(apdu_len < 0, NULL);
|
||||
/* ALL - fits in APDU */
|
||||
apdu_index = BACNET_ARRAY_ALL;
|
||||
apdu_len = bacnet_array_encode(
|
||||
object_instance, apdu_index, bacnet_apdu_property_element_encode,
|
||||
apdu_size, apdu, sizeof(apdu));
|
||||
array_count, apdu, sizeof(apdu));
|
||||
zassert_true(apdu_len == 5, "len=%d", apdu_len);
|
||||
/* ALL - APDU too small */
|
||||
apdu_len = bacnet_array_encode(
|
||||
object_instance, apdu_index, bacnet_apdu_property_element_encode,
|
||||
apdu_size, apdu, 4);
|
||||
array_count, apdu, 4);
|
||||
zassert_true(apdu_len == BACNET_STATUS_ABORT, NULL);
|
||||
/* ALL - elements are zero size */
|
||||
apdu_len = bacnet_array_encode(
|
||||
object_instance, apdu_index, bacnet_apdu_property_zero_element_encode,
|
||||
array_count, apdu, sizeof(apdu));
|
||||
zassert_true(apdu_len == 0, NULL);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST(bacdcode_tests, test_bacnet_enclosed_data_length)
|
||||
#else
|
||||
static void test_bacnet_enclosed_data_length(void)
|
||||
#endif
|
||||
{
|
||||
uint8_t apdu[480] = { 0 };
|
||||
int apdu_len = 0, len = 0, test_len = 0;
|
||||
unsigned bit_i;
|
||||
uint8_t tag_number;
|
||||
|
||||
test_len = bacnet_enclosed_data_length(NULL, apdu_len);
|
||||
zassert_equal(test_len, BACNET_STATUS_ERROR, NULL);
|
||||
test_len = bacnet_enclosed_data_length(apdu, apdu_len);
|
||||
zassert_equal(test_len, BACNET_STATUS_ERROR, NULL);
|
||||
/* nested sequence of open then close tags */
|
||||
for (bit_i = 0; bit_i < 8; bit_i++) {
|
||||
tag_number = BIT(bit_i);
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
}
|
||||
for (bit_i = 0; bit_i < 8; bit_i++) {
|
||||
tag_number = BIT(7 - bit_i);
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
}
|
||||
test_len = bacnet_enclosed_data_length(apdu, apdu_len);
|
||||
/* enclosed is 1 open and 1 close tag less than the APDU length */
|
||||
zassert_equal(
|
||||
test_len, apdu_len - 2, "test_len=%d apdu_len=%d", test_len, apdu_len);
|
||||
while (apdu_len) {
|
||||
apdu_len--;
|
||||
test_len = bacnet_enclosed_data_length(apdu, apdu_len);
|
||||
zassert_equal(test_len, BACNET_STATUS_ERROR, NULL);
|
||||
}
|
||||
/* nested same open then close tags */
|
||||
tag_number = BIT(0);
|
||||
for (bit_i = 0; bit_i < 8; bit_i++) {
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
}
|
||||
for (bit_i = 0; bit_i < 8; bit_i++) {
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
}
|
||||
test_len = bacnet_enclosed_data_length(apdu, apdu_len);
|
||||
zassert_equal(
|
||||
test_len, apdu_len - 2, "test_len=%d apdu_len=%d", test_len, apdu_len);
|
||||
while (apdu_len) {
|
||||
apdu_len--;
|
||||
test_len = bacnet_enclosed_data_length(apdu, apdu_len);
|
||||
zassert_equal(test_len, BACNET_STATUS_ERROR, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST(bacdcode_tests, test_octet_string_buffer)
|
||||
#else
|
||||
static void test_octet_string_buffer(void)
|
||||
#endif
|
||||
{
|
||||
uint8_t apdu[50] = { 0 };
|
||||
uint8_t buffer[32] = { 0 }, test_buffer[32] = { 0 };
|
||||
int apdu_len = 0, null_len = 0, test_len = 0;
|
||||
size_t buffer_size = 0;
|
||||
uint8_t tag_number = 0;
|
||||
unsigned i;
|
||||
int diff = 0; /* for memcmp */
|
||||
|
||||
buffer_size = sizeof(buffer);
|
||||
apdu_len =
|
||||
encode_application_octet_string_buffer(apdu, buffer, buffer_size);
|
||||
null_len =
|
||||
encode_application_octet_string_buffer(NULL, buffer, buffer_size);
|
||||
zassert_equal(apdu_len, null_len, NULL);
|
||||
for (i = 0; i < sizeof(buffer); i++) {
|
||||
buffer[i] = '0' + i;
|
||||
buffer_size = 1 + i;
|
||||
/* application tagged */
|
||||
apdu_len = bacnet_octet_string_buffer_application_encode(
|
||||
apdu, sizeof(apdu), buffer, buffer_size);
|
||||
null_len = bacnet_octet_string_buffer_application_encode(
|
||||
NULL, sizeof(apdu), buffer, buffer_size);
|
||||
zassert_equal(apdu_len, null_len, NULL);
|
||||
null_len = bacnet_octet_string_buffer_application_encode(
|
||||
NULL, 0, buffer, buffer_size);
|
||||
zassert_equal(null_len, 0, NULL);
|
||||
test_len = bacnet_octet_string_buffer_application_decode(
|
||||
apdu, apdu_len, test_buffer, sizeof(test_buffer));
|
||||
zassert_equal(
|
||||
apdu_len, test_len, "apdu_len=%d test_len=%d i=%d", apdu_len,
|
||||
test_len, i);
|
||||
diff = memcmp(buffer, test_buffer, buffer_size);
|
||||
zassert_equal(diff, 0, NULL);
|
||||
/* context tagged */
|
||||
tag_number = i;
|
||||
apdu_len = bacnet_octet_string_buffer_context_encode(
|
||||
apdu, sizeof(apdu), tag_number, buffer, buffer_size);
|
||||
null_len = bacnet_octet_string_buffer_context_encode(
|
||||
NULL, sizeof(apdu), tag_number, buffer, buffer_size);
|
||||
zassert_equal(apdu_len, null_len, NULL);
|
||||
null_len = bacnet_octet_string_buffer_context_encode(
|
||||
NULL, 0, tag_number, buffer, buffer_size);
|
||||
zassert_equal(null_len, 0, NULL);
|
||||
test_len = bacnet_octet_string_buffer_context_decode(
|
||||
apdu, apdu_len, tag_number, test_buffer, sizeof(test_buffer));
|
||||
zassert_equal(
|
||||
apdu_len, test_len, "apdu_len=%d test_len=%d i=%d", apdu_len,
|
||||
test_len, i);
|
||||
diff = memcmp(buffer, test_buffer, buffer_size);
|
||||
zassert_equal(diff, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST(bacdcode_tests, test_bacnet_character_string_buffer)
|
||||
#else
|
||||
static void test_bacnet_character_string_buffer(void)
|
||||
#endif
|
||||
{
|
||||
uint8_t apdu[50] = { 0 };
|
||||
char buffer[26] = { 0 }, test_buffer[26] = { 0 };
|
||||
BACNET_CHARACTER_STRING_BUFFER value = { 0 }, test_value = { 0 };
|
||||
int apdu_len = 0, null_len = 0, test_len = 0;
|
||||
uint8_t tag_number = 0;
|
||||
unsigned i;
|
||||
int diff = 0; /* for memcmp */
|
||||
|
||||
value.buffer = buffer;
|
||||
value.buffer_size = sizeof(buffer);
|
||||
value.encoding = CHARACTER_ANSI_X34;
|
||||
test_value.buffer = test_buffer;
|
||||
test_value.buffer_size = sizeof(test_buffer);
|
||||
apdu_len = encode_application_character_string_buffer(apdu, &value);
|
||||
null_len = encode_application_character_string_buffer(NULL, &value);
|
||||
zassert_equal(apdu_len, null_len, NULL);
|
||||
for (i = 0; i < sizeof(buffer); i++) {
|
||||
buffer[i] = 'a' + i;
|
||||
value.buffer_length = 1 + i;
|
||||
/* application tagged */
|
||||
apdu_len = bacnet_character_string_buffer_application_encode(
|
||||
apdu, sizeof(apdu), &value);
|
||||
null_len = bacnet_character_string_buffer_application_encode(
|
||||
NULL, sizeof(apdu), &value);
|
||||
zassert_equal(apdu_len, null_len, NULL);
|
||||
null_len =
|
||||
bacnet_character_string_buffer_application_encode(NULL, 0, &value);
|
||||
zassert_equal(null_len, 0, NULL);
|
||||
test_len = bacnet_character_string_buffer_application_decode(
|
||||
apdu, apdu_len, &test_value);
|
||||
zassert_equal(
|
||||
apdu_len, test_len, "apdu_len=%d test_len=%d i=%d", apdu_len,
|
||||
test_len, i);
|
||||
diff = memcmp(buffer, test_buffer, value.buffer_length);
|
||||
zassert_equal(diff, 0, NULL);
|
||||
zassert_equal(value.buffer_length, test_value.buffer_length, NULL);
|
||||
zassert_equal(value.encoding, test_value.encoding, NULL);
|
||||
/* context tagged */
|
||||
tag_number = i;
|
||||
apdu_len = bacnet_character_string_buffer_context_encode(
|
||||
apdu, sizeof(apdu), tag_number, &value);
|
||||
null_len = bacnet_character_string_buffer_context_encode(
|
||||
NULL, sizeof(apdu), tag_number, &value);
|
||||
zassert_equal(apdu_len, null_len, NULL);
|
||||
null_len = bacnet_character_string_buffer_context_encode(
|
||||
NULL, 0, tag_number, &value);
|
||||
zassert_equal(null_len, 0, NULL);
|
||||
test_len = bacnet_character_string_buffer_context_decode(
|
||||
apdu, apdu_len, tag_number, &test_value);
|
||||
zassert_equal(
|
||||
apdu_len, test_len, "apdu_len=%d test_len=%d i=%d", apdu_len,
|
||||
test_len, i);
|
||||
diff = memcmp(buffer, test_buffer, value.buffer_length);
|
||||
zassert_equal(diff, 0, NULL);
|
||||
zassert_equal(value.buffer_length, test_value.buffer_length, NULL);
|
||||
zassert_equal(value.encoding, test_value.encoding, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST(bacdcode_tests, test_bacnet_constructed_value)
|
||||
#else
|
||||
static void test_bacnet_constructed_value(void)
|
||||
#endif
|
||||
{
|
||||
uint8_t apdu[50] = { 0 };
|
||||
BACNET_CONSTRUCTED_VALUE_TYPE value = { 0 }, test_value = { 0 };
|
||||
int apdu_len = 0, null_len = 0, test_len = 0;
|
||||
uint8_t tag_number = 0;
|
||||
bool status = false;
|
||||
|
||||
value.data_len = BACNET_CONSTRUCTED_VALUE_SIZE;
|
||||
null_len =
|
||||
bacnet_constructed_value_context_encode(NULL, tag_number, &value);
|
||||
apdu_len =
|
||||
bacnet_constructed_value_context_encode(apdu, tag_number, &value);
|
||||
zassert_equal(apdu_len, null_len, NULL);
|
||||
test_len = bacnet_constructed_value_context_decode(
|
||||
apdu, apdu_len, tag_number, &test_value);
|
||||
zassert_equal(apdu_len, test_len, NULL);
|
||||
zassert_equal(value.data_len, test_value.data_len, NULL);
|
||||
status = bacnet_constructed_value_same(&value, &test_value);
|
||||
zassert_true(status, NULL);
|
||||
status = bacnet_constructed_value_copy(&value, &test_value);
|
||||
zassert_true(status, NULL);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST(bacdcode_tests, test_simple_ack)
|
||||
#else
|
||||
static void test_simple_ack(void)
|
||||
#endif
|
||||
{
|
||||
uint8_t apdu[50] = { 0 };
|
||||
uint8_t invoke_id = 1;
|
||||
int len, null_len;
|
||||
|
||||
len = encode_simple_ack(apdu, invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
|
||||
zassert_true(len > 0, NULL);
|
||||
zassert_equal(apdu[0], PDU_TYPE_SIMPLE_ACK, NULL);
|
||||
zassert_equal(apdu[1], invoke_id, NULL);
|
||||
zassert_equal(apdu[2], SERVICE_CONFIRMED_WRITE_PROPERTY, NULL);
|
||||
null_len =
|
||||
encode_simple_ack(NULL, invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
|
||||
zassert_equal(len, null_len, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2009,6 +2533,8 @@ void test_main(void)
|
||||
bacdcode_tests, ztest_unit_test(testBACnetTagEncoder),
|
||||
ztest_unit_test(testBACnetTagCodec),
|
||||
ztest_unit_test(testBACDCodeTags),
|
||||
ztest_unit_test(testBACDCodeNULL),
|
||||
ztest_unit_test(testBACDCodeBoolean),
|
||||
ztest_unit_test(testBACDCodeReal),
|
||||
ztest_unit_test(testBACDCodeUnsigned),
|
||||
ztest_unit_test(testBACnetUnsigned),
|
||||
@@ -2030,12 +2556,17 @@ void test_main(void)
|
||||
ztest_unit_test(testDoubleContextDecodes),
|
||||
ztest_unit_test(testObjectIDContextDecodes),
|
||||
ztest_unit_test(testBitStringContextDecodes),
|
||||
ztest_unit_test(testTimeContextDecodes),
|
||||
ztest_unit_test(testTimeDecodes),
|
||||
ztest_unit_test(testDateContextDecodes),
|
||||
ztest_unit_test(testDateRangeContextDecodes),
|
||||
ztest_unit_test(testOctetStringContextDecodes),
|
||||
ztest_unit_test(testBACDCodeDouble),
|
||||
ztest_unit_test(test_bacnet_array_encode));
|
||||
ztest_unit_test(test_bacnet_array_encode),
|
||||
ztest_unit_test(test_bacnet_enclosed_data_length),
|
||||
ztest_unit_test(test_octet_string_buffer),
|
||||
ztest_unit_test(test_bacnet_character_string_buffer),
|
||||
ztest_unit_test(test_bacnet_constructed_value),
|
||||
ztest_unit_test(test_simple_ack));
|
||||
|
||||
ztest_run_test_suite(bacdcode_tests);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user