Add network port callbacks for pending changes activate and discard. (#836)
This commit is contained in:
@@ -25,6 +25,9 @@
|
||||
#include "bacnet/basic/services.h"
|
||||
#include "bacnet/datalink/datalink.h"
|
||||
#include "bacnet/basic/binding/address.h"
|
||||
#if (BACFILE)
|
||||
#include "bacnet/basic/object/bacfile.h"
|
||||
#endif
|
||||
#if (BACNET_PROTOCOL_REVISION >= 17)
|
||||
#include "bacnet/basic/object/netport.h"
|
||||
#endif
|
||||
@@ -1172,6 +1175,124 @@ int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles the writing of the object name property
|
||||
* @param wp_data [in,out] WriteProperty data structure
|
||||
* @param Object_Write_Property object specific function to write the property
|
||||
* @return True on success, else False if there is an error.
|
||||
*/
|
||||
static bool Device_Write_Property_Object_Name(
|
||||
BACNET_WRITE_PROPERTY_DATA *wp_data,
|
||||
write_property_function Object_Write_Property)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
int len = 0;
|
||||
BACNET_CHARACTER_STRING value;
|
||||
BACNET_OBJECT_TYPE object_type = OBJECT_NONE;
|
||||
uint32_t object_instance = 0;
|
||||
int apdu_size = 0;
|
||||
uint8_t *apdu = NULL;
|
||||
|
||||
if (!wp_data) {
|
||||
return false;
|
||||
}
|
||||
if (wp_data->array_index != BACNET_ARRAY_ALL) {
|
||||
/* only array properties can have array options */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
||||
return false;
|
||||
}
|
||||
apdu = wp_data->application_data;
|
||||
apdu_size = wp_data->application_data_len;
|
||||
len = bacnet_character_string_application_decode(apdu, apdu_size, &value);
|
||||
if (len > 0) {
|
||||
if ((characterstring_encoding(&value) != CHARACTER_ANSI_X34) ||
|
||||
(characterstring_length(&value) == 0) ||
|
||||
(!characterstring_printable(&value))) {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
} else {
|
||||
status = true;
|
||||
}
|
||||
} else if (len == 0) {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
if (status) {
|
||||
/* All the object names in a device must be unique */
|
||||
if (Device_Valid_Object_Name(&value, &object_type, &object_instance)) {
|
||||
if ((object_type == wp_data->object_type) &&
|
||||
(object_instance == wp_data->object_instance)) {
|
||||
/* writing same name to same object */
|
||||
status = true;
|
||||
} else {
|
||||
/* name already exists in some object */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_DUPLICATE_NAME;
|
||||
status = false;
|
||||
}
|
||||
} else {
|
||||
status = Object_Write_Property(wp_data);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Looks up the requested Object and Property, and set the new Value in it,
|
||||
* if allowed.
|
||||
* If the Object or Property can't be found, sets the error class and code.
|
||||
* @ingroup ObjIntf
|
||||
*
|
||||
* @param wp_data [in,out] Structure with the desired Object and Property info
|
||||
* and new Value on entry, and APDU message on return.
|
||||
* @return True on success, else False if there is an error.
|
||||
*/
|
||||
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* Ever the pessimist! */
|
||||
struct object_functions *pObject = NULL;
|
||||
|
||||
/* initialize the default return values */
|
||||
wp_data->error_class = ERROR_CLASS_OBJECT;
|
||||
wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
pObject = Device_Objects_Find_Functions(wp_data->object_type);
|
||||
if (pObject != NULL) {
|
||||
if (pObject->Object_Valid_Instance &&
|
||||
pObject->Object_Valid_Instance(wp_data->object_instance)) {
|
||||
if (pObject->Object_Write_Property) {
|
||||
#if (BACNET_PROTOCOL_REVISION >= 14)
|
||||
if (wp_data->object_property == PROP_PROPERTY_LIST) {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
if (wp_data->object_property == PROP_OBJECT_NAME) {
|
||||
status = Device_Write_Property_Object_Name(
|
||||
wp_data, pObject->Object_Write_Property);
|
||||
} else {
|
||||
status = pObject->Object_Write_Property(wp_data);
|
||||
}
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
}
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_OBJECT;
|
||||
wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
}
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_OBJECT;
|
||||
wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates all the object timers with elapsed milliseconds
|
||||
* @param milliseconds - number of milliseconds elapsed
|
||||
|
||||
@@ -666,6 +666,7 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
||||
{
|
||||
bool status = false;
|
||||
bool password_success = false;
|
||||
unsigned i;
|
||||
|
||||
/* From 16.4.1.1.2 Password
|
||||
This optional parameter shall be a CharacterString of up to
|
||||
@@ -690,8 +691,19 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
||||
if (password_success) {
|
||||
switch (rd_data->state) {
|
||||
case BACNET_REINIT_COLDSTART:
|
||||
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
|
||||
/* note: you probably want to restart *after* the
|
||||
simple ack has been sent from the return handler
|
||||
so just set a flag from here */
|
||||
Reinitialize_State = rd_data->state;
|
||||
status = true;
|
||||
break;
|
||||
case BACNET_REINIT_WARMSTART:
|
||||
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
|
||||
for (i = 0; i < Network_Port_Count(); i++) {
|
||||
Network_Port_Changes_Pending_Activate(
|
||||
Network_Port_Index_To_Instance(i));
|
||||
}
|
||||
/* note: you probably want to restart *after* the
|
||||
simple ack has been sent from the return handler
|
||||
so just set a flag from here */
|
||||
@@ -714,6 +726,10 @@ bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
||||
break;
|
||||
case BACNET_REINIT_ACTIVATE_CHANGES:
|
||||
/* note: activate changes *after* the simple ack is sent */
|
||||
for (i = 0; i < Network_Port_Count(); i++) {
|
||||
Network_Port_Changes_Pending_Activate(
|
||||
Network_Port_Index_To_Instance(i));
|
||||
}
|
||||
Reinitialize_State = rd_data->state;
|
||||
status = true;
|
||||
break;
|
||||
|
||||
@@ -104,6 +104,8 @@ struct object_data {
|
||||
BACNET_PORT_QUALITY Quality;
|
||||
uint16_t APDU_Length;
|
||||
float Link_Speed;
|
||||
bacnet_network_port_activate_changes Activate_Changes;
|
||||
bacnet_network_port_discard_changes Discard_Changes;
|
||||
union {
|
||||
struct bacnet_ipv4_port IPv4;
|
||||
struct bacnet_ipv6_port IPv6;
|
||||
@@ -956,6 +958,9 @@ bool Network_Port_Changes_Pending_Set(uint32_t object_instance, bool value)
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
Object_List[index].Changes_Pending = value;
|
||||
if (value == false) {
|
||||
Network_Port_Changes_Pending_Discard(object_instance);
|
||||
}
|
||||
status = true;
|
||||
}
|
||||
|
||||
@@ -972,7 +977,25 @@ void Network_Port_Changes_Pending_Activate(uint32_t object_instance)
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
/* callback? something else? */
|
||||
if (Object_List[index].Activate_Changes) {
|
||||
Object_List[index].Activate_Changes(object_instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For a given object instance-number, sets the callback function
|
||||
* to activate any pending changes
|
||||
*/
|
||||
void Network_Port_Changes_Pending_Activate_Callback_Set(
|
||||
uint32_t object_instance, bacnet_network_port_activate_changes callback)
|
||||
|
||||
{
|
||||
unsigned index = 0;
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
Object_List[index].Activate_Changes = callback;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -986,7 +1009,25 @@ void Network_Port_Changes_Pending_Discard(uint32_t object_instance)
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
/* callback? something else? */
|
||||
if (Object_List[index].Discard_Changes) {
|
||||
Object_List[index].Discard_Changes(object_instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For a given object instance-number, sets the callback function
|
||||
* to discard any pending changes
|
||||
*/
|
||||
void Network_Port_Changes_Pending_Discard_Callback_Set(
|
||||
uint32_t object_instance, bacnet_network_port_discard_changes callback)
|
||||
|
||||
{
|
||||
unsigned index = 0;
|
||||
|
||||
index = Network_Port_Instance_To_Index(object_instance);
|
||||
if (index < BACNET_NETWORK_PORTS_MAX) {
|
||||
Object_List[index].Discard_Changes = callback;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,20 @@
|
||||
#include "bacnet/rp.h"
|
||||
#include "bacnet/wp.h"
|
||||
|
||||
/**
|
||||
* @brief API for a network port object when changes need to be activated
|
||||
* @param object_instance [in] Object instance number
|
||||
* @return true if successful, else false
|
||||
*/
|
||||
typedef void (*bacnet_network_port_activate_changes)(uint32_t object_instance);
|
||||
|
||||
/**
|
||||
* @brief API for a network port object when changes need to be discarded
|
||||
* @param object_instance [in] Object instance number
|
||||
* @return true if successful, else false
|
||||
*/
|
||||
typedef void (*bacnet_network_port_discard_changes)(uint32_t object_instance);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
@@ -318,7 +332,13 @@ bool Network_Port_Changes_Pending_Set(uint32_t instance, bool flag);
|
||||
BACNET_STACK_EXPORT
|
||||
void Network_Port_Changes_Pending_Activate(uint32_t instance);
|
||||
BACNET_STACK_EXPORT
|
||||
void Network_Port_Changes_Pending_Activate_Callback_Set(
|
||||
uint32_t instance, bacnet_network_port_activate_changes callback);
|
||||
BACNET_STACK_EXPORT
|
||||
void Network_Port_Changes_Pending_Discard(uint32_t instance);
|
||||
BACNET_STACK_EXPORT
|
||||
void Network_Port_Changes_Pending_Discard_Callback_Set(
|
||||
uint32_t instance, bacnet_network_port_discard_changes callback);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool Network_Port_Valid_Instance(uint32_t object_instance);
|
||||
|
||||
Reference in New Issue
Block a user