Feature/add create object service (#476)
Added BACnet CreateObject and DeleteObject services * refactored codec for BACnetPropertyValue into bacapp module * added unit tests for BACnetPropertyValue * refactored COV and Events to use BACnetPropertyValue codec API * added unit tests for COV * added overrun safe decoders for tag numbers and boolean context * added unit tests and codecs for CreateObject and DeleteObject services * added APDU service handers and senders for CreateObject and DeleteObject services * added command line apps bacco and bacdo for CreateObject and DeleteObject services * added CreateObject and DeleteObject service handling in example server app and device object * added new BACnetRejectReason, Error Class, and BACnetAbortReason enumerations and conversions --------- Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
@@ -696,6 +696,39 @@ bool decode_is_context_tag_with_length(
|
||||
return (bool)(IS_CONTEXT_SPECIFIC(*apdu) && (my_tag_number == tag_number));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the tag is context specific
|
||||
* and matches, as defined in clause 20.2.1.3.2 Constructed
|
||||
* Data. This function returns the tag length as well.
|
||||
*
|
||||
* @param apdu Pointer to the tag begin.
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
* @param tag_number Tag number, that has been decoded before.
|
||||
* @param tag_length Pointer to a variable, or NULL.
|
||||
* Returns the length of the tag in bytes if not NULL.
|
||||
*
|
||||
* @return true on a match, false otherwise.
|
||||
*/
|
||||
bool bacnet_is_context_tag_number(
|
||||
uint8_t *apdu, uint32_t apdu_size, uint8_t tag_number, int *tag_length)
|
||||
{
|
||||
bool match = false;
|
||||
uint8_t my_tag_number = 0;
|
||||
int len;
|
||||
|
||||
len = bacnet_tag_number_decode(apdu, apdu_size, &my_tag_number);
|
||||
if ((len > 0) && (my_tag_number == tag_number)) {
|
||||
if (IS_CONTEXT_SPECIFIC(apdu[0])) {
|
||||
if (tag_length) {
|
||||
*tag_length = len;
|
||||
}
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the tag does match and it
|
||||
* is an opening tag as well.
|
||||
@@ -715,6 +748,39 @@ bool decode_is_opening_tag_number(uint8_t *apdu, uint8_t tag_number)
|
||||
return (bool)(IS_OPENING_TAG(apdu[0]) && (my_tag_number == tag_number));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the tag does match and it
|
||||
* is an opening tag as well.
|
||||
* As defined in clause 20.2.1.3.2 Constructed Data.
|
||||
*
|
||||
* @param apdu Pointer to the tag begin.
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
* @param tag_number Tag number, that has been decoded before.
|
||||
* @param tag_length Pointer to a variable, or NULL.
|
||||
* Returns the length of the tag in bytes if not NULL.
|
||||
*
|
||||
* @return true on a match, false otherwise.
|
||||
*/
|
||||
bool bacnet_is_opening_tag_number(
|
||||
uint8_t *apdu, uint32_t apdu_size, uint8_t tag_number, int *tag_length)
|
||||
{
|
||||
bool match = false;
|
||||
uint8_t my_tag_number = 0;
|
||||
int len;
|
||||
|
||||
len = bacnet_tag_number_decode(apdu, apdu_size, &my_tag_number);
|
||||
if ((len > 0) && (my_tag_number == tag_number)) {
|
||||
if (IS_OPENING_TAG(apdu[0])) {
|
||||
match = true;
|
||||
if (tag_length) {
|
||||
*tag_length = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the tag does match and it
|
||||
* is an closing tag as well.
|
||||
@@ -733,6 +799,39 @@ bool decode_is_closing_tag_number(uint8_t *apdu, uint8_t tag_number)
|
||||
return (bool)(IS_CLOSING_TAG(apdu[0]) && (my_tag_number == tag_number));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the tag does match and it
|
||||
* is a closing tag as well.
|
||||
* As defined in clause 20.2.1.3.2 Constructed Data.
|
||||
*
|
||||
* @param apdu Pointer to the tag begin.
|
||||
* @param apdu_size - number of bytes in the buffer
|
||||
* @param tag_number Tag number, that has been decoded before.
|
||||
* @param tag_length Pointer to a variable, or NULL.
|
||||
* Returns the length of the tag in bytes if not NULL.
|
||||
*
|
||||
* @return true on a match, false otherwise.
|
||||
*/
|
||||
bool bacnet_is_closing_tag_number(
|
||||
uint8_t *apdu, uint32_t apdu_size, uint8_t tag_number, int *tag_length)
|
||||
{
|
||||
bool match = false;
|
||||
uint8_t my_tag_number = 0;
|
||||
int len;
|
||||
|
||||
len = bacnet_tag_number_decode(apdu, apdu_size, &my_tag_number);
|
||||
if ((len > 0) && (my_tag_number == tag_number)) {
|
||||
if (IS_CLOSING_TAG(apdu[0])) {
|
||||
match = true;
|
||||
if (tag_length) {
|
||||
*tag_length = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode an boolean value.
|
||||
* From clause 20.2.3 Encoding of a Boolean Value
|
||||
@@ -852,6 +951,60 @@ bool decode_boolean(uint32_t len_value)
|
||||
return boolean_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decode the Boolean Value when context encoded
|
||||
* From clause 20.2.3 Encoding of a Boolean Value
|
||||
* and 20.2.1 General Rules for Encoding BACnet Tags
|
||||
*
|
||||
* @note The Boolean datatype differs from the other datatypes
|
||||
* in that the encoding of a context-tagged Boolean value is not the
|
||||
* same as the encoding of an application-tagged Boolean value.
|
||||
* This is done so that the application-tagged value may be encoded
|
||||
* in a single octet, without a contents octet. While this same encoding
|
||||
* could have been used for the context-tagged case, doing
|
||||
* so would require that the context be known in order to distinguish
|
||||
* between a length or a value in the length/value/type field.
|
||||
* This was considered to be undesirable.
|
||||
*
|
||||
* @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 boolean_value - decoded Boolean Value, if decoded
|
||||
*
|
||||
* @return number of bytes decoded, zero if wrong tag number,
|
||||
* or #BACNET_STATUS_ERROR (-1) if malformed
|
||||
*/
|
||||
int bacnet_boolean_context_decode(
|
||||
uint8_t *apdu, uint32_t apdu_size, uint8_t tag_value, bool *boolean_value)
|
||||
{
|
||||
int apdu_len = 0;
|
||||
int len = 0;
|
||||
|
||||
if (bacnet_is_context_tag_number(
|
||||
&apdu[apdu_len], apdu_size, tag_value, &len) &&
|
||||
!bacnet_is_closing_tag(&apdu[apdu_len], apdu_size)) {
|
||||
if (len > 0) {
|
||||
apdu_len += len;
|
||||
if (apdu_len < apdu_size) {
|
||||
if (boolean_value) {
|
||||
if (apdu[apdu_len]) {
|
||||
*boolean_value = true;
|
||||
} else {
|
||||
*boolean_value = false;
|
||||
}
|
||||
}
|
||||
apdu_len++;
|
||||
} else {
|
||||
return BACNET_STATUS_ERROR;
|
||||
}
|
||||
} else {
|
||||
return BACNET_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode a Null value.
|
||||
* From clause 20.2.2 Encoding of a Null Value
|
||||
|
||||
Reference in New Issue
Block a user