Add CreateObject and DeleteObject for Octet String and Positive Integer Values (#1246)

* Added CreateObject and DeleteObject for basic Octet String Value and Positive Integer Value objects.

* Changed PositiveInteger present-value datatype to BACNET_UNSIGNED_INTEGER.
This commit is contained in:
Steve Karg
2026-02-26 16:25:03 -06:00
committed by GitHub
parent 24587dfc27
commit 1437a68ce1
13 changed files with 599 additions and 234 deletions
+4
View File
@@ -52,6 +52,8 @@ The git repositories are hosted at the following sites:
### Added
* Added CreateObject and DeleteObject for Octet StringValue and
PositiveInteger Value objects. (#1246)
* Added PROP_TIMER_RUNNING to writable properties and implement
Timer_Running_Set functionality. (#1245)
* Added BACNET_STACK_DEPRECATED_DISABLE guards around all of the deprecated
@@ -150,6 +152,8 @@ The git repositories are hosted at the following sites:
### Changed
* Changed PositiveInteger present-value datatype to
BACNET_UNSIGNED_INTEGER. (#1246)
* Changed BACFILE define dependencies to reflect bacfile-posix.c dependence
since bacfile.c is now independent of any back end file system. (#1227)
* Changed the default BACnet protocol revision to 28 to enable usage of
+1
View File
@@ -46,6 +46,7 @@ SRC = main.c blinkt.c \
$(BACNET_OBJECT_DIR)/nc.c \
$(BACNET_OBJECT_DIR)/netport.c \
$(BACNET_OBJECT_DIR)/osv.c \
$(BACNET_OBJECT_DIR)/piv.c \
$(BACNET_OBJECT_DIR)/program.c \
$(BACNET_OBJECT_DIR)/structured_view.c \
$(BACNET_OBJECT_DIR)/timer.c \
+1
View File
@@ -40,6 +40,7 @@ SRC = main.c \
$(BACNET_OBJECT_DIR)/nc.c \
$(BACNET_OBJECT_DIR)/netport.c \
$(BACNET_OBJECT_DIR)/osv.c \
$(BACNET_OBJECT_DIR)/piv.c \
$(BACNET_OBJECT_DIR)/program.c \
$(BACNET_OBJECT_DIR)/structured_view.c \
$(BACNET_OBJECT_DIR)/timer.c \
+3 -2
View File
@@ -218,7 +218,7 @@ static object_functions_t My_Object_Table[] = {
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */,
OctetString_Value_Create, OctetString_Value_Delete, NULL /* Timer */,
OctetString_Value_Writable_Property_List },
{ OBJECT_POSITIVE_INTEGER_VALUE, PositiveInteger_Value_Init,
PositiveInteger_Value_Count, PositiveInteger_Value_Index_To_Instance,
@@ -229,7 +229,8 @@ static object_functions_t My_Object_Table[] = {
NULL /* Iterator */, NULL /* Value_Lists */, NULL /* COV */,
NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */,
PositiveInteger_Value_Create, PositiveInteger_Value_Delete,
NULL /* Timer */,
PositiveInteger_Value_Writable_Property_List },
{ OBJECT_TIME_VALUE, Time_Value_Init, Time_Value_Count,
Time_Value_Index_To_Instance, Time_Value_Valid_Instance,
+209 -67
View File
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack API */
@@ -17,13 +18,11 @@
#include "bacnet/bactext.h"
#include "bacnet/basic/object/device.h"
#include "bacnet/basic/services.h"
#include "bacnet/basic/sys/keylist.h"
#include "bacnet/basic/object/osv.h"
#ifndef MAX_OCTETSTRING_VALUES
#define MAX_OCTETSTRING_VALUES 4
#endif
static OCTETSTRING_VALUE_DESCR OSV_Descr[MAX_OCTETSTRING_VALUES];
/* Key List for storing object data sorted by instance number */
static OS_Keylist Object_List = NULL;
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int32_t Properties_Required[] = {
@@ -48,6 +47,12 @@ static const int32_t Writable_Properties[] = {
PROP_PRESENT_VALUE, PROP_OUT_OF_SERVICE, -1
};
/**
* @brief Retrieves property identifier lists for Octet String Value objects.
* @param pRequired Optional pointer to receive required property list.
* @param pOptional Optional pointer to receive optional property list.
* @param pProprietary Optional pointer to receive proprietary property list.
*/
void OctetString_Value_Property_Lists(
const int32_t **pRequired,
const int32_t **pOptional,
@@ -80,55 +85,128 @@ void OctetString_Value_Writable_Property_List(
}
}
void OctetString_Value_Init(void)
/**
* @brief Finds an Octet String Value object descriptor by instance number.
* @param object_instance Object instance number.
* @return Pointer to object descriptor, or NULL if not found.
*/
static OCTETSTRING_VALUE_DESCR *
OctetString_Value_Object(uint32_t object_instance)
{
unsigned i;
for (i = 0; i < MAX_OCTETSTRING_VALUES; i++) {
memset(&OSV_Descr[i], 0x00, sizeof(OCTETSTRING_VALUE_DESCR));
octetstring_init(&OSV_Descr[i].Present_Value, NULL, 0);
}
return Keylist_Data(Object_List, object_instance);
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool OctetString_Value_Valid_Instance(uint32_t object_instance)
/**
* @brief Creates an Octet String Value object instance.
* @param object_instance Requested object instance number, or
* BACNET_MAX_INSTANCE for auto-allocation.
* @return Created instance number, or BACNET_MAX_INSTANCE on failure.
*/
uint32_t OctetString_Value_Create(uint32_t object_instance)
{
if (object_instance < MAX_OCTETSTRING_VALUES) {
OCTETSTRING_VALUE_DESCR *pObject = NULL;
int index = 0;
if (!Object_List) {
Object_List = Keylist_Create();
}
if (object_instance > BACNET_MAX_INSTANCE) {
return BACNET_MAX_INSTANCE;
} else if (object_instance == BACNET_MAX_INSTANCE) {
object_instance = Keylist_Next_Empty_Key(Object_List, 1);
}
pObject = OctetString_Value_Object(object_instance);
if (!pObject) {
pObject = calloc(1, sizeof(OCTETSTRING_VALUE_DESCR));
if (!pObject) {
return BACNET_MAX_INSTANCE;
}
index = Keylist_Data_Add(Object_List, object_instance, pObject);
if (index < 0) {
free(pObject);
return BACNET_MAX_INSTANCE;
}
octetstring_init(&pObject->Present_Value, NULL, 0);
pObject->Out_Of_Service = false;
pObject->Event_State = EVENT_STATE_NORMAL;
}
return object_instance;
}
/**
* @brief Deletes an Octet String Value object instance.
* @param object_instance Object instance number.
* @return true if object existed and was deleted.
*/
bool OctetString_Value_Delete(uint32_t object_instance)
{
OCTETSTRING_VALUE_DESCR *pObject = NULL;
pObject = Keylist_Data_Delete(Object_List, object_instance);
if (pObject) {
free(pObject);
return true;
}
return false;
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
/**
* @brief Initializes Octet String Value object instances.
*/
void OctetString_Value_Init(void)
{
#ifdef MAX_OCTETSTRING_VALUES
unsigned i = 0;
for (i = 0; i < MAX_OCTETSTRING_VALUES; i++) {
OctetString_Value_Create(i);
}
#endif
}
/**
* @brief Checks whether an Octet String Value instance exists.
* @param object_instance Object instance number.
* @return true if the instance exists.
*/
bool OctetString_Value_Valid_Instance(uint32_t object_instance)
{
return (OctetString_Value_Object(object_instance) != NULL);
}
/**
* @brief Gets the number of Octet String Value instances.
* @return Number of object instances.
*/
unsigned OctetString_Value_Count(void)
{
return MAX_OCTETSTRING_VALUES;
return Keylist_Count(Object_List);
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
/**
* @brief Maps an object list index to an instance number.
* @param index Zero-based object index.
* @return Object instance number, or UINT32_MAX if index is invalid.
*/
uint32_t OctetString_Value_Index_To_Instance(unsigned index)
{
return index;
KEY key = UINT32_MAX;
Keylist_Index_Key(Object_List, index, &key);
return key;
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
/**
* @brief Maps an instance number to object list index.
* @param object_instance Object instance number.
* @return Zero-based object index.
*/
unsigned OctetString_Value_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_OCTETSTRING_VALUES;
if (object_instance < MAX_OCTETSTRING_VALUES) {
index = object_instance;
}
return index;
return Keylist_Index(Object_List, object_instance);
}
/**
@@ -146,59 +224,119 @@ bool OctetString_Value_Present_Value_Set(
const BACNET_OCTET_STRING *value,
uint8_t priority)
{
unsigned index = 0;
OCTETSTRING_VALUE_DESCR *pObject = NULL;
bool status = false;
(void)priority;
index = OctetString_Value_Instance_To_Index(object_instance);
if (index < MAX_OCTETSTRING_VALUES) {
octetstring_copy(&OSV_Descr[index].Present_Value, value);
pObject = OctetString_Value_Object(object_instance);
if (pObject) {
octetstring_copy(&pObject->Present_Value, value);
status = true;
}
return status;
}
/**
* @brief Gets the present value for an Octet String Value object.
* @param object_instance Object instance number.
* @return Pointer to present value, or NULL if object does not exist.
*/
BACNET_OCTET_STRING *OctetString_Value_Present_Value(uint32_t object_instance)
{
BACNET_OCTET_STRING *value = NULL;
unsigned index = 0;
OCTETSTRING_VALUE_DESCR *pObject = NULL;
index = OctetString_Value_Instance_To_Index(object_instance);
if (index < MAX_OCTETSTRING_VALUES) {
value = &OSV_Descr[index].Present_Value;
pObject = OctetString_Value_Object(object_instance);
if (pObject) {
value = &pObject->Present_Value;
}
return value;
}
/* note: the object name must be unique within this device */
/**
* @brief Gets the object name for an Octet String Value object.
* @param object_instance Object instance number.
* @param object_name Pointer to string storage for resulting object name.
* @return true if object name is generated successfully.
*/
bool OctetString_Value_Object_Name(
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
{
char text[32] = "";
bool status = false;
OCTETSTRING_VALUE_DESCR *pObject = NULL;
if (object_instance < MAX_OCTETSTRING_VALUES) {
pObject = OctetString_Value_Object(object_instance);
if (pObject) {
if (pObject->Object_Name) {
status =
characterstring_init_ansi(object_name, pObject->Object_Name);
} else {
snprintf(
text, sizeof(text), "OCTETSTRING VALUE %lu",
(unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text);
}
}
return status;
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
/**
* @brief For a given object instance-number, sets the object-name
* Note that the object name must be unique within this device.
* @param object_instance - object-instance number of the object
* @param new_name - holds the object-name to be set
* @return true if object-name was set
*/
bool OctetString_Value_Name_Set(uint32_t object_instance, const char *new_name)
{
bool status = false; /* return value */
OCTETSTRING_VALUE_DESCR *pObject;
pObject = OctetString_Value_Object(object_instance);
if (pObject) {
status = true;
pObject->Object_Name = new_name;
}
return status;
}
/**
* @brief Return the object name C string
* @param object_instance [in] BACnet object instance number
* @return object name or NULL if not found
*/
const char *OctetString_Value_Name_ASCII(uint32_t object_instance)
{
const char *name = NULL;
OCTETSTRING_VALUE_DESCR *pObject;
pObject = OctetString_Value_Object(object_instance);
if (pObject) {
name = pObject->Object_Name;
}
return name;
}
/**
* @brief Encodes a read-property response for an Octet String Value object.
* @param rpdata Read property request/response context.
* @return Encoded APDU length, or BACNET_STATUS_ERROR on error.
*/
int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_OCTET_STRING *real_value = NULL;
unsigned object_index = 0;
bool state = false;
uint8_t *apdu = NULL;
OCTETSTRING_VALUE_DESCR *CurrentAV;
OCTETSTRING_VALUE_DESCR *pObject = NULL;
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
@@ -207,10 +345,10 @@ int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
apdu = rpdata->application_data;
object_index = OctetString_Value_Instance_To_Index(rpdata->object_instance);
if (object_index < MAX_OCTETSTRING_VALUES) {
CurrentAV = &OSV_Descr[object_index];
} else {
pObject = OctetString_Value_Object(rpdata->object_instance);
if (!pObject) {
rpdata->error_class = ERROR_CLASS_OBJECT;
rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT;
return BACNET_STATUS_ERROR;
}
@@ -246,7 +384,7 @@ int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(
&bit_string, STATUS_FLAG_OUT_OF_SERVICE,
CurrentAV->Out_Of_Service);
pObject->Out_Of_Service);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
@@ -257,7 +395,7 @@ int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
break;
case PROP_OUT_OF_SERVICE:
state = CurrentAV->Out_Of_Service;
state = pObject->Out_Of_Service;
apdu_len = encode_application_boolean(&apdu[0], state);
break;
default:
@@ -270,14 +408,24 @@ int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
return apdu_len;
}
/* returns true if successful */
/**
* @brief Processes a write-property request for an Octet String Value object.
* @param wp_data Write property request/response context.
* @return true if property write is successful.
*/
bool OctetString_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
unsigned int object_index = 0;
int len = 0;
BACNET_APPLICATION_DATA_VALUE value = { 0 };
OCTETSTRING_VALUE_DESCR *CurrentAV;
OCTETSTRING_VALUE_DESCR *pObject = NULL;
if (wp_data == NULL) {
return false;
}
if (wp_data->application_data_len == 0) {
return false;
}
/* decode the some of the request */
len = bacapp_decode_application_data(
@@ -289,11 +437,10 @@ bool OctetString_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
return false;
}
object_index =
OctetString_Value_Instance_To_Index(wp_data->object_instance);
if (object_index < MAX_OCTETSTRING_VALUES) {
CurrentAV = &OSV_Descr[object_index];
} else {
pObject = OctetString_Value_Object(wp_data->object_instance);
if (!pObject) {
wp_data->error_class = ERROR_CLASS_OBJECT;
wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT;
return false;
}
@@ -326,7 +473,7 @@ bool OctetString_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
status = write_property_type_valid(
wp_data, &value, BACNET_APPLICATION_TAG_BOOLEAN);
if (status) {
CurrentAV->Out_Of_Service = value.type.Boolean;
pObject->Out_Of_Service = value.type.Boolean;
}
break;
default:
@@ -344,8 +491,3 @@ bool OctetString_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
return status;
}
void OctetString_Value_Intrinsic_Reporting(uint32_t object_instance)
{
(void)object_instance;
}
+10 -2
View File
@@ -24,6 +24,7 @@ typedef struct octetstring_value_descr {
unsigned Event_State : 3;
bool Out_Of_Service;
BACNET_OCTET_STRING Present_Value;
const char *Object_Name;
} OCTETSTRING_VALUE_DESCR;
BACNET_STACK_EXPORT
@@ -47,6 +48,10 @@ unsigned OctetString_Value_Instance_To_Index(uint32_t object_instance);
BACNET_STACK_EXPORT
bool OctetString_Value_Object_Name(
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name);
BACNET_STACK_EXPORT
bool OctetString_Value_Name_Set(uint32_t object_instance, const char *new_name);
BACNET_STACK_EXPORT
const char *OctetString_Value_Name_ASCII(uint32_t object_instance);
BACNET_STACK_EXPORT
int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata);
@@ -80,8 +85,11 @@ bool OctetString_Value_Out_Of_Service(uint32_t instance);
BACNET_STACK_EXPORT
void OctetString_Value_Out_Of_Service_Set(uint32_t instance, bool oos_flag);
/* note: header of Intrinsic_Reporting function is required
even when INTRINSIC_REPORTING is not defined */
BACNET_STACK_EXPORT
uint32_t OctetString_Value_Create(uint32_t object_instance);
BACNET_STACK_EXPORT
bool OctetString_Value_Delete(uint32_t object_instance);
BACNET_STACK_EXPORT
void OctetString_Value_Intrinsic_Reporting(uint32_t object_instance);
+206 -76
View File
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack API */
@@ -17,13 +18,13 @@
#include "bacnet/bactext.h"
#include "bacnet/basic/object/device.h"
#include "bacnet/basic/services.h"
#include "bacnet/basic/sys/keylist.h"
#include "bacnet/basic/object/piv.h"
#ifndef MAX_POSITIVEINTEGER_VALUES
#define MAX_POSITIVEINTEGER_VALUES 4
#endif
static POSITIVEINTEGER_VALUE_DESCR PIV_Descr[MAX_POSITIVEINTEGER_VALUES];
/* Key List for storing object data sorted by instance number */
static OS_Keylist Object_List = NULL;
/* common object type */
static const BACNET_OBJECT_TYPE Object_Type = OBJECT_POSITIVE_INTEGER_VALUE;
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int32_t Properties_Required[] = {
@@ -97,56 +98,131 @@ void PositiveInteger_Value_Writable_Property_List(
}
/**
* @brief Initializes the Positive Integer Value objects
* @brief Finds a Positive Integer Value object descriptor by instance number.
* @param object_instance Object instance number.
* @return Pointer to object descriptor, or NULL if not found.
*/
void PositiveInteger_Value_Init(void)
static POSITIVEINTEGER_VALUE_DESCR *
PositiveInteger_Value_Object(uint32_t object_instance)
{
unsigned i;
for (i = 0; i < MAX_POSITIVEINTEGER_VALUES; i++) {
memset(&PIV_Descr[i], 0x00, sizeof(POSITIVEINTEGER_VALUE_DESCR));
}
return Keylist_Data(Object_List, object_instance);
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool PositiveInteger_Value_Valid_Instance(uint32_t object_instance)
/**
* @brief Creates a Positive Integer Value object instance.
* @param object_instance Requested object instance number, or
* BACNET_MAX_INSTANCE for auto-allocation.
* @return Created instance number, or BACNET_MAX_INSTANCE on failure.
*/
uint32_t PositiveInteger_Value_Create(uint32_t object_instance)
{
if (object_instance < MAX_POSITIVEINTEGER_VALUES) {
POSITIVEINTEGER_VALUE_DESCR *pObject = NULL;
int index = 0;
if (!Object_List) {
Object_List = Keylist_Create();
}
if (object_instance > BACNET_MAX_INSTANCE) {
return BACNET_MAX_INSTANCE;
} else if (object_instance == BACNET_MAX_INSTANCE) {
object_instance = Keylist_Next_Empty_Key(Object_List, 1);
}
pObject = PositiveInteger_Value_Object(object_instance);
if (!pObject) {
pObject = calloc(1, sizeof(POSITIVEINTEGER_VALUE_DESCR));
if (!pObject) {
return BACNET_MAX_INSTANCE;
}
index = Keylist_Data_Add(Object_List, object_instance, pObject);
if (index < 0) {
free(pObject);
return BACNET_MAX_INSTANCE;
}
pObject->Out_Of_Service = false;
pObject->Present_Value = 0;
pObject->Units = UNITS_NO_UNITS;
pObject->Object_Name = NULL;
}
return object_instance;
}
/**
* @brief Deletes a Positive Integer Value object instance.
* @param object_instance Object instance number.
* @return true if object existed and was deleted.
*/
bool PositiveInteger_Value_Delete(uint32_t object_instance)
{
POSITIVEINTEGER_VALUE_DESCR *pObject = NULL;
pObject = Keylist_Data_Delete(Object_List, object_instance);
if (pObject) {
free(pObject);
return true;
}
return false;
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
/**
* @brief Initializes the Positive Integer Value objects
*/
void PositiveInteger_Value_Init(void)
{
#ifdef MAX_POSITIVEINTEGER_VALUES
unsigned i = 0;
if (!Object_List) {
Object_List = Keylist_Create();
}
for (i = 0; i < MAX_POSITIVEINTEGER_VALUES; i++) {
PositiveInteger_Value_Create(i);
}
#endif
}
/**
* @brief Checks whether a Positive Integer Value instance exists.
* @param object_instance Object instance number.
* @return true if the instance exists.
*/
bool PositiveInteger_Value_Valid_Instance(uint32_t object_instance)
{
return (PositiveInteger_Value_Object(object_instance) != NULL);
}
/**
* @brief Gets the number of Positive Integer Value instances.
* @return Number of object instances.
*/
unsigned PositiveInteger_Value_Count(void)
{
return MAX_POSITIVEINTEGER_VALUES;
return Keylist_Count(Object_List);
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
/**
* @brief Maps an object list index to an instance number.
* @param index Zero-based object index.
* @return Object instance number, or UINT32_MAX if index is invalid.
*/
uint32_t PositiveInteger_Value_Index_To_Instance(unsigned index)
{
return index;
KEY key = UINT32_MAX;
Keylist_Index_Key(Object_List, index, &key);
return key;
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
/**
* @brief Maps an instance number to object list index.
* @param object_instance Object instance number.
* @return Zero-based object index.
*/
unsigned PositiveInteger_Value_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_POSITIVEINTEGER_VALUES;
if (object_instance < MAX_POSITIVEINTEGER_VALUES) {
index = object_instance;
}
return index;
return Keylist_Index(Object_List, object_instance);
}
/**
@@ -160,51 +236,109 @@ unsigned PositiveInteger_Value_Instance_To_Index(uint32_t object_instance)
* @return true if values are within range and present-value is set.
*/
bool PositiveInteger_Value_Present_Value_Set(
uint32_t object_instance, uint32_t value, uint8_t priority)
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value, uint8_t priority)
{
unsigned index = 0;
POSITIVEINTEGER_VALUE_DESCR *pObject = NULL;
bool status = false;
(void)priority;
index = PositiveInteger_Value_Instance_To_Index(object_instance);
if (index < MAX_POSITIVEINTEGER_VALUES) {
PIV_Descr[index].Present_Value = value;
pObject = PositiveInteger_Value_Object(object_instance);
if (pObject) {
pObject->Present_Value = value;
status = true;
}
return status;
}
uint32_t PositiveInteger_Value_Present_Value(uint32_t object_instance)
/**
* @brief Gets the present value for a Positive Integer Value object.
* @param object_instance Object instance number.
* @return Present value, or 0 if object does not exist.
*/
BACNET_UNSIGNED_INTEGER
PositiveInteger_Value_Present_Value(uint32_t object_instance)
{
uint32_t value = 0;
unsigned index = 0;
BACNET_UNSIGNED_INTEGER value = 0;
POSITIVEINTEGER_VALUE_DESCR *pObject = NULL;
index = PositiveInteger_Value_Instance_To_Index(object_instance);
if (index < MAX_POSITIVEINTEGER_VALUES) {
value = PIV_Descr[index].Present_Value;
pObject = PositiveInteger_Value_Object(object_instance);
if (pObject) {
value = pObject->Present_Value;
}
return value;
}
/* note: the object name must be unique within this device */
/**
* @brief Gets the object name for a Positive Integer Value object.
* @param object_instance Object instance number.
* @param object_name Pointer to string storage for resulting object name.
* @return true if object name is generated successfully.
*/
bool PositiveInteger_Value_Object_Name(
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
{
char text[32] = "";
char text[48] = "";
bool status = false;
POSITIVEINTEGER_VALUE_DESCR *pObject = NULL;
if (object_instance < MAX_POSITIVEINTEGER_VALUES) {
pObject = PositiveInteger_Value_Object(object_instance);
if (pObject) {
if (pObject->Object_Name) {
status =
characterstring_init_ansi(object_name, pObject->Object_Name);
} else {
snprintf(
text, sizeof(text), "POSITIVEINTEGER VALUE %lu",
(unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text);
}
}
return status;
}
/**
* @brief For a given object instance-number, sets the object-name
* Note that the object name must be unique within this device.
* @param object_instance - object-instance number of the object
* @param new_name - holds the object-name to be set
* @return true if object-name was set
*/
bool PositiveInteger_Value_Name_Set(
uint32_t object_instance, const char *new_name)
{
bool status = false; /* return value */
POSITIVEINTEGER_VALUE_DESCR *pObject;
pObject = PositiveInteger_Value_Object(object_instance);
if (pObject) {
status = true;
pObject->Object_Name = new_name;
}
return status;
}
/**
* @brief Return the object name C string
* @param object_instance [in] BACnet object instance number
* @return object name or NULL if not found
*/
const char *PositiveInteger_Value_Name_ASCII(uint32_t object_instance)
{
const char *name = NULL;
POSITIVEINTEGER_VALUE_DESCR *pObject;
pObject = PositiveInteger_Value_Object(object_instance);
if (pObject) {
name = pObject->Object_Name;
}
return name;
}
/**
* ReadProperty handler for this object. For the given ReadProperty
* data, the application_data is loaded or the error flags are set.
@@ -220,10 +354,9 @@ int PositiveInteger_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
unsigned object_index = 0;
bool state = false;
uint8_t *apdu = NULL;
POSITIVEINTEGER_VALUE_DESCR *CurrentAV;
POSITIVEINTEGER_VALUE_DESCR *pObject = NULL;
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
@@ -232,19 +365,17 @@ int PositiveInteger_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
apdu = rpdata->application_data;
object_index =
PositiveInteger_Value_Instance_To_Index(rpdata->object_instance);
if (object_index < MAX_POSITIVEINTEGER_VALUES) {
CurrentAV = &PIV_Descr[object_index];
} else {
pObject = PositiveInteger_Value_Object(rpdata->object_instance);
if (!pObject) {
rpdata->error_class = ERROR_CLASS_OBJECT;
rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT;
return BACNET_STATUS_ERROR;
}
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_POSITIVE_INTEGER_VALUE,
rpdata->object_instance);
&apdu[0], Object_Type, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
@@ -255,8 +386,7 @@ int PositiveInteger_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(
&apdu[0], OBJECT_POSITIVE_INTEGER_VALUE);
apdu_len = encode_application_enumerated(&apdu[0], Object_Type);
break;
case PROP_PRESENT_VALUE:
@@ -272,14 +402,14 @@ int PositiveInteger_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(
&bit_string, STATUS_FLAG_OUT_OF_SERVICE,
CurrentAV->Out_Of_Service);
pObject->Out_Of_Service);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(
&apdu[0], (uint32_t)CurrentAV->Units);
&apdu[0], (uint32_t)pObject->Units);
break;
/* BACnet Testing Observed Incident oi00109
Positive Integer Value / Units returned wrong datatype -
@@ -291,7 +421,7 @@ int PositiveInteger_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
parties. Say 6 months -> September 2016 */
case PROP_OUT_OF_SERVICE:
state = CurrentAV->Out_Of_Service;
state = pObject->Out_Of_Service;
apdu_len = encode_application_boolean(&apdu[0], state);
break;
default:
@@ -316,10 +446,16 @@ int PositiveInteger_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
bool PositiveInteger_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
unsigned int object_index = 0;
int len = 0;
BACNET_APPLICATION_DATA_VALUE value = { 0 };
POSITIVEINTEGER_VALUE_DESCR *CurrentAV;
POSITIVEINTEGER_VALUE_DESCR *pObject = NULL;
if (wp_data == NULL) {
return false;
}
if (wp_data->application_data_len == 0) {
return false;
}
/* decode the some of the request */
len = bacapp_decode_application_data(
@@ -331,11 +467,10 @@ bool PositiveInteger_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
return false;
}
object_index =
PositiveInteger_Value_Instance_To_Index(wp_data->object_instance);
if (object_index < MAX_POSITIVEINTEGER_VALUES) {
CurrentAV = &PIV_Descr[object_index];
} else {
pObject = PositiveInteger_Value_Object(wp_data->object_instance);
if (!pObject) {
wp_data->error_class = ERROR_CLASS_OBJECT;
wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT;
return false;
}
switch (wp_data->object_property) {
@@ -366,7 +501,7 @@ bool PositiveInteger_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
status = write_property_type_valid(
wp_data, &value, BACNET_APPLICATION_TAG_BOOLEAN);
if (status) {
CurrentAV->Out_Of_Service = value.type.Boolean;
pObject->Out_Of_Service = value.type.Boolean;
}
break;
case PROP_UNITS:
@@ -374,7 +509,7 @@ bool PositiveInteger_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
wp_data, &value, BACNET_APPLICATION_TAG_ENUMERATED);
if (status) {
if (value.type.Enumerated <= UINT16_MAX) {
CurrentAV->Units = (uint16_t)value.type.Enumerated;
pObject->Units = (uint16_t)value.type.Enumerated;
} else {
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
@@ -397,8 +532,3 @@ bool PositiveInteger_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
return status;
}
void PositiveInteger_Value_Intrinsic_Reporting(uint32_t object_instance)
{
(void)object_instance;
}
+15 -5
View File
@@ -22,8 +22,9 @@ extern "C" {
typedef struct positiveinteger_value_descr {
bool Out_Of_Service : 1;
uint32_t Present_Value;
BACNET_UNSIGNED_INTEGER Present_Value;
BACNET_ENGINEERING_UNITS Units;
const char *Object_Name;
} POSITIVEINTEGER_VALUE_DESCR;
BACNET_STACK_EXPORT
@@ -46,6 +47,11 @@ unsigned PositiveInteger_Value_Instance_To_Index(uint32_t object_instance);
BACNET_STACK_EXPORT
bool PositiveInteger_Value_Object_Name(
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name);
BACNET_STACK_EXPORT
bool PositiveInteger_Value_Name_Set(
uint32_t object_instance, const char *new_name);
BACNET_STACK_EXPORT
const char *PositiveInteger_Value_Name_ASCII(uint32_t object_instance);
BACNET_STACK_EXPORT
int PositiveInteger_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata);
@@ -55,9 +61,10 @@ bool PositiveInteger_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data);
BACNET_STACK_EXPORT
bool PositiveInteger_Value_Present_Value_Set(
uint32_t object_instance, uint32_t value, uint8_t priority);
uint32_t object_instance, BACNET_UNSIGNED_INTEGER value, uint8_t priority);
BACNET_STACK_EXPORT
uint32_t PositiveInteger_Value_Present_Value(uint32_t object_instance);
BACNET_UNSIGNED_INTEGER
PositiveInteger_Value_Present_Value(uint32_t object_instance);
BACNET_STACK_EXPORT
bool PositiveInteger_Value_Change_Of_Value(uint32_t instance);
@@ -78,8 +85,11 @@ bool PositiveInteger_Value_Out_Of_Service(uint32_t instance);
BACNET_STACK_EXPORT
void PositiveInteger_Value_Out_Of_Service_Set(uint32_t instance, bool oos_flag);
/* note: header of Intrinsic_Reporting function is required
even when INTRINSIC_REPORTING is not defined */
BACNET_STACK_EXPORT
uint32_t PositiveInteger_Value_Create(uint32_t object_instance);
BACNET_STACK_EXPORT
bool PositiveInteger_Value_Delete(uint32_t object_instance);
BACNET_STACK_EXPORT
void PositiveInteger_Value_Intrinsic_Reporting(uint32_t object_instance);
+52
View File
@@ -45,6 +45,8 @@
#include "bacnet/basic/object/ms-input.h"
#include "bacnet/basic/object/mso.h"
#include "bacnet/basic/object/msv.h"
#include "bacnet/basic/object/osv.h"
#include "bacnet/basic/object/piv.h"
#include "bacnet/basic/object/schedule.h"
#include "bacnet/basic/object/structured_view.h"
#include "bacnet/basic/object/trendlog.h"
@@ -122,6 +124,7 @@
defined(CONFIG_BACNET_BASIC_OBJECT_NETWORK_PORT) || \
defined(CONFIG_BACNET_BASIC_OBJECT_CALENDAR) || \
defined(CONFIG_BACNET_BASIC_OBJECT_INTEGER_VALUE) || \
defined(CONFIG_BACNET_BASIC_OBJECT_POSITIVE_INTEGER_VALUE) || \
defined(CONFIG_BACNET_BASIC_OBJECT_LIFE_SAFETY_POINT) || \
defined(CONFIG_BACNET_BASIC_OBJECT_LIFE_SAFETY_ZONE) || \
defined(CONFIG_BACNET_BASIC_OBJECT_LIGHTING_OUTPUT) || \
@@ -133,6 +136,7 @@
defined(CONFIG_BACNET_BASIC_OBJECT_FILE) || \
defined(CONFIG_BACNET_BASIC_OBJECT_STRUCTURED_VIEW) || \
defined(CONFIG_BACNET_BASIC_OBJECT_BITSTRING_VALUE) || \
defined(CONFIG_BACNET_BASIC_OBJECT_OCTETSTRING_VALUE) || \
defined(CONFIG_BACNET_BASIC_OBJECT_TIME_VALUE) || \
defined(CONFIG_BACNET_BASIC_OBJECT_TIMER) || \
defined(CONFIG_BACNET_BASIC_OBJECT_LOOP) || \
@@ -155,6 +159,7 @@
#define CONFIG_BACNET_BASIC_OBJECT_NETWORK_PORT
#define CONFIG_BACNET_BASIC_OBJECT_CALENDAR
#define CONFIG_BACNET_BASIC_OBJECT_INTEGER_VALUE
#define CONFIG_BACNET_BASIC_OBJECT_POSITIVE_INTEGER_VALUE
#define CONFIG_BACNET_BASIC_OBJECT_LIFE_SAFETY_POINT
#define CONFIG_BACNET_BASIC_OBJECT_LIFE_SAFETY_ZONE
#define CONFIG_BACNET_BASIC_OBJECT_LIGHTING_OUTPUT
@@ -166,6 +171,7 @@
#define CONFIG_BACNET_BASIC_OBJECT_FILE
#define CONFIG_BACNET_BASIC_OBJECT_STRUCTURED_VIEW
#define CONFIG_BACNET_BASIC_OBJECT_BITSTRING_VALUE
#define CONFIG_BACNET_BASIC_OBJECT_OCTETSTRING_VALUE
#define CONFIG_BACNET_BASIC_OBJECT_TIME_VALUE
#define CONFIG_BACNET_BASIC_OBJECT_TIMER
#define CONFIG_BACNET_BASIC_OBJECT_LOOP
@@ -813,6 +819,52 @@ static object_functions_t My_Object_Table[] = {
NULL /* Timer */,
CharacterString_Value_Writable_Property_List },
#endif
#if defined(CONFIG_BACNET_BASIC_OBJECT_OCTETSTRING_VALUE)
{ OBJECT_OCTETSTRING_VALUE,
OctetString_Value_Init,
OctetString_Value_Count,
OctetString_Value_Index_To_Instance,
OctetString_Value_Valid_Instance,
OctetString_Value_Object_Name,
OctetString_Value_Read_Property,
OctetString_Value_Write_Property,
OctetString_Value_Property_Lists,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */,
NULL /* Remove_List_Element */,
OctetString_Value_Create,
OctetString_Value_Delete,
NULL /* Timer */,
OctetString_Value_Writable_Property_List },
#endif
#if defined(CONFIG_BACNET_BASIC_OBJECT_POSITIVE_INTEGER_VALUE)
{ OBJECT_POSITIVE_INTEGER_VALUE,
PositiveInteger_Value_Init,
PositiveInteger_Value_Count,
PositiveInteger_Value_Index_To_Instance,
PositiveInteger_Value_Valid_Instance,
PositiveInteger_Value_Object_Name,
PositiveInteger_Value_Read_Property,
PositiveInteger_Value_Write_Property,
PositiveInteger_Value_Property_Lists,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */,
NULL /* Remove_List_Element */,
PositiveInteger_Value_Create,
PositiveInteger_Value_Delete,
NULL /* Timer */,
PositiveInteger_Value_Writable_Property_List },
#endif
#if defined(CONFIG_BACNET_BASIC_OBJECT_TIME_VALUE)
{ OBJECT_TIME_VALUE,
Time_Value_Init,
+4 -1
View File
@@ -27,6 +27,7 @@ add_compile_definitions(
include_directories(
${SRC_DIR}
${TST_DIR}/bacnet/basic/object/test
${TST_DIR}/ztest/include
)
@@ -46,9 +47,10 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/bacreal.c
${SRC_DIR}/bacnet/bacstr.c
${SRC_DIR}/bacnet/bactext.c
${SRC_DIR}/bacnet/basic/sys/bigend.c
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/bigend.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/basic/sys/keylist.c
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
@@ -66,6 +68,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/secure_connect.c
# Test and test library files
./src/main.c
${TST_DIR}/bacnet/basic/object/test/property_test.c
${ZTST_DIR}/ztest_mock.c
${ZTST_DIR}/ztest.c
)
+40 -38
View File
@@ -9,6 +9,7 @@
#include <zephyr/ztest.h>
#include <bacnet/basic/object/osv.h>
#include <bacnet/bactext.h>
#include <property_test.h>
/**
* @addtogroup bacnet_tests
@@ -24,46 +25,47 @@ ZTEST(osv_tests, testOctetString_Value)
static void testOctetString_Value(void)
#endif
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0, test_len = 0;
BACNET_READ_PROPERTY_DATA rpdata = { 0 };
BACNET_APPLICATION_DATA_VALUE value = { 0 };
const int32_t *required_property = NULL;
const uint32_t instance = 1;
bool status = false;
unsigned count = 0, index = 0;
uint32_t object_instance = 0, test_object_instance = 0;
const int32_t *writable_properties = NULL;
const int32_t skip_fail_property_list[] = { -1 };
OctetString_Value_Init();
rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_OCTETSTRING_VALUE;
rpdata.object_instance = instance;
rpdata.array_index = BACNET_ARRAY_ALL;
OctetString_Value_Property_Lists(&required_property, NULL, NULL);
while ((*required_property) >= 0) {
rpdata.object_property = *required_property;
len = OctetString_Value_Read_Property(&rpdata);
zassert_true(len >= 0, NULL);
if (len >= 0) {
test_len = bacapp_decode_known_property(
rpdata.application_data, len, &value, rpdata.object_type,
rpdata.object_property);
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_equal(len, test_len, NULL);
} else {
printf(
"property '%s': failed to read!\n",
bactext_property_name(rpdata.object_property));
}
required_property++;
}
test_object_instance = OctetString_Value_Create(BACNET_MAX_INSTANCE + 1);
zassert_equal(test_object_instance, BACNET_MAX_INSTANCE, NULL);
test_object_instance = OctetString_Value_Create(BACNET_MAX_INSTANCE);
zassert_not_equal(test_object_instance, BACNET_MAX_INSTANCE, NULL);
status = OctetString_Value_Delete(test_object_instance);
zassert_true(status, NULL);
count = OctetString_Value_Count();
zassert_true(count == 0, NULL);
test_object_instance = OctetString_Value_Create(object_instance);
zassert_equal(test_object_instance, object_instance, NULL);
status = OctetString_Value_Valid_Instance(object_instance);
zassert_true(status, NULL);
status = OctetString_Value_Valid_Instance(object_instance - 1);
zassert_false(status, NULL);
index = OctetString_Value_Instance_To_Index(object_instance);
zassert_equal(index, 0, NULL);
test_object_instance = OctetString_Value_Index_To_Instance(index);
zassert_equal(object_instance, test_object_instance, NULL);
count = OctetString_Value_Count();
zassert_true(count == 1, NULL);
test_object_instance = OctetString_Value_Index_To_Instance(0);
zassert_equal(object_instance, test_object_instance, NULL);
bacnet_object_properties_read_write_test(
OBJECT_OCTETSTRING_VALUE, object_instance,
OctetString_Value_Property_Lists, OctetString_Value_Read_Property,
OctetString_Value_Write_Property, skip_fail_property_list);
bacnet_object_name_ascii_test(
object_instance, OctetString_Value_Name_Set,
OctetString_Value_Name_ASCII);
OctetString_Value_Writable_Property_List(
object_instance, &writable_properties);
zassert_not_null(writable_properties, NULL);
status = OctetString_Value_Delete(object_instance);
zassert_true(status, NULL);
}
/**
* @}
+4 -1
View File
@@ -27,6 +27,7 @@ add_compile_definitions(
include_directories(
${SRC_DIR}
${TST_DIR}/bacnet/basic/object/test
${TST_DIR}/ztest/include
)
@@ -46,9 +47,10 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/bacreal.c
${SRC_DIR}/bacnet/bacstr.c
${SRC_DIR}/bacnet/bactext.c
${SRC_DIR}/bacnet/basic/sys/bigend.c
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/basic/sys/bigend.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/basic/sys/keylist.c
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
@@ -66,6 +68,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/secure_connect.c
# Test and test library files
./src/main.c
${TST_DIR}/bacnet/basic/object/test/property_test.c
${ZTST_DIR}/ztest_mock.c
${ZTST_DIR}/ztest.c
)
+42 -34
View File
@@ -10,6 +10,7 @@
#include <zephyr/ztest.h>
#include <bacnet/basic/object/piv.h>
#include <bacnet/bactext.h>
#include <property_test.h>
/**
* @addtogroup bacnet_tests
@@ -25,42 +26,49 @@ ZTEST(piv_tests, testPositiveInteger_Value)
static void testPositiveInteger_Value(void)
#endif
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0, test_len = 0;
BACNET_READ_PROPERTY_DATA rpdata = { 0 };
BACNET_APPLICATION_DATA_VALUE value = { 0 };
const int32_t *required_property = NULL;
const uint32_t instance = 1;
bool status = false;
unsigned count = 0, index = 0;
uint32_t object_instance = 0, test_object_instance = 0;
const int32_t *writable_properties = NULL;
const int32_t skip_fail_property_list[] = { -1 };
PositiveInteger_Value_Init();
rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_POSITIVE_INTEGER_VALUE;
rpdata.object_instance = instance;
rpdata.array_index = BACNET_ARRAY_ALL;
PositiveInteger_Value_Property_Lists(&required_property, NULL, NULL);
while ((*required_property) >= 0) {
rpdata.object_property = *required_property;
len = PositiveInteger_Value_Read_Property(&rpdata);
zassert_true(len >= 0, NULL);
if (len >= 0) {
test_len = bacapp_decode_known_property(
rpdata.application_data, len, &value, rpdata.object_type,
rpdata.object_property);
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_equal(len, test_len, NULL);
}
required_property++;
}
test_object_instance =
PositiveInteger_Value_Create(BACNET_MAX_INSTANCE + 1);
zassert_equal(test_object_instance, BACNET_MAX_INSTANCE, NULL);
test_object_instance = PositiveInteger_Value_Create(BACNET_MAX_INSTANCE);
zassert_not_equal(test_object_instance, BACNET_MAX_INSTANCE, NULL);
status = PositiveInteger_Value_Delete(test_object_instance);
zassert_true(status, NULL);
count = PositiveInteger_Value_Count();
zassert_true(count == 0, NULL);
test_object_instance = PositiveInteger_Value_Create(object_instance);
zassert_equal(test_object_instance, object_instance, NULL);
status = PositiveInteger_Value_Valid_Instance(object_instance);
zassert_true(status, NULL);
status = PositiveInteger_Value_Valid_Instance(object_instance - 1);
zassert_false(status, NULL);
index = PositiveInteger_Value_Instance_To_Index(object_instance);
zassert_equal(index, 0, NULL);
test_object_instance = PositiveInteger_Value_Index_To_Instance(index);
zassert_equal(object_instance, test_object_instance, NULL);
count = PositiveInteger_Value_Count();
zassert_true(count == 1, NULL);
test_object_instance = PositiveInteger_Value_Index_To_Instance(0);
zassert_equal(object_instance, test_object_instance, NULL);
bacnet_object_properties_read_write_test(
OBJECT_POSITIVE_INTEGER_VALUE, object_instance,
PositiveInteger_Value_Property_Lists,
PositiveInteger_Value_Read_Property,
PositiveInteger_Value_Write_Property, skip_fail_property_list);
bacnet_object_name_ascii_test(
object_instance, PositiveInteger_Value_Name_Set,
PositiveInteger_Value_Name_ASCII);
PositiveInteger_Value_Writable_Property_List(
object_instance, &writable_properties);
zassert_not_null(writable_properties, NULL);
status = PositiveInteger_Value_Delete(object_instance);
zassert_true(status, NULL);
}
/**
* @}