Added post-write notifications for channel, timer, and loop objects. (#1204)
This commit is contained in:
@@ -32,6 +32,7 @@ The git repositories are hosted at the following sites:
|
||||
|
||||
### Added
|
||||
|
||||
* Added post-write notifications for channel, timer, and loop objects. (#1204)
|
||||
* Added device WriteProperty callbacks for Timer object in example device
|
||||
objects implementations. (#1203)
|
||||
* Added file path name checking for AtomicReadFile and AtomicWriteFile
|
||||
|
||||
@@ -52,8 +52,11 @@ struct object_data {
|
||||
|
||||
/* Key List for storing the object data sorted by instance number */
|
||||
static OS_Keylist Object_List;
|
||||
|
||||
/* Internal write property callback */
|
||||
static write_property_function Write_Property_Internal_Callback;
|
||||
/* Write Property notification callbacks for logging or other purposes */
|
||||
static struct channel_write_property_notification
|
||||
Write_Property_Notification_Head;
|
||||
|
||||
/* These arrays are used by the ReadPropertyMultiple handler
|
||||
property-list property (as of protocol-revision 14) */
|
||||
@@ -735,12 +738,15 @@ static bool Channel_Write_Members(
|
||||
bactext_error_code_name(wp_data.error_code));
|
||||
}
|
||||
} else {
|
||||
wp_data.error_code = ERROR_CODE_PARAMETER_OUT_OF_RANGE;
|
||||
debug_printf(
|
||||
"channel[%lu].Channel_Write_Member[%u] "
|
||||
"coercion failed!\n",
|
||||
(unsigned long)object_instance, m);
|
||||
pObject->Write_Status = BACNET_WRITE_STATUS_FAILED;
|
||||
}
|
||||
Channel_Write_Property_Notify(
|
||||
object_instance, status, &wp_data);
|
||||
} else {
|
||||
debug_printf(
|
||||
"channel[%lu].Channel_Write_Member[%u] invalid!\n",
|
||||
@@ -1380,6 +1386,49 @@ void Channel_Write_Property_Internal_Callback_Set(write_property_function cb)
|
||||
Write_Property_Internal_Callback = cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a Channel notification callback
|
||||
* @param notification - pointer to the notification structure
|
||||
*/
|
||||
void Channel_Write_Property_Notification_Add(
|
||||
struct channel_write_property_notification *notification)
|
||||
{
|
||||
struct channel_write_property_notification *head;
|
||||
|
||||
head = &Write_Property_Notification_Head;
|
||||
do {
|
||||
if (head->next == notification) {
|
||||
/* already here! */
|
||||
break;
|
||||
} else if (!head->next) {
|
||||
/* first available node */
|
||||
head->next = notification;
|
||||
break;
|
||||
}
|
||||
head = head->next;
|
||||
} while (head);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief call the channel WriteProperty notification callbacks
|
||||
* @param instance - object instance number
|
||||
* @param status - status of the write
|
||||
* @param wp_data - write property data
|
||||
*/
|
||||
void Channel_Write_Property_Notify(
|
||||
uint32_t instance, bool status, BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
struct channel_write_property_notification *head;
|
||||
|
||||
head = &Write_Property_Notification_Head;
|
||||
do {
|
||||
if (head->callback) {
|
||||
head->callback(instance, status, wp_data);
|
||||
}
|
||||
head = head->next;
|
||||
} while (head);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the context used with a specific object instance
|
||||
* @param object_instance [in] BACnet object instance number
|
||||
|
||||
@@ -19,6 +19,21 @@
|
||||
#include "bacnet/basic/object/lo.h"
|
||||
#include "bacnet/channel_value.h"
|
||||
|
||||
/**
|
||||
* @brief Callback for tracking the channel writes for logging or other purposes
|
||||
* @param instance - channel object instance number
|
||||
* @param status - true if write was successful
|
||||
* @param wp_data - pointer to the write property data structure
|
||||
*/
|
||||
typedef void (*channel_write_property_callback)(
|
||||
uint32_t instance, bool status, BACNET_WRITE_PROPERTY_DATA *wp_data);
|
||||
/* linked list structure for notifications */
|
||||
struct channel_write_property_notification;
|
||||
struct channel_write_property_notification {
|
||||
struct channel_write_property_notification *next;
|
||||
channel_write_property_callback callback;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
@@ -104,6 +119,12 @@ bool Channel_Write_Member_Value(
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
void Channel_Write_Property_Internal_Callback_Set(write_property_function cb);
|
||||
BACNET_STACK_EXPORT
|
||||
void Channel_Write_Property_Notification_Add(
|
||||
struct channel_write_property_notification *notification);
|
||||
BACNET_STACK_EXPORT
|
||||
void Channel_Write_Property_Notify(
|
||||
uint32_t instance, bool status, BACNET_WRITE_PROPERTY_DATA *wp_data);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
void *Channel_Context_Get(uint32_t object_instance);
|
||||
|
||||
@@ -40,6 +40,8 @@ static const BACNET_OBJECT_TYPE Object_Type = OBJECT_LOOP;
|
||||
/* handling for manipulated and reference properties */
|
||||
static write_property_function Write_Property_Internal_Callback;
|
||||
static read_property_function Read_Property_Internal_Callback;
|
||||
/* Write Property notification callbacks for logging or other purposes */
|
||||
static struct loop_write_property_notification Write_Property_Notification_Head;
|
||||
|
||||
struct object_data {
|
||||
/* internal variables for PID calculations */
|
||||
@@ -2016,6 +2018,49 @@ void Loop_Write_Property_Internal_Callback_Set(write_property_function cb)
|
||||
Write_Property_Internal_Callback = cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a Loop notification callback
|
||||
* @param notification - pointer to the notification structure
|
||||
*/
|
||||
void Loop_Write_Property_Notification_Add(
|
||||
struct loop_write_property_notification *notification)
|
||||
{
|
||||
struct loop_write_property_notification *head;
|
||||
|
||||
head = &Write_Property_Notification_Head;
|
||||
do {
|
||||
if (head->next == notification) {
|
||||
/* already here! */
|
||||
break;
|
||||
} else if (!head->next) {
|
||||
/* first available node */
|
||||
head->next = notification;
|
||||
break;
|
||||
}
|
||||
head = head->next;
|
||||
} while (head);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calls all registered Loop write property notification callbacks
|
||||
* @param instance - object instance number
|
||||
* @param status - write property status
|
||||
* @param wp_data - write property data
|
||||
*/
|
||||
void Loop_Write_Property_Notify(
|
||||
uint32_t instance, bool status, BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
struct loop_write_property_notification *head;
|
||||
|
||||
head = &Write_Property_Notification_Head;
|
||||
do {
|
||||
if (head->callback) {
|
||||
head->callback(instance, status, wp_data);
|
||||
}
|
||||
head = head->next;
|
||||
} while (head);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For a given object, writes to the manipulated-variable-reference
|
||||
* @param pObject - object instance data
|
||||
@@ -2059,6 +2104,7 @@ static bool Loop_Write_Manipulated_Variable(
|
||||
}
|
||||
}
|
||||
}
|
||||
Loop_Write_Property_Notify(object_instance, status, &wp_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,21 @@
|
||||
#include "bacnet/rp.h"
|
||||
#include "bacnet/list_element.h"
|
||||
|
||||
/**
|
||||
* @brief Callback for tracking the loop writes for logging or other purposes
|
||||
* @param instance - loop object instance number
|
||||
* @param status - true if write was successful
|
||||
* @param wp_data - pointer to the write property data structure
|
||||
*/
|
||||
typedef void (*loop_write_property_callback)(
|
||||
uint32_t instance, bool status, BACNET_WRITE_PROPERTY_DATA *wp_data);
|
||||
/* linked list structure for notifications */
|
||||
struct loop_write_property_notification;
|
||||
struct loop_write_property_notification {
|
||||
struct loop_write_property_notification *next;
|
||||
loop_write_property_callback callback;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
@@ -191,6 +206,12 @@ BACNET_STACK_EXPORT
|
||||
void Loop_Write_Property_Internal_Callback_Set(write_property_function cb);
|
||||
BACNET_STACK_EXPORT
|
||||
void Loop_Read_Property_Internal_Callback_Set(read_property_function cb);
|
||||
BACNET_STACK_EXPORT
|
||||
void Loop_Write_Property_Notification_Add(
|
||||
struct loop_write_property_notification *notification);
|
||||
BACNET_STACK_EXPORT
|
||||
void Loop_Write_Property_Notify(
|
||||
uint32_t instance, bool status, BACNET_WRITE_PROPERTY_DATA *wp_data);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int Loop_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata);
|
||||
|
||||
@@ -39,6 +39,9 @@ static OS_Keylist Object_List = NULL;
|
||||
/* common object type */
|
||||
static const BACNET_OBJECT_TYPE Object_Type = OBJECT_TIMER;
|
||||
static write_property_function Write_Property_Internal_Callback;
|
||||
/* Write Property notification callbacks for logging or other purposes */
|
||||
static struct timer_write_property_notification
|
||||
Write_Property_Notification_Head;
|
||||
|
||||
struct object_data {
|
||||
uint32_t Present_Value;
|
||||
@@ -459,7 +462,7 @@ unsigned Timer_Reference_List_Member_Element_Count(uint32_t object_instance)
|
||||
/**
|
||||
* For a given object instance-number, sets the present-value at a given
|
||||
* priority 1..16.
|
||||
*
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param pObject - object instance data
|
||||
* @param value - application value
|
||||
* @param priority - BACnet priority 0=none,1..16
|
||||
@@ -467,6 +470,7 @@ unsigned Timer_Reference_List_Member_Element_Count(uint32_t object_instance)
|
||||
* @return true if values are within range and present-value is sent.
|
||||
*/
|
||||
static bool Timer_Write_Members(
|
||||
uint32_t object_instance,
|
||||
struct object_data *pObject,
|
||||
const BACNET_TIMER_STATE_CHANGE_VALUE *value,
|
||||
uint8_t priority)
|
||||
@@ -504,6 +508,7 @@ static bool Timer_Write_Members(
|
||||
}
|
||||
}
|
||||
}
|
||||
Timer_Write_Property_Notify(object_instance, status, &wp_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -514,9 +519,11 @@ static bool Timer_Write_Members(
|
||||
/**
|
||||
* @brief initiate the write requests for the current transition
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param pObject - object instance data
|
||||
* @return true if the write occurred
|
||||
*/
|
||||
static bool Timer_Write_Request_Initiate(struct object_data *pObject)
|
||||
static bool Timer_Write_Request_Initiate(
|
||||
uint32_t object_instance, struct object_data *pObject)
|
||||
{
|
||||
bool status = false;
|
||||
unsigned index = 0;
|
||||
@@ -532,7 +539,7 @@ static bool Timer_Write_Request_Initiate(struct object_data *pObject)
|
||||
}
|
||||
if (value) {
|
||||
status = Timer_Write_Members(
|
||||
pObject, value, pObject->Priority_For_Writing);
|
||||
object_instance, pObject, value, pObject->Priority_For_Writing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -600,7 +607,7 @@ bool Timer_State_Set(uint32_t object_instance, BACNET_TIMER_STATE value)
|
||||
&pObject->Update_Time.date, &pObject->Update_Time.time,
|
||||
NULL, NULL);
|
||||
pObject->Last_State_Change = TIMER_TRANSITION_RUNNING_TO_IDLE;
|
||||
Timer_Write_Request_Initiate(pObject);
|
||||
Timer_Write_Request_Initiate(object_instance, pObject);
|
||||
} else if (pObject->Timer_State == TIMER_STATE_EXPIRED) {
|
||||
pObject->Last_State_Change = TIMER_TRANSITION_EXPIRED_TO_IDLE;
|
||||
/* then set Timer_State to IDLE;
|
||||
@@ -614,7 +621,7 @@ bool Timer_State_Set(uint32_t object_instance, BACNET_TIMER_STATE value)
|
||||
&pObject->Update_Time.date, &pObject->Update_Time.time,
|
||||
NULL, NULL);
|
||||
pObject->Last_State_Change = TIMER_TRANSITION_EXPIRED_TO_IDLE;
|
||||
Timer_Write_Request_Initiate(pObject);
|
||||
Timer_Write_Request_Initiate(object_instance, pObject);
|
||||
} else if (pObject->Timer_State == TIMER_STATE_IDLE) {
|
||||
/* then no properties shall be changed;
|
||||
no write requests shall be initiated;
|
||||
@@ -695,7 +702,7 @@ bool Timer_Running_Set(uint32_t object_instance, bool start)
|
||||
datetime_local(
|
||||
&pObject->Update_Time.date, &pObject->Update_Time.time,
|
||||
NULL, NULL);
|
||||
Timer_Write_Request_Initiate(pObject);
|
||||
Timer_Write_Request_Initiate(object_instance, pObject);
|
||||
} else if (pObject->Timer_State == TIMER_STATE_RUNNING) {
|
||||
/* If a value of TRUE is written to the Timer_Running property,
|
||||
then set Last_State_Change to RUNNING_TO_RUNNING;
|
||||
@@ -712,7 +719,7 @@ bool Timer_Running_Set(uint32_t object_instance, bool start)
|
||||
datetime_local(
|
||||
&pObject->Update_Time.date, &pObject->Update_Time.time,
|
||||
NULL, NULL);
|
||||
Timer_Write_Request_Initiate(pObject);
|
||||
Timer_Write_Request_Initiate(object_instance, pObject);
|
||||
} else if (pObject->Timer_State == TIMER_STATE_EXPIRED) {
|
||||
/* If a value of TRUE is written to the Timer_Running property,
|
||||
set Timer_State to RUNNING;
|
||||
@@ -730,7 +737,7 @@ bool Timer_Running_Set(uint32_t object_instance, bool start)
|
||||
datetime_local(
|
||||
&pObject->Update_Time.date, &pObject->Update_Time.time,
|
||||
NULL, NULL);
|
||||
Timer_Write_Request_Initiate(pObject);
|
||||
Timer_Write_Request_Initiate(object_instance, pObject);
|
||||
}
|
||||
} else {
|
||||
if (pObject->Timer_State == TIMER_STATE_RUNNING) {
|
||||
@@ -749,7 +756,7 @@ bool Timer_Running_Set(uint32_t object_instance, bool start)
|
||||
datetime_local(
|
||||
&pObject->Update_Time.date, &pObject->Update_Time.time,
|
||||
NULL, NULL);
|
||||
Timer_Write_Request_Initiate(pObject);
|
||||
Timer_Write_Request_Initiate(object_instance, pObject);
|
||||
}
|
||||
}
|
||||
status = true;
|
||||
@@ -1079,7 +1086,7 @@ bool Timer_Present_Value_Set(uint32_t object_instance, uint32_t value)
|
||||
datetime_local(
|
||||
&pObject->Update_Time.date, &pObject->Update_Time.time,
|
||||
NULL, NULL);
|
||||
Timer_Write_Request_Initiate(pObject);
|
||||
Timer_Write_Request_Initiate(object_instance, pObject);
|
||||
}
|
||||
status = true;
|
||||
} else {
|
||||
@@ -1112,7 +1119,7 @@ bool Timer_Present_Value_Set(uint32_t object_instance, uint32_t value)
|
||||
datetime_local(
|
||||
&pObject->Update_Time.date, &pObject->Update_Time.time,
|
||||
NULL, NULL);
|
||||
Timer_Write_Request_Initiate(pObject);
|
||||
Timer_Write_Request_Initiate(object_instance, pObject);
|
||||
status = true;
|
||||
} else {
|
||||
status = false;
|
||||
@@ -2082,6 +2089,49 @@ void Timer_Write_Property_Internal_Callback_Set(write_property_function cb)
|
||||
Write_Property_Internal_Callback = cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a Timer write property notification callback
|
||||
* @param notification - pointer to the notification structure
|
||||
*/
|
||||
void Timer_Write_Property_Notification_Add(
|
||||
struct timer_write_property_notification *notification)
|
||||
{
|
||||
struct timer_write_property_notification *head;
|
||||
|
||||
head = &Write_Property_Notification_Head;
|
||||
do {
|
||||
if (head->next == notification) {
|
||||
/* already here! */
|
||||
break;
|
||||
} else if (!head->next) {
|
||||
/* first available node */
|
||||
head->next = notification;
|
||||
break;
|
||||
}
|
||||
head = head->next;
|
||||
} while (head);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calls all registered Timer write property notification callbacks
|
||||
* @param instance - object instance number
|
||||
* @param status - write property status
|
||||
* @param wp_data - write property data
|
||||
*/
|
||||
void Timer_Write_Property_Notify(
|
||||
uint32_t instance, bool status, BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
struct timer_write_property_notification *head;
|
||||
|
||||
head = &Write_Property_Notification_Head;
|
||||
do {
|
||||
if (head->callback) {
|
||||
head->callback(instance, status, wp_data);
|
||||
}
|
||||
head = head->next;
|
||||
} while (head);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the object program operation
|
||||
* @details In the RUNNING state, the timer is active
|
||||
|
||||
@@ -18,6 +18,21 @@
|
||||
#include "bacnet/rp.h"
|
||||
#include "bacnet/list_element.h"
|
||||
|
||||
/**
|
||||
* @brief Callback for tracking the timer writes for logging or other purposes
|
||||
* @param instance - timer object instance number
|
||||
* @param status - true if write was successful
|
||||
* @param wp_data - pointer to the write property data structure
|
||||
*/
|
||||
typedef void (*timer_write_property_callback)(
|
||||
uint32_t instance, bool status, BACNET_WRITE_PROPERTY_DATA *wp_data);
|
||||
/* linked list structure for notifications */
|
||||
struct timer_write_property_notification;
|
||||
struct timer_write_property_notification {
|
||||
struct timer_write_property_notification *next;
|
||||
timer_write_property_callback callback;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
@@ -166,6 +181,12 @@ void Timer_Task(uint32_t object_instance, uint16_t milliseconds);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
void Timer_Write_Property_Internal_Callback_Set(write_property_function cb);
|
||||
BACNET_STACK_EXPORT
|
||||
void Timer_Write_Property_Notification_Add(
|
||||
struct timer_write_property_notification *notification);
|
||||
BACNET_STACK_EXPORT
|
||||
void Timer_Write_Property_Notify(
|
||||
uint32_t instance, bool status, BACNET_WRITE_PROPERTY_DATA *wp_data);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int Timer_Add_List_Element(BACNET_LIST_ELEMENT_DATA *list_element);
|
||||
|
||||
@@ -26,6 +26,20 @@ static bool Write_Property_Internal(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct channel_write_property_notification Write_Property_Notification;
|
||||
static BACNET_WRITE_PROPERTY_DATA Write_Property_Notification_Data;
|
||||
static uint32_t Write_Property_Notification_Instance;
|
||||
static bool Write_Property_Notification_Status;
|
||||
static void Channel_Write_Property_Notification_Callback(
|
||||
uint32_t instance, bool status, BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
Write_Property_Notification_Instance = instance;
|
||||
Write_Property_Notification_Status = status;
|
||||
memcpy(
|
||||
&Write_Property_Notification_Data, wp_data,
|
||||
sizeof(BACNET_WRITE_PROPERTY_DATA));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test
|
||||
*/
|
||||
@@ -38,15 +52,21 @@ static void test_Channel_Property_Read_Write(void)
|
||||
const char *test_name = NULL;
|
||||
uint32_t test_instance = 0;
|
||||
bool status = false;
|
||||
int len = 0;
|
||||
const int32_t skip_fail_property_list[] = { -1 };
|
||||
BACNET_CHANNEL_VALUE channel_value = { 0 };
|
||||
BACNET_WRITE_PROPERTY_DATA wp_data = { 0 };
|
||||
BACNET_WRITE_GROUP_DATA wg_data = { 0 };
|
||||
|
||||
BACNET_APPLICATION_DATA_VALUE value = { 0 };
|
||||
BACNET_APPLICATION_DATA_VALUE test_value = { 0 };
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE member = { 0 };
|
||||
|
||||
Channel_Write_Property_Internal_Callback_Set(Write_Property_Internal);
|
||||
Write_Property_Notification.callback =
|
||||
Channel_Write_Property_Notification_Callback;
|
||||
Write_Property_Notification.next = NULL;
|
||||
Channel_Write_Property_Notification_Add(&Write_Property_Notification);
|
||||
|
||||
Channel_Init();
|
||||
Channel_Create(instance);
|
||||
status = Channel_Valid_Instance(instance);
|
||||
@@ -162,6 +182,48 @@ static void test_Channel_Property_Read_Write(void)
|
||||
bacapp_encode_application_data(wp_data.application_data, &value);
|
||||
status = Channel_Write_Property(&wp_data);
|
||||
zassert_true(status, NULL);
|
||||
/* does the callback object property match the last member? */
|
||||
zassert_equal(
|
||||
Write_Property_Internal_Data.object_property, member.propertyIdentifier,
|
||||
"%s:%d %s",
|
||||
bactext_object_type_name(Write_Property_Internal_Data.object_type),
|
||||
Write_Property_Internal_Data.object_instance,
|
||||
bactext_property_name(Write_Property_Internal_Data.object_property));
|
||||
zassert_equal(
|
||||
Write_Property_Internal_Data.object_type, member.objectIdentifier.type,
|
||||
"WriteProperty=%s:%d",
|
||||
bactext_object_type_name(Write_Property_Internal_Data.object_type),
|
||||
Write_Property_Internal_Data.object_instance);
|
||||
zassert_equal(
|
||||
Write_Property_Internal_Data.object_instance,
|
||||
member.objectIdentifier.instance, "WriteProperty=%s:%d",
|
||||
bactext_object_type_name(Write_Property_Internal_Data.object_type),
|
||||
Write_Property_Internal_Data.object_instance);
|
||||
len = bacapp_decode_application_data(
|
||||
Write_Property_Internal_Data.application_data,
|
||||
Write_Property_Internal_Data.application_data_len, &test_value);
|
||||
zassert_true(len > 0, "len=%d", len);
|
||||
/* does the notify callback object property match the last member? */
|
||||
zassert_equal(Write_Property_Notification_Instance, instance, NULL);
|
||||
zassert_equal(Write_Property_Notification_Status, true, NULL);
|
||||
zassert_equal(
|
||||
Write_Property_Notification_Data.object_property,
|
||||
member.propertyIdentifier, NULL);
|
||||
zassert_equal(
|
||||
Write_Property_Notification_Data.object_type,
|
||||
member.objectIdentifier.type, "WriteProperty=%s:%d",
|
||||
bactext_object_type_name(Write_Property_Notification_Data.object_type),
|
||||
Write_Property_Notification_Data.object_instance);
|
||||
zassert_equal(
|
||||
Write_Property_Notification_Data.object_instance,
|
||||
member.objectIdentifier.instance, "WriteProperty=%s:%d",
|
||||
bactext_object_type_name(Write_Property_Notification_Data.object_type),
|
||||
Write_Property_Notification_Data.object_instance);
|
||||
len = bacapp_decode_application_data(
|
||||
Write_Property_Notification_Data.application_data,
|
||||
Write_Property_Notification_Data.application_data_len, &test_value);
|
||||
zassert_true(len > 0, "len=%d", len);
|
||||
/* another coercion */
|
||||
value.type.Channel_Value.tag = BACNET_APPLICATION_TAG_XY_COLOR;
|
||||
value.type.Channel_Value.type.XY_Color.x_coordinate = 0.4590f;
|
||||
value.type.Channel_Value.type.XY_Color.y_coordinate = 0.4101f;
|
||||
|
||||
@@ -35,6 +35,20 @@ static int Read_Property_Internal(BACNET_READ_PROPERTY_DATA *data)
|
||||
return Read_Property_Internal_Length;
|
||||
}
|
||||
|
||||
static struct loop_write_property_notification Write_Property_Notification;
|
||||
static BACNET_WRITE_PROPERTY_DATA Write_Property_Notification_Data;
|
||||
static uint32_t Write_Property_Notification_Instance;
|
||||
static bool Write_Property_Notification_Status;
|
||||
static void Loop_Write_Property_Notification_Callback(
|
||||
uint32_t instance, bool status, BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
Write_Property_Notification_Instance = instance;
|
||||
Write_Property_Notification_Status = status;
|
||||
memcpy(
|
||||
&Write_Property_Notification_Data, wp_data,
|
||||
sizeof(BACNET_WRITE_PROPERTY_DATA));
|
||||
}
|
||||
|
||||
static int Proprietary_Properties[] = { 512, 513, -1 };
|
||||
static uint8_t Proprietary_Serial_Number[16];
|
||||
|
||||
@@ -369,6 +383,8 @@ static void test_Loop_Operation(void)
|
||||
bool status = false;
|
||||
uint32_t elapsed_time = 0;
|
||||
BACNET_OBJECT_PROPERTY_REFERENCE reference = { 0 };
|
||||
BACNET_APPLICATION_DATA_VALUE test_value = { 0 };
|
||||
int len = 0;
|
||||
|
||||
/* init */
|
||||
Loop_Init();
|
||||
@@ -379,6 +395,10 @@ static void test_Loop_Operation(void)
|
||||
/* connect the read and write property callbacks */
|
||||
Loop_Write_Property_Internal_Callback_Set(Write_Property_Internal);
|
||||
Loop_Read_Property_Internal_Callback_Set(Read_Property_Internal);
|
||||
Write_Property_Notification.callback =
|
||||
Loop_Write_Property_Notification_Callback;
|
||||
Write_Property_Notification.next = NULL;
|
||||
Loop_Write_Property_Notification_Add(&Write_Property_Notification);
|
||||
/* run the PID loop */
|
||||
Loop_Timer(instance, elapsed_time);
|
||||
elapsed_time += 1000;
|
||||
@@ -402,6 +422,42 @@ static void test_Loop_Operation(void)
|
||||
Loop_Manipulated_Variable_Reference_Set(instance, &reference);
|
||||
elapsed_time += 100;
|
||||
Loop_Timer(instance, elapsed_time);
|
||||
/* references - test by referencing another internal object */
|
||||
reference.object_identifier.type = OBJECT_ANALOG_OUTPUT;
|
||||
reference.property_identifier = PROP_PRESENT_VALUE;
|
||||
Loop_Manipulated_Variable_Reference_Set(instance, &reference);
|
||||
elapsed_time += 100;
|
||||
Loop_Timer(instance, elapsed_time);
|
||||
/* verify that the internal read/write property callbacks were used */
|
||||
zassert_equal(
|
||||
Write_Property_Internal_Data.object_type, OBJECT_ANALOG_OUTPUT,
|
||||
"WriteProperty=%s:%d",
|
||||
bactext_object_type_name(Write_Property_Internal_Data.object_type),
|
||||
Write_Property_Internal_Data.object_instance);
|
||||
zassert_equal(
|
||||
Write_Property_Internal_Data.object_instance, instance,
|
||||
"WriteProperty=%s:%d",
|
||||
bactext_object_type_name(Write_Property_Internal_Data.object_type),
|
||||
Write_Property_Internal_Data.object_instance);
|
||||
zassert_equal(
|
||||
Write_Property_Internal_Data.object_property, PROP_PRESENT_VALUE,
|
||||
"WriteProperty=%s:%d %s",
|
||||
bactext_object_type_name(Write_Property_Internal_Data.object_type),
|
||||
Write_Property_Internal_Data.object_instance,
|
||||
bactext_property_name(Write_Property_Internal_Data.object_property));
|
||||
len = bacapp_decode_application_data(
|
||||
Write_Property_Internal_Data.application_data,
|
||||
Write_Property_Internal_Data.application_data_len, &test_value);
|
||||
zassert_true(len > 0, "len=%d", len);
|
||||
zassert_equal(Write_Property_Notification_Instance, instance, NULL);
|
||||
zassert_equal(Write_Property_Notification_Status, true, NULL);
|
||||
zassert_equal(
|
||||
Write_Property_Notification_Data.object_property, PROP_PRESENT_VALUE,
|
||||
NULL);
|
||||
len = bacapp_decode_application_data(
|
||||
Write_Property_Notification_Data.application_data,
|
||||
Write_Property_Notification_Data.application_data_len, &test_value);
|
||||
zassert_true(len > 0, "len=%d", len);
|
||||
/* cleanup instance */
|
||||
status = Loop_Delete(instance);
|
||||
zassert_true(status, NULL);
|
||||
|
||||
@@ -26,6 +26,20 @@ static bool Write_Property_Internal(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct timer_write_property_notification Write_Property_Notification;
|
||||
static BACNET_WRITE_PROPERTY_DATA Write_Property_Notification_Data;
|
||||
static uint32_t Write_Property_Notification_Instance;
|
||||
static bool Write_Property_Notification_Status;
|
||||
static void Timer_Write_Property_Notification_Callback(
|
||||
uint32_t instance, bool status, BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
Write_Property_Notification_Instance = instance;
|
||||
Write_Property_Notification_Status = status;
|
||||
memcpy(
|
||||
&Write_Property_Notification_Data, wp_data,
|
||||
sizeof(BACNET_WRITE_PROPERTY_DATA));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test
|
||||
*/
|
||||
@@ -544,6 +558,15 @@ static void test_Timer_Operation_Transition_Default(
|
||||
Write_Property_Internal_Data.application_data,
|
||||
Write_Property_Internal_Data.application_data_len, &test_value);
|
||||
zassert_true(len > 0, "len=%d", len);
|
||||
zassert_equal(Write_Property_Notification_Instance, instance, NULL);
|
||||
zassert_equal(Write_Property_Notification_Status, true, NULL);
|
||||
zassert_equal(
|
||||
Write_Property_Notification_Data.object_property, PROP_PRESENT_VALUE,
|
||||
NULL);
|
||||
len = bacapp_decode_application_data(
|
||||
Write_Property_Notification_Data.application_data,
|
||||
Write_Property_Notification_Data.application_data_len, &test_value);
|
||||
zassert_true(len > 0, "len=%d", len);
|
||||
value = Timer_State_Change_Value(instance, test_transition);
|
||||
zassert_equal(test_value.tag, value->tag, NULL);
|
||||
zassert_equal(test_value.type.Enumerated, value->type.Enumerated, NULL);
|
||||
@@ -576,6 +599,10 @@ static void test_Timer_Operation(void)
|
||||
datetime_timesync(&bdatetime.date, &bdatetime.time, false);
|
||||
/* configure the reference members and the write property values */
|
||||
Timer_Write_Property_Internal_Callback_Set(Write_Property_Internal);
|
||||
Write_Property_Notification.callback =
|
||||
Timer_Write_Property_Notification_Callback;
|
||||
Write_Property_Notification.next = NULL;
|
||||
Timer_Write_Property_Notification_Add(&Write_Property_Notification);
|
||||
members = Timer_Reference_List_Member_Capacity(instance);
|
||||
for (i = 0; i < members; i++) {
|
||||
member.deviceIdentifier.type = OBJECT_DEVICE;
|
||||
|
||||
Reference in New Issue
Block a user