Fixed the loop object empty reference property by initializing to self. When configured for self, the manipulated property value will update the controlled variable value for simulation. (#1158)

* Fixed the loop object empty reference property by initializing to self.   When configured for self, the manipulated property value will update the controlled variable value for simulation.

* Changed min/max output and update-interval defaults.
This commit is contained in:
Steve Karg
2025-11-21 15:45:14 -06:00
committed by GitHub
parent 94b267d67e
commit a508e11624
2 changed files with 46 additions and 17 deletions
+5
View File
@@ -31,6 +31,11 @@ The git repositories are hosted at the following sites:
### Fixed ### Fixed
* Fixed the ports/linux BACnet/IP cache netmask for accurate subnet
prefix calculation implementation which had always returned 0. (#1155)
* Fixed the loop object empty reference property by initializing to self.
When configured for self, the manipulated property value will update
the controlled variable value for simulation.(#1158)
* Fixed unit test stack corruption from using stack based message text * Fixed unit test stack corruption from using stack based message text
characterstring pointer in multiple functions and setting the value characterstring pointer in multiple functions and setting the value
in the global event and test event data structures. (#1154) in the global event and test event data structures. (#1154)
+41 -17
View File
@@ -50,7 +50,7 @@ struct object_data {
uint32_t Update_Interval; uint32_t Update_Interval;
float Present_Value; float Present_Value;
BACNET_ENGINEERING_UNITS Output_Units; BACNET_ENGINEERING_UNITS Output_Units;
BACNET_OBJECT_PROPERTY_REFERENCE Manipulated_Property_Reference; BACNET_OBJECT_PROPERTY_REFERENCE Manipulated_Variable_Reference;
BACNET_ENGINEERING_UNITS Controlled_Variable_Units; BACNET_ENGINEERING_UNITS Controlled_Variable_Units;
float Controlled_Variable_Value; float Controlled_Variable_Value;
BACNET_OBJECT_PROPERTY_REFERENCE Controlled_Variable_Reference; BACNET_OBJECT_PROPERTY_REFERENCE Controlled_Variable_Reference;
@@ -652,11 +652,18 @@ Object_Property_Reference_Empty(const BACNET_OBJECT_PROPERTY_REFERENCE *value)
* @param value - object property reference * @param value - object property reference
* @return true if the reference is empty * @return true if the reference is empty
*/ */
static void static void Object_Property_Reference_Set(
Object_Property_Reference_Set_Empty(BACNET_OBJECT_PROPERTY_REFERENCE *value) BACNET_OBJECT_PROPERTY_REFERENCE *value,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_PROPERTY_ID property_id,
BACNET_ARRAY_INDEX array_index)
{ {
if (value) { if (value) {
value->object_identifier.instance = BACNET_MAX_INSTANCE; value->object_identifier.type = object_type;
value->object_identifier.instance = object_instance;
value->property_identifier = property_id;
value->property_array_index = array_index;
} }
} }
@@ -679,7 +686,7 @@ bool Loop_Manipulated_Variable_Reference(
pObject = Keylist_Data(Object_List, object_instance); pObject = Keylist_Data(Object_List, object_instance);
if (pObject) { if (pObject) {
status = bacnet_object_property_reference_copy( status = bacnet_object_property_reference_copy(
value, &pObject->Manipulated_Property_Reference); value, &pObject->Manipulated_Variable_Reference);
} }
return status; return status;
@@ -705,7 +712,7 @@ bool Loop_Manipulated_Variable_Reference_Set(
pObject = Keylist_Data(Object_List, object_instance); pObject = Keylist_Data(Object_List, object_instance);
if (pObject) { if (pObject) {
status = bacnet_object_property_reference_copy( status = bacnet_object_property_reference_copy(
&pObject->Manipulated_Property_Reference, value); &pObject->Manipulated_Variable_Reference, value);
} }
return status; return status;
@@ -2013,20 +2020,28 @@ void Loop_Write_Property_Internal_Callback_Set(write_property_function cb)
/** /**
* @brief For a given object, writes to the manipulated-variable-reference * @brief For a given object, writes to the manipulated-variable-reference
* @param pObject - object instance data * @param pObject - object instance data
* @param object_instance - object-instance number of the object
* @param value - application value * @param value - application value
* @param priority - BACnet priority 0=none,1..16 * @param priority - BACnet priority 0=none,1..16
* @return true if values are within range and value is written. * @return true if values are within range and value is written.
*/ */
static bool Loop_Write_Manipulated_Variable( static bool Loop_Write_Manipulated_Variable(
struct object_data *pObject, float value, uint8_t priority) struct object_data *pObject,
uint32_t object_instance,
float value,
uint8_t priority)
{ {
BACNET_WRITE_PROPERTY_DATA wp_data = { 0 }; BACNET_WRITE_PROPERTY_DATA wp_data = { 0 };
BACNET_OBJECT_PROPERTY_REFERENCE *member; BACNET_OBJECT_PROPERTY_REFERENCE *member;
bool status = false; bool status = false;
if (pObject) { if (pObject) {
member = &pObject->Manipulated_Property_Reference; member = &pObject->Manipulated_Variable_Reference;
if (!Object_Property_Reference_Empty(member)) { if ((member->object_identifier.type == OBJECT_LOOP) &&
(member->object_identifier.instance == object_instance)) {
/* self - perform simulation by setting the controlled variable */
pObject->Controlled_Variable_Value = value;
} else if (!Object_Property_Reference_Empty(member)) {
wp_data.object_type = member->object_identifier.type; wp_data.object_type = member->object_identifier.type;
wp_data.object_instance = member->object_identifier.instance; wp_data.object_instance = member->object_identifier.instance;
wp_data.object_property = member->property_identifier; wp_data.object_property = member->property_identifier;
@@ -2146,7 +2161,7 @@ void Loop_Timer(uint32_t object_instance, uint16_t elapsed_milliseconds)
respond to changes made to these properties, respond to changes made to these properties,
as if those changes had been made by the algorithm.*/ as if those changes had been made by the algorithm.*/
Loop_Write_Manipulated_Variable( Loop_Write_Manipulated_Variable(
pObject, pObject->Present_Value, pObject, object_instance, pObject->Present_Value,
pObject->Priority_For_Writing); pObject->Priority_For_Writing);
} }
} }
@@ -2193,19 +2208,28 @@ uint32_t Loop_Create(uint32_t object_instance)
return BACNET_MAX_INSTANCE; return BACNET_MAX_INSTANCE;
} }
/* only need to set property values that are non-zero */ /* only need to set property values that are non-zero */
pObject->Maximum_Output = 10.0f;
pObject->Minimum_Output = 0.0f;
pObject->Output_Units = UNITS_NO_UNITS; pObject->Output_Units = UNITS_NO_UNITS;
pObject->Controlled_Variable_Units = UNITS_NO_UNITS; pObject->Controlled_Variable_Units = UNITS_NO_UNITS;
pObject->Proportional_Constant = 1.0f;
pObject->Proportional_Constant_Units = UNITS_NO_UNITS; pObject->Proportional_Constant_Units = UNITS_NO_UNITS;
pObject->Integral_Constant = 0.2f;
pObject->Integral_Constant_Units = UNITS_NO_UNITS; pObject->Integral_Constant_Units = UNITS_NO_UNITS;
pObject->Derivative_Constant = 0.05f;
pObject->Derivative_Constant_Units = UNITS_NO_UNITS; pObject->Derivative_Constant_Units = UNITS_NO_UNITS;
pObject->Action = ACTION_DIRECT; pObject->Action = ACTION_DIRECT;
pObject->Maximum_Output = FLT_MAX; pObject->Update_Interval = 1000;
pObject->Minimum_Output = FLT_MIN; /* set the references to self */
Object_Property_Reference_Set_Empty( Object_Property_Reference_Set(
&pObject->Manipulated_Property_Reference); &pObject->Manipulated_Variable_Reference, OBJECT_LOOP, object_instance,
Object_Property_Reference_Set_Empty( PROP_CONTROLLED_VARIABLE_VALUE, BACNET_ARRAY_ALL);
&pObject->Controlled_Variable_Reference); Object_Property_Reference_Set(
Object_Property_Reference_Set_Empty(&pObject->Setpoint_Reference); &pObject->Controlled_Variable_Reference, OBJECT_LOOP, object_instance,
PROP_CONTROLLED_VARIABLE_VALUE, BACNET_ARRAY_ALL);
Object_Property_Reference_Set(
&pObject->Setpoint_Reference, OBJECT_LOOP, object_instance,
PROP_SETPOINT, BACNET_ARRAY_ALL);
pObject->Priority_For_Writing = BACNET_MAX_PRIORITY; pObject->Priority_For_Writing = BACNET_MAX_PRIORITY;
pObject->COV_Increment = 1.0f; pObject->COV_Increment = 1.0f;
pObject->Description = NULL; pObject->Description = NULL;